core: move SIP transport auth type to public API
[siplcs.git] / src / miranda / miranda-plugin.c
blob0dd341b04c94279e7bfb26f9ef5cc4d8c006e3db
1 /**
2 * @file miranda-plugin.c
4 * pidgin-sipe
6 * Copyright (C) 2010-12 SIPE Project <http://sipe.sourceforge.net/>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #pragma comment(lib, "Secur32.lib")
24 #ifdef HAVE_LIBKRB5
25 #pragma comment(lib, "krb5_32.lib")
26 #pragma comment(lib, "gssapi32.lib")
27 #pragma comment(lib, "comerr32.lib")
28 #endif
30 #include <windows.h>
31 #include <Windowsx.h>
32 #include <win2k.h>
33 #include <Richedit.h>
34 #include <stdio.h>
36 #include <glib.h>
38 #include "miranda-version.h"
39 #include "newpluginapi.h"
40 #include "m_protosvc.h"
41 #include "m_protoint.h"
42 #include "m_protomod.h"
43 #include "m_system.h"
44 #include "m_database.h"
45 #include "m_options.h"
46 #include "m_netlib.h"
47 #include "m_chat.h"
48 #include "m_clist.h"
49 #include "m_langpack.h"
50 #include "m_message.h"
51 #include "m_genmenu.h"
53 #include "sipe-common.h"
54 #include "sipe-backend.h"
55 #include "sipe-core.h"
56 #include "sipe-nls.h"
58 #include "miranda-private.h"
59 #include "miranda-resource.h"
61 /* FIXME: Not here */
62 void CreateProtoService(const SIPPROTO *pr, const char* szService, SipSimpleServiceFunc serviceProc);
64 HANDLE sipe_miranda_incoming_netlibuser = NULL;
65 CRITICAL_SECTION sipe_miranda_debug_CriticalSection;
67 gchar *sipe_backend_version(void)
69 char version[200];
71 if (CallService(MS_SYSTEM_GETVERSIONTEXT, sizeof(version), (LPARAM)version)) {
72 strcpy(version, "Unknown");
75 return g_strdup_printf("Miranda %s SIPLCS " __DATE__ " " __TIME__, version );
79 * Miranda globals
81 * Global variables related to miranda core or UI
83 static BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0;
84 HINSTANCE hInst;
85 PLUGINLINK* pluginLink;
86 struct MM_INTERFACE mmi;
89 * Dialog boxes
91 static void
92 EnableDlgItem(HWND hwndDlg, UINT control, gboolean enable)
94 EnableWindow(GetDlgItem(hwndDlg, control), enable);
97 static void
98 CheckDlgItem(HWND hwndDlg, UINT control, int state)
100 Button_SetCheck(GetDlgItem(hwndDlg, control), state);
103 INT_PTR CALLBACK DlgProcSipSimpleOptsAbout(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
106 switch(msg)
108 case WM_INITDIALOG:
110 SIPPROTO *pr = (SIPPROTO *)lParam;
111 SETTEXTEX tex;
112 gchar *tmp, *about;
113 LOCK;
114 tmp = sipe_core_about();
115 about = sipe_miranda_html2rtf(tmp);
116 g_free(tmp);
117 UNLOCK;
119 TranslateDialogDefault(hwndDlg);
121 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
123 tex.flags = ST_DEFAULT;
124 tex.codepage = 437;
126 SendDlgItemMessage(hwndDlg, IDC_ABOUTSIPE, EM_SETTEXTEX, (WPARAM)&tex, (LPARAM)about );
128 g_free(about);
132 return FALSE;
135 static INT_PTR CALLBACK DlgProcSipSimpleOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
137 static int lock=0;
139 switch(msg)
141 case WM_INITDIALOG:
143 const SIPPROTO *pr = (const SIPPROTO *)lParam;
144 char *str;
145 gboolean state;
146 WORD iptype;
148 TranslateDialogDefault(hwndDlg);
150 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
152 lock++;
154 state = sipe_miranda_getBool(pr, "sso", FALSE);
155 if (state)
157 CheckDlgItem(hwndDlg, IDC_USESSO, BST_CHECKED);
158 EnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);
159 EnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);
160 } else {
161 CheckDlgItem(hwndDlg, IDC_USESSO, BST_UNCHECKED);
162 EnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);
163 EnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);
166 state = sipe_miranda_getBool(pr, "krb5", FALSE);
167 if (state)
168 CheckDlgItem(hwndDlg, IDC_USEKRB, BST_CHECKED);
169 else
170 CheckDlgItem(hwndDlg, IDC_USEKRB, BST_UNCHECKED);
172 str = sipe_miranda_getString(pr, "username");
173 SetDlgItemTextA(hwndDlg, IDC_HANDLE, str);
174 SendDlgItemMessage(hwndDlg, IDC_HANDLE, EM_SETLIMITTEXT, 50, 0);
175 mir_free(str);
177 str = sipe_miranda_getString(pr, "login");
178 SetDlgItemTextA(hwndDlg, IDC_LOGIN, str);
179 SendDlgItemMessage(hwndDlg, IDC_LOGIN, EM_SETLIMITTEXT, 50, 0);
180 mir_free(str);
182 str = sipe_miranda_getString(pr, "password");
183 if (str) CallService(MS_DB_CRYPT_DECODESTRING, strlen(str),(LPARAM)str);
184 SetDlgItemTextA(hwndDlg, IDC_PASSWORD, str);
185 SendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_SETLIMITTEXT, 16, 0);
186 mir_free(str);
188 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("Auto"));
189 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("SSL/TLS"));
190 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("TCP"));
192 str = sipe_miranda_getString(pr, "transport");
193 if (!str || !strcmp(str, "auto"))
194 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("Auto"));
195 else if (!strcmp(str, "tls"))
196 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("SSL/TLS"));
197 else if (!strcmp(str, "tcp"))
198 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("TCP"));
200 str = sipe_miranda_getGlobalString("public_ip");
201 SetDlgItemTextA(hwndDlg, IDC_PUBLICIP, str);
202 SendDlgItemMessage(hwndDlg, IDC_PUBLICIP, EM_SETLIMITTEXT, 20, 0);
203 mir_free(str);
205 str = sipe_miranda_getGlobalString("ipprog");
206 SetDlgItemTextA(hwndDlg, IDC_IPPROGEXE, str);
207 SendDlgItemMessage(hwndDlg, IDC_IPPROGEXE, EM_SETLIMITTEXT, 60, 0);
208 mir_free(str);
210 str = sipe_miranda_get_local_ip();
211 SetDlgItemTextA(hwndDlg, IDC_IPLOCALFOUND, str);
213 sipe_miranda_getGlobalWord("iptype", &iptype);
214 if (iptype == SIPE_MIRANDA_IP_LOCAL)
216 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPLOCAL);
217 EnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);
218 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);
219 } else if (iptype == SIPE_MIRANDA_IP_MANUAL) {
220 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPMANUAL);
221 EnableDlgItem(hwndDlg, IDC_PUBLICIP, TRUE);
222 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);
223 } else {
224 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPPROG);
225 EnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);
226 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, TRUE);
229 lock--;
230 return TRUE;
233 case WM_COMMAND:
235 int code = wParam >> 16;
236 int id = wParam & 0xffff;
238 if (LOWORD(wParam) == IDC_IPLOCAL)
240 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPLOCAL);
241 EnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);
242 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);
243 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
244 } else if (LOWORD(wParam) == IDC_IPMANUAL) {
245 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPMANUAL);
246 EnableDlgItem(hwndDlg, IDC_PUBLICIP, TRUE);
247 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);
248 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
249 } else if (LOWORD(wParam) == IDC_IPPROG) {
250 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPPROG);
251 EnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);
252 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, TRUE);
253 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
254 } else if (LOWORD(wParam) == IDC_USEKRB) {
255 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
256 } else if (LOWORD(wParam) == IDC_USESSO) {
257 if (IsDlgButtonChecked(hwndDlg, IDC_USESSO) == BST_CHECKED)
259 EnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);
260 EnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);
261 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
262 } else {
263 CheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_MSO);
264 EnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);
265 EnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);
267 } else if (!lock && (code == EN_CHANGE || code == CBN_SELCHANGE)) {
268 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
270 return TRUE;
273 case WM_NOTIFY:
275 if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
277 char buf[100];
278 TCHAR tbuf[100];
280 const SIPPROTO *pr = (const SIPPROTO *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
282 GetDlgItemTextA(hwndDlg, IDC_HANDLE, buf, sizeof(buf));
283 sipe_miranda_setString(pr, "username", buf);
285 GetDlgItemTextA(hwndDlg, IDC_LOGIN, buf, sizeof(buf));
286 sipe_miranda_setString(pr, "login", buf);
288 GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf));
289 CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf),(LPARAM)buf);
290 sipe_miranda_setString(pr, "password", buf);
292 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, WM_GETTEXT, 100, (LPARAM)tbuf );
294 if (!_tcscmp(tbuf, _T("Auto")))
295 sipe_miranda_setString(pr, "transport", "auto");
296 else if (!_tcscmp(tbuf, _T("SSL/TLS")))
297 sipe_miranda_setString(pr, "transport", "tls");
298 else if (!_tcscmp(tbuf, _T("TCP")))
299 sipe_miranda_setString(pr, "transport", "tcp");
301 GetDlgItemTextA(hwndDlg, IDC_PUBLICIP, buf, sizeof(buf));
302 sipe_miranda_setGlobalString("public_ip", buf);
304 GetDlgItemTextA(hwndDlg, IDC_IPPROGEXE, buf, sizeof(buf));
305 sipe_miranda_setGlobalString("ipprog", buf);
307 if (IsDlgButtonChecked(hwndDlg, IDC_USEKRB) == BST_CHECKED)
309 sipe_miranda_setBool(pr, "krb5", TRUE);
310 } else {
311 sipe_miranda_setBool(pr, "krb5", FALSE);
314 if (IsDlgButtonChecked(hwndDlg, IDC_IPLOCAL) == BST_CHECKED)
316 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_LOCAL);
317 } else if (IsDlgButtonChecked(hwndDlg, IDC_IPMANUAL) == BST_CHECKED) {
318 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_MANUAL);
319 } else {
320 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_PROG);
322 return TRUE;
324 return TRUE;
329 return FALSE;
332 INT_PTR CALLBACK DlgProcAccMgrUI(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
334 switch(msg)
336 case WM_INITDIALOG:
338 const SIPPROTO *pr = (const SIPPROTO *)lParam;
339 char *str;
340 gboolean sso;
342 TranslateDialogDefault(hwndDlg);
344 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
346 sso = sipe_miranda_getBool(pr, "sso", FALSE);
347 if (sso)
349 CheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_SSO);
350 EnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);
351 EnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);
352 } else {
353 CheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_MSO);
354 EnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);
355 EnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);
358 str = sipe_miranda_getString(pr, "username");
359 SetDlgItemTextA(hwndDlg, IDC_HANDLE, str);
360 mir_free(str);
362 str = sipe_miranda_getString(pr, "login");
363 SetDlgItemTextA(hwndDlg, IDC_LOGIN, str);
364 mir_free(str);
366 str = sipe_miranda_getString(pr, "password");
367 if (str) CallService(MS_DB_CRYPT_DECODESTRING, strlen(str),(LPARAM)str);
368 SetDlgItemTextA(hwndDlg, IDC_PASSWORD, str);
369 mir_free(str);
371 SendDlgItemMessage(hwndDlg, IDC_HANDLE, EM_SETLIMITTEXT, 50, 0);
372 SendDlgItemMessage(hwndDlg, IDC_LOGIN, EM_SETLIMITTEXT, 50, 0);
373 SendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_SETLIMITTEXT, 16, 0);
375 return TRUE;
378 case WM_COMMAND:
379 if (LOWORD(wParam) == IDC_SSO)
381 EnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);
382 EnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);
383 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
384 } else if (LOWORD(wParam) == IDC_MSO) {
385 EnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);
386 EnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);
387 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
388 } else if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus()) {
389 switch(LOWORD(wParam))
391 case IDC_HANDLE:
392 case IDC_LOGIN:
393 case IDC_PASSWORD:
394 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
395 break;
398 break;
400 case WM_NOTIFY:
401 if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
403 char buf[100];
405 const SIPPROTO *pr = (const SIPPROTO *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
407 if (IsDlgButtonChecked(hwndDlg, IDC_SSO) == BST_CHECKED)
409 sipe_miranda_setBool(pr, "sso", TRUE);
410 } else {
411 sipe_miranda_setBool(pr, "sso", FALSE);
414 GetDlgItemTextA(hwndDlg, IDC_HANDLE, buf, sizeof(buf));
415 sipe_miranda_setString(pr, "username", buf);
417 GetDlgItemTextA(hwndDlg, IDC_LOGIN, buf, sizeof(buf));
418 sipe_miranda_setString(pr, "login", buf);
420 GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf));
421 CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf),(LPARAM)buf);
422 sipe_miranda_setString(pr, "password", buf);
424 return TRUE;
426 break;
429 return FALSE;
434 * Miranda service support functions
436 * Functions called by our service functions
438 static void fix_contact_groups(SIPPROTO *pr)
440 GSList *contacts = sipe_miranda_buddy_find_all(pr, NULL, NULL);
441 char *group;
443 CONTACTS_FOREACH(contacts)
444 group = DBGetString(hContact, "CList", "Group");
445 sipe_miranda_setContactString(pr, hContact, "Group", group);
446 mir_free(group);
447 CONTACTS_FOREACH_END
451 static INT_PTR sipe_miranda_start_chat(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
453 HANDLE hContact = (HANDLE)wParam;
454 struct sipe_core_public *sipe_public = pr->sip;
456 DBVARIANT dbv;
457 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
458 LOCK;
459 sipe_core_buddy_new_chat(sipe_public, dbv.pszVal);
460 UNLOCK;
461 DBFreeVariant( &dbv );
462 return TRUE;
465 return FALSE;
468 static void OnModulesLoaded(SIPPROTO *pr)
470 TCHAR descr[MAX_PATH];
471 NETLIBUSER nlu = {0};
472 GCREGISTER gcr;
473 DBEVENTTYPEDESCR eventType = {0};
475 SIPE_DEBUG_INFO_NOFORMAT("OnEvent::OnModulesLoaded");
477 nlu.cbSize = sizeof(nlu);
478 nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_TCHAR;
479 nlu.szSettingsModule = pr->proto.m_szModuleName;
480 _sntprintf(descr, SIZEOF(descr), TranslateT("%s server connection"), pr->proto.m_tszUserName );
481 nlu.ptszDescriptiveName = descr;
483 pr->m_hServerNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
485 gcr.cbSize = sizeof(gcr);
486 gcr.dwFlags = 0;
487 gcr.pszModule = pr->proto.m_szModuleName;
488 gcr.pszModuleDispName = "Sip/Simple";
489 gcr.iMaxText = 0;
490 gcr.nColors = 0;
492 if (CallService(MS_GC_REGISTER, 0, (LPARAM)&gcr))
494 SIPE_DEBUG_INFO_NOFORMAT("OnEvent::OnModulesLoaded Failed to register chat");
497 // Register custom database events
498 eventType.cbSize = DBEVENTTYPEDESCR_SIZE;
499 eventType.module = pr->proto.m_szModuleName;
500 eventType.eventType = SIPE_EVENTTYPE_ERROR_NOTIFY;
501 eventType.descr = "Message error notification";
502 eventType.textService = SIPE_DB_GETEVENTTEXT_ERROR_NOTIFY;
503 eventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
504 // for now keep default "message" icon
505 CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);
507 eventType.cbSize = DBEVENTTYPEDESCR_SIZE;
508 eventType.module = pr->proto.m_szModuleName;
509 eventType.eventType = SIPE_EVENTTYPE_INFO_NOTIFY;
510 eventType.descr = "Message info notification";
511 eventType.textService = SIPE_DB_GETEVENTTEXT_INFO_NOTIFY;
512 eventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
513 // for now keep default "message" icon
514 CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);
516 eventType.cbSize = DBEVENTTYPEDESCR_SIZE;
517 eventType.module = pr->proto.m_szModuleName;
518 eventType.eventType = SIPE_EVENTTYPE_IM_TOPIC;
519 eventType.descr = "Chat topic set";
520 eventType.textService = SIPE_DB_GETEVENTTEXT_IM_TOPIC;
521 eventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
522 // for now keep default "message" icon
523 CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);
527 int OnOptionsInit(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
529 OPTIONSDIALOGPAGE odp = {0};
530 HMODULE hUxTheme = 0;
532 if (IsWinVerXPPlus())
534 hUxTheme = GetModuleHandleA("uxtheme.dll");
535 if (hUxTheme)
536 pfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
539 odp.cbSize = sizeof(odp);
540 odp.position = -800000000;
541 odp.hInstance = hInst;
542 odp.ptszGroup = LPGENT("Network");
543 odp.dwInitParam = (LPARAM)pr;
544 odp.ptszTitle = pr->proto.m_tszUserName;
545 odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
547 odp.ptszTab = LPGENT("Account");
548 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE);
549 odp.pfnDlgProc = DlgProcSipSimpleOpts;
550 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
552 odp.ptszTab = LPGENT("About");
553 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE_ABOUT);
554 odp.pfnDlgProc = DlgProcSipSimpleOptsAbout;
555 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
557 #if 0
559 odp.ptszTab = LPGENT("Features");
560 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQFEATURES);
561 odp.pfnDlgProc = DlgProcIcqFeaturesOpts;
562 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
564 odp.ptszTab = LPGENT("Privacy");
565 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQPRIVACY);
566 odp.pfnDlgProc = DlgProcIcqPrivacyOpts;
567 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
569 if (bPopUpService)
571 odp.position = 100000000;
572 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUPS);
573 odp.groupPosition = 900000000;
574 odp.pfnDlgProc = DlgProcIcqPopupOpts;
575 odp.ptszGroup = LPGENT("Popups");
576 odp.ptszTab = NULL;
577 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
579 #endif
580 return 0;
583 void sipe_miranda_close(SIPPROTO *pr)
585 struct sipe_core_public *sipe_public = pr->sip;
587 if (sipe_public) {
588 LOCK;
589 sipe_core_deallocate(sipe_public);
590 pr->sip = NULL;
591 UNLOCK;
593 // sipe_purple_chat_destroy_rejoin(purple_private);
594 // g_free(purple_private);
598 void set_buddies_offline(const SIPPROTO* pr)
600 HANDLE hContact;
602 hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
603 while (hContact) {
604 char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
605 if (szProto != NULL && !lstrcmpA(szProto, pr->proto.m_szModuleName)) {
606 if (DBGetContactSettingByte(hContact, pr->proto.m_szModuleName, "ChatRoom", 0) == 0)
607 DBWriteContactSettingWord(hContact, pr->proto.m_szModuleName, "Status", ID_STATUS_OFFLINE);
609 hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
613 int __stdcall show_vlc(void *data);
614 void sipe_miranda_login(SIPPROTO *pr) {
615 gchar *username = sipe_miranda_getString(pr, "username");
616 gchar *login = sipe_miranda_getString(pr, "login");
617 gchar *email = sipe_miranda_getString(pr, "email");
618 gchar *email_url = sipe_miranda_getString(pr, "email_url");
619 gchar **domain_user = g_strsplit_set(login, "/\\", 2);
620 const gchar *errmsg;
621 gchar *password;
622 gchar *tmp = (char*)mir_calloc(1024);
623 int tmpstatus;
624 int ttype;
625 guint authentication_type;
626 struct sipe_core_public *sipe_public;
628 // CloseHandle((HANDLE) mir_forkthreadex(show_vlc, NULL, 65536, NULL));
630 if (sipe_miranda_getStaticString(pr, NULL, "password", tmp, 1024 )) tmp[0] = '\0';
631 CallService(MS_DB_CRYPT_DECODESTRING, sizeof(tmp),(LPARAM)tmp);
632 password = g_strdup(tmp);
633 mir_free(tmp);
635 LOCK;
636 pr->sip = sipe_core_allocate(username,
637 domain_user[0], domain_user[0] != NULL ? domain_user[1] : "",
638 password,
639 email,
640 email_url,
641 &errmsg);
642 if (pr->sip) pr->sip->backend_private = pr;
643 sipe_public = pr->sip;
644 UNLOCK;
646 mir_free(username);
647 mir_free(login);
648 mir_free(email);
649 mir_free(email_url);
650 g_strfreev(domain_user);
651 g_free(password);
653 if (!pr->sip) {
654 sipe_miranda_connection_error_reason(pr,
655 SIPE_CONNECTION_ERROR_INVALID_USERNAME,
656 errmsg);
657 return;
660 //sipe_miranda_chat_setup_rejoin(pr);
662 /* default is NTLM */
663 authentication_type = SIPE_AUTHENTICATION_TYPE_NTLM;
664 #ifdef HAVE_LIBKRB5
665 if (sipe_miranda_getBool(pr, "krb5", FALSE))
666 authentication_type = SIPE_AUTHENTICATION_TYPE_KERBEROS;
667 #endif
668 /* TODO: configuration option for TLS-DSK? */
670 // /* @TODO: is this correct?
671 // "sso" is only available when Kerberos support is compiled in */
672 if (sipe_miranda_getBool(pr, "sso", FALSE))
673 SIPE_CORE_FLAG_SET(SSO);
675 /* Set display name */
676 sipe_miranda_setStringUtf(pr, "Nick", pr->sip->sip_name);
678 /* Update connection progress */
679 tmpstatus = pr->proto.m_iStatus;
680 pr->proto.m_iStatus = ID_STATUS_CONNECTING;
681 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)tmpstatus, ID_STATUS_CONNECTING);
683 tmp = sipe_miranda_getString(pr, "transport");
684 if (sipe_strequal(tmp, "auto")) {
685 ttype = SIPE_TRANSPORT_AUTO;
686 } else if (sipe_strequal(tmp, "tls")) {
687 ttype = SIPE_TRANSPORT_TLS;
688 } else {
689 ttype = SIPE_TRANSPORT_TCP;
691 mir_free(tmp);
693 LOCK;
694 sipe_core_transport_sip_connect(pr->sip,
695 ttype,
696 authentication_type,
697 NULL,
698 NULL);
699 UNLOCK;
702 void sipsimple_search_contact_cb( GList *columns, GList *results, GHashTable *opts, void *data )
704 SIPPROTO *pr = (SIPPROTO *)data;
705 GList *row, *col;
706 HANDLE hProcess = g_hash_table_lookup(opts, "searchid");
707 PROTOSEARCHRESULT psr = { 0 };
709 psr.cbSize = sizeof(psr);
711 row = results;
712 while (row)
714 gchar **name;
716 col = (GList*)row->data;
717 psr.id = (PROTOCHAR*)col->data;
719 col = g_list_next(col);
720 name = g_strsplit_set(col->data, ",", 2);
721 psr.nick = (FNAMECHAR*)col->data;
722 psr.firstName = (PROTOCHAR*)(name[0] ? name[1] : NULL);
723 psr.lastName = (PROTOCHAR*)name[0];
725 col = g_list_next(col);
726 /* company */
728 col = g_list_next(col);
729 /* country */
731 col = g_list_next(col);
732 psr.email = (PROTOCHAR*)col->data;
734 row = g_list_next(row);
735 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, hProcess, (LPARAM) & psr);
736 g_strfreev(name);
739 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hProcess, 0);
743 static int OnGroupChange(SIPPROTO *pr, WPARAM w, LPARAM l )
745 CLISTGROUPCHANGE *gi = (CLISTGROUPCHANGE*)l;
746 HANDLE hContact = (HANDLE)w;
747 DBVARIANT dbv;
749 /* No contact => it's a group add/rename/remove */
750 if (!hContact)
752 gchar *oldname, *newname;
754 /* No old name => add */
755 if (!gi->pszOldName)
757 return 0;
759 /* No new name => delete */
760 else if (!gi->pszNewName)
762 SIPE_DEBUG_INFO("Removing group <%ls>", gi->pszOldName);
763 oldname = mir_t2a(gi->pszOldName);
764 LOCK;
765 sipe_core_group_remove(pr->sip, oldname);
766 UNLOCK;
767 mir_free(oldname);
768 return 0;
771 SIPE_DEBUG_INFO("Renaming group <%S> to <%S>", gi->pszOldName, gi->pszNewName);
772 oldname = mir_t2a(gi->pszOldName);
773 newname = mir_t2a(gi->pszNewName);
774 LOCK;
775 sipe_core_group_rename(pr->sip, oldname, newname);
776 UNLOCK;
777 mir_free(oldname);
778 mir_free(newname);
779 return 0;
782 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
783 gchar *oldgroup;
784 gchar *who = g_strdup(dbv.pszVal);
785 DBFreeVariant( &dbv );
787 if (oldgroup = sipe_miranda_getContactString(pr, hContact, "Group"))
789 SIPE_DEBUG_INFO("Moving buddy <%s> from group <%ls> to group <%ls>", who, oldgroup, gi->pszNewName);
790 LOCK;
791 sipe_core_buddy_group(pr->sip, who, oldgroup, TCHAR2CHAR(gi->pszNewName));
792 UNLOCK;
793 mir_free(oldgroup);
794 } else {
795 gchar *name = mir_t2a(gi->pszNewName);
797 if (!g_str_has_prefix(name, "sip:")) {
798 gchar *newname = sip_uri_from_name(name);
799 mir_free(name);
800 name = mir_strdup(newname);
801 g_free(newname);
804 SIPE_DEBUG_INFO("Really adding buddy <%s> to list in group <%s>", who, name);
805 LOCK;
806 sipe_core_buddy_add(pr->sip, who, name);
807 UNLOCK;
808 mir_free(name);
811 g_free(who);
814 return TRUE;
817 static int sipe_miranda_build_chat_menu(SIPPROTO *pr, WPARAM w, LPARAM lParam )
819 GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;
821 if (gcmi->Type == MENU_ON_NICKLIST)
823 static struct gc_item Item[] = {
824 {"&Make Leader", 1, MENU_ITEM, FALSE},
827 gcmi->nItems = sizeof(Item)/sizeof(Item[0]);
828 gcmi->Item = &Item[0];
831 return 0;
834 static int OnChatEvent(SIPPROTO *pr, WPARAM w, LPARAM l )
836 GCHOOK *hook = (GCHOOK*)l;
837 GCDEST *dst = hook->pDest;
839 if (dst->iType == GC_USER_MESSAGE) {
840 GCDEST gcd = {0};
841 GCEVENT gce = {0};
842 struct sipe_chat_session *session;
844 gcd.pszModule = pr->proto.m_szModuleName;
845 gcd.pszID = dst->pszID;
846 gcd.iType = GC_EVENT_GETITEMDATA;
848 gce.cbSize = sizeof(gce);
849 gce.pDest = &gcd;
852 if ((session = (struct sipe_chat_session*)CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)
854 SIPE_DEBUG_WARNING_NOFORMAT("Failed to get chat session");
855 return 0;
858 LOCK;
859 sipe_core_chat_send(pr->sip, session, hook->pszText);
860 UNLOCK;
862 return TRUE;
863 } else if (dst->iType == GC_USER_PRIVMESS) {
864 } else if (dst->iType == GC_USER_NICKLISTMENU) {
865 if (hook->dwData == 1)
867 SIPE_DEBUG_INFO("make leader <%s>", hook->pszUID);
871 return FALSE;
874 int OnPreBuildContactMenu(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
876 HANDLE hContact = (HANDLE)wParam;
877 int chatcount = CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)pr->proto.m_szModuleName);
878 int idx;
879 CLISTMENUITEM mi = {0};
880 GC_INFO gci = {0};
881 gpointer tmp;
883 mi.cbSize = sizeof(mi);
884 gci.pszModule = pr->proto.m_szModuleName;
886 /* Remove the old list */
887 while (pr->contactMenuChatItems)
889 SIPE_DEBUG_INFO("Removing old menuitem <%08x>", pr->contactMenuChatItems->data);
890 CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)pr->contactMenuChatItems->data, 0);
891 pr->contactMenuChatItems = g_slist_remove(pr->contactMenuChatItems, pr->contactMenuChatItems->data);
894 /* Add the main entry */
895 mi.pszName = "Invite to chat";
896 mi.flags = CMIF_NOTOFFLINE;
897 mi.position = 20;
898 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
899 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
901 mi.pszName = "New chat";
902 mi.hParentMenu = pr->contactMenuChatItems->data;
903 mi.flags = CMIF_ROOTHANDLE;
904 mi.popupPosition = 0;
905 mi.position=-10;
906 mi.pszService = g_strdup_printf("%s/StartChat", pr->proto.m_szModuleName);
907 mi.pszContactOwner = pr->proto.m_szModuleName;
908 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
909 g_free(mi.pszService);
910 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
912 for (idx=0 ; idx<chatcount ; idx++)
914 SIPE_DEBUG_INFO("Chat <%d> Menuitem <%08x>", idx, pr->contactMenuChatItems);
915 gci.iItem = idx;
916 gci.Flags = BYINDEX | NAME | ID;
917 if(!CallServiceSync( MS_GC_GETINFO, 0, (LPARAM)&gci )) {
918 SIPE_DEBUG_INFO("Chat <%s>", gci.pszName);
920 mi.pszName = gci.pszName;
921 mi.hParentMenu = pr->contactMenuChatItems->data;
922 mi.flags = CMIF_ROOTHANDLE;
923 mi.popupPosition = g_strdup(gci.pszID);
924 mi.position = idx;
925 mi.pszService = g_strdup_printf("%s/InviteToChat", pr->proto.m_szModuleName);
926 mi.pszContactOwner = pr->proto.m_szModuleName;
927 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
928 g_free(mi.pszService);
929 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
933 return 0;
936 INT_PTR SvcCreateAccMgrUI(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
938 return (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ACCMGRUI), (HWND)lParam, DlgProcAccMgrUI, (LPARAM)pr);
943 * Miranda service functions
945 * The functions in our plugin that get called directly by core Miranda
947 static DWORD_PTR GetCaps( SIPPROTO *pr, int type, HANDLE hContact )
949 switch (type) {
950 case PFLAGNUM_1:
951 return PF1_IM | PF1_CHAT | PF1_FILE | PF1_MODEMSG
952 | PF1_SERVERCLIST | PF1_ADDED
953 | PF1_BASICSEARCH | PF1_ADDSEARCHRES
954 | PF1_SEARCHBYEMAIL | PF1_USERIDISEMAIL
955 | PF1_SEARCHBYNAME | PF1_EXTSEARCH
958 case PFLAGNUM_2:
959 return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY
960 | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND
961 | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;
963 case PFLAGNUM_3:
964 return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY
965 | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND
966 | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;
968 case PFLAGNUM_4:
969 return PF4_NOCUSTOMAUTH | PF4_IMSENDUTF | PF4_SUPPORTTYPING
970 | PF4_SUPPORTIDLE;
972 case PFLAGNUM_5:
973 return 0;
975 case PFLAG_UNIQUEIDSETTING:
976 return (DWORD_PTR) SIP_UNIQUEID;
977 break;
978 default:
979 SIPE_DEBUG_INFO("GetCaps: unknown type <%x>", type);
983 return 0;
986 static HICON GetIcon( SIPPROTO *pr, int iconIndex )
988 SIPE_DEBUG_INFO("GetIcon: unknown index <%x>", iconIndex);
989 return NULL;
992 static int OnEvent( SIPPROTO *pr, PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam )
994 SIPE_DEBUG_INFO("OnEvent: type <%x>", eventType);
996 switch (eventType)
998 case EV_PROTO_ONLOAD:
999 OnModulesLoaded(pr);
1000 break;
1002 case EV_PROTO_ONREADYTOEXIT:
1003 break;
1005 case EV_PROTO_ONEXIT:
1006 break;
1008 case EV_PROTO_ONRENAME:
1009 break;
1011 case EV_PROTO_ONOPTIONS:
1012 return OnOptionsInit( pr, wParam, lParam );
1013 break;
1015 case EV_PROTO_ONERASE:
1016 break;
1020 return 0;
1023 static HANDLE AddToListByEvent( SIPPROTO *pr, int flags, int iContact, HANDLE hDbEvent )
1025 DBEVENTINFO dbei = {0};
1027 dbei.cbSize = sizeof(dbei);
1028 if ((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) == -1)
1029 return 0;
1031 dbei.pBlob = (PBYTE)_alloca(dbei.cbBlob + 1);
1032 dbei.pBlob[dbei.cbBlob] = '\0';
1034 if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei))
1035 return 0; // failed to get event
1037 if (strcmp(dbei.szModule, pr->proto.m_szModuleName))
1038 return 0; // this event is not ours
1040 _NIF();
1041 SIPE_DEBUG_INFO("AddToListByEvent: flags <%x> iContact <%x>", flags, iContact);
1042 return NULL;
1045 static int Authorize( SIPPROTO *pr, HANDLE hContact )
1047 _NIF();
1048 SIPE_DEBUG_INFO_NOFORMAT("Authorize");
1049 return 0;
1052 static int AuthDeny( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szReason )
1054 _NIF();
1055 SIPE_DEBUG_INFO("AuthDeny: reason <%s>", szReason);
1056 return 0;
1059 static int AuthRecv( SIPPROTO *pr, HANDLE hContact, PROTORECVEVENT* evt )
1061 _NIF();
1062 SIPE_DEBUG_INFO_NOFORMAT("AuthRecv");
1063 return 0;
1066 static int AuthRequest( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szMessage )
1068 _NIF();
1069 SIPE_DEBUG_INFO("AuthRequest: message <%s>", szMessage);
1070 return 0;
1073 static HANDLE ChangeInfo( SIPPROTO *pr, int iInfoType, void* pInfoData )
1075 _NIF();
1076 SIPE_DEBUG_INFO("ChangeInfo: infotype <%x>", iInfoType);
1077 return NULL;
1080 static int FileCancel( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer )
1082 _NIF();
1083 SIPE_DEBUG_INFO_NOFORMAT("FileCancel");
1084 return 0;
1087 static int FileResume( SIPPROTO *pr, HANDLE hTransfer, int* action, const PROTOCHAR** szFilename )
1089 _NIF();
1090 SIPE_DEBUG_INFO("FileResume: action <%x>", action);
1091 return 0;
1094 static HANDLE SearchBasic( SIPPROTO *pr, const PROTOCHAR* id )
1096 return NULL;
1099 static HWND CreateExtendedSearchUI( SIPPROTO *pr, HWND owner )
1101 return CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SEARCHUI), (HWND)owner, NULL, (LPARAM)pr);
1104 static HANDLE AddToList( SIPPROTO *pr, int flags, PROTOSEARCHRESULT* psr )
1106 HANDLE hContact;
1107 gchar *id = g_strdup(TCHAR2CHAR(psr->id));
1109 /* Prepend sip: if needed */
1110 if (strncmp("sip:", id, 4)) {
1111 gchar *tmp = id;
1112 id = sip_uri_from_name(tmp);
1113 g_free(tmp);
1116 hContact = sipe_miranda_buddy_find(pr, id, NULL);
1117 if (hContact) {
1118 g_free(id);
1119 return hContact;
1122 hContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );
1123 CallService( MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)pr->proto.m_szModuleName );
1124 sipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, id ); // name
1125 if (psr->nick)
1127 /* server_alias */
1128 gchar *tmp = mir_t2a(psr->nick);
1129 sipe_miranda_setContactStringUtf( pr, hContact, "Nick", tmp );
1130 mir_free(tmp);
1133 g_free(id);
1134 return hContact;
1138 sipe_miranda_window_closed(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
1140 MessageWindowEventData* evt = (MessageWindowEventData*)lParam;
1142 SIPE_DEBUG_INFO("contact <%08x> module <%s> type <%02x> flags <%02x>",
1143 evt->hContact, evt->szModule, evt->uType, evt->uFlags);
1145 return 0;
1148 static int
1149 sipe_miranda_invite_to_chat(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
1151 HANDLE hContact = (HANDLE)wParam;
1152 gchar *id = (gchar*)lParam;
1153 GCDEST gcd = {0};
1154 GCEVENT gce = {0};
1155 struct sipe_chat_session *session;
1156 gchar *uid;
1158 gcd.pszModule = pr->proto.m_szModuleName;
1159 gcd.pszID = id;
1160 gcd.iType = GC_EVENT_GETITEMDATA;
1162 gce.cbSize = sizeof(gce);
1163 gce.pDest = &gcd;
1165 if ((session = (struct sipe_chat_session*)CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)
1167 SIPE_DEBUG_WARNING_NOFORMAT("Failed to get chat session");
1168 return 0;
1171 uid = sipe_miranda_getContactString(pr, hContact, SIP_UNIQUEID);
1172 sipe_core_chat_invite(pr->sip, session, uid);
1174 mir_free(uid);
1175 g_free(id);
1176 return 0;
1180 * Main Miranda interface
1182 * The structures and functions that allow Miranda to recovnize and load
1183 * our plugin.
1186 /* Plugin information structure */
1187 PLUGININFOEX pluginInfo = {
1188 sizeof(PLUGININFOEX),
1189 "Office Communicator Protocol",
1190 PLUGIN_MAKE_VERSION(0,11,2,1),
1191 "Support for Microsoft Office Communicator",
1192 "Miranda support by Jochen De Smet, for core sipe support see homepage",
1193 "jochen.libsipe@leahnim.org",
1194 "(C)2009-2011",
1195 "https://sourceforge.net/projects/sipe",
1196 UNICODE_AWARE,
1197 0, //doesn't replace anything built-in
1198 #if defined( _UNICODE )
1199 { 0x842395ed, 0x4e56, 0x40e5, { 0x94, 0x25, 0x28, 0x29, 0xd8, 0xab, 0xae, 0xa5 } } // {842395ED-4E56-40e5-9425-2829D8ABAEA5}
1200 #else
1201 { 0x1ef8af37, 0xdec1, 0x4757, { 0x89, 0x78, 0xe8, 0xad, 0xd0, 0xd8, 0x6e, 0x7f } } // {1EF8AF37-DEC1-4757-8978-E8ADD0D86E7F}
1202 #endif
1205 __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
1207 // Only load for 0.8.0.29 or greater
1208 // We need the core stubs for PS_GETNAME and PS_GETSTATUS
1209 if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 9, 0, 0))
1211 MessageBoxA(
1212 NULL,
1213 "SIP/Simple plugin cannot be loaded. It requires Miranda IM 0.9.0.0 or later.",
1214 "SIP/Simple Plugin",
1215 MB_OK | MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST
1217 return NULL;
1220 return &pluginInfo;
1223 static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST};
1224 __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
1226 return interfaces;
1229 static PROTO_INTERFACE* sipsimpleProtoInit( const char* pszProtoName, const TCHAR* tszUserName )
1231 gchar *tmp;
1232 SIPPROTO *pr = (SIPPROTO *)mir_calloc(sizeof(SIPPROTO));
1233 pr->proto.vtbl = (PROTO_INTERFACE_VTBL*)mir_calloc(sizeof(PROTO_INTERFACE_VTBL));
1235 SIPE_DEBUG_INFO("protoname <%s> username <%ls>", pszProtoName, tszUserName);
1237 if (!InitializeCriticalSectionAndSpinCount(&pr->CriticalSection, 0))
1239 SIPE_DEBUG_ERROR_NOFORMAT("Can't initialize critical section");
1240 return NULL;
1243 tmp = sipe_miranda_getString(pr, "transport");
1244 if (!tmp)
1246 sipe_miranda_setString(pr, "transport", "auto");
1247 } else {
1248 mir_free(tmp);
1251 /* To make it easy to detect when a SIPPROTO* isn't a SIPPROTO* */
1252 strncpy(pr->_SIGNATURE, "AbandonAllHope..", sizeof(pr->_SIGNATURE));
1254 pr->main_thread_id = GetCurrentThreadId();
1255 pr->proto.m_iVersion = 2;
1256 pr->proto.m_szModuleName = mir_strdup(pszProtoName);
1257 pr->proto.m_tszUserName = mir_tstrdup(tszUserName);
1258 pr->proto.m_szProtoName = mir_strdup(pszProtoName);
1260 // set_buddies_offline(pr);
1261 fix_contact_groups(pr);
1263 /* Fill the function table */
1264 pr->proto.vtbl->AddToList = AddToList;
1265 pr->proto.vtbl->AddToListByEvent = AddToListByEvent;
1267 pr->proto.vtbl->Authorize = Authorize;
1268 pr->proto.vtbl->AuthDeny = AuthDeny;
1269 pr->proto.vtbl->AuthRecv = AuthRecv;
1270 pr->proto.vtbl->AuthRequest = AuthRequest;
1272 pr->proto.vtbl->ChangeInfo = ChangeInfo;
1274 pr->proto.vtbl->FileAllow = sipe_miranda_FileAllow;
1275 pr->proto.vtbl->FileCancel = FileCancel;
1276 pr->proto.vtbl->FileDeny = sipe_miranda_FileDeny;
1277 pr->proto.vtbl->FileResume = FileResume;
1279 pr->proto.vtbl->GetCaps = GetCaps;
1280 pr->proto.vtbl->GetIcon = GetIcon;
1281 pr->proto.vtbl->GetInfo = sipe_miranda_GetInfo;
1283 pr->proto.vtbl->SearchBasic = SearchBasic;
1284 pr->proto.vtbl->SearchByEmail = sipe_miranda_SearchByEmail;
1285 pr->proto.vtbl->SearchByName = sipe_miranda_SearchByName;
1286 pr->proto.vtbl->SearchAdvanced = sipe_miranda_SearchAdvanced;
1287 pr->proto.vtbl->CreateExtendedSearchUI = CreateExtendedSearchUI;
1289 pr->proto.vtbl->RecvMsg = sipe_miranda_RecvMsg;
1291 pr->proto.vtbl->SendMsg = sipe_miranda_SendMsg;
1293 pr->proto.vtbl->SetStatus = sipe_miranda_SetStatus;
1295 pr->proto.vtbl->GetAwayMsg = sipe_miranda_GetAwayMsg;
1296 pr->proto.vtbl->SetAwayMsg = sipe_miranda_SetAwayMsg;
1298 pr->proto.vtbl->UserIsTyping = sipe_miranda_UserIsTyping;
1300 pr->proto.vtbl->SendFile = sipe_miranda_SendFile;
1301 pr->proto.vtbl->RecvFile = sipe_miranda_RecvFile;
1303 pr->proto.vtbl->OnEvent = OnEvent;
1305 /* Setup services */
1306 CreateProtoService(pr, PS_CREATEACCMGRUI, &SvcCreateAccMgrUI );
1307 CreateProtoService(pr, "/InviteToChat", &sipe_miranda_invite_to_chat);
1308 CreateProtoService(pr, "/StartChat",&sipe_miranda_start_chat);
1310 #define HOOKEVENT(evt,func) HookEventObj(evt, func, pr)
1311 HOOKEVENT(ME_OPT_INITIALISE, &OnOptionsInit);
1312 HOOKEVENT(ME_CLIST_GROUPCHANGE, &OnGroupChange);
1313 HOOKEVENT(ME_GC_EVENT, &OnChatEvent);
1314 HOOKEVENT(ME_CLIST_PREBUILDCONTACTMENU, &OnPreBuildContactMenu);
1315 HOOKEVENT(ME_DB_CONTACT_DELETED, &sipe_miranda_buddy_delete);
1316 HOOKEVENT(ME_MSG_WINDOWEVENT, &sipe_miranda_window_closed);
1317 HOOKEVENT(ME_GC_BUILDMENU, &sipe_miranda_build_chat_menu);
1319 return (PROTO_INTERFACE*)pr;
1322 static int sipsimpleProtoUninit( PROTO_INTERFACE* _pr )
1324 SIPPROTO *pr = (SIPPROTO *)_pr;
1326 DeleteCriticalSection(&pr->CriticalSection);
1328 Netlib_CloseHandle(pr->m_hServerNetlibUser);
1329 mir_free(pr->proto.m_szProtoName);
1330 mir_free(pr->proto.m_szModuleName);
1331 mir_free(pr->proto.m_tszUserName);
1332 mir_free(pr->proto.vtbl);
1333 mir_free(pr);
1335 return 0;
1338 __declspec(dllexport) int Load(PLUGINLINK *link)
1340 PROTOCOLDESCRIPTOR pd = {0};
1341 NETLIBUSER nlu = {0};
1342 char *tmp;
1343 WORD iptype;
1345 pluginLink = link;
1347 sipe_core_init("");
1349 mir_getMMI( &mmi );
1351 /* Register the module */
1352 pd.cbSize = sizeof(pd);
1353 pd.szName = SIPSIMPLE_PROTOCOL_NAME;
1354 pd.type = PROTOTYPE_PROTOCOL;
1355 pd.fnInit = sipsimpleProtoInit;
1356 pd.fnUninit = sipsimpleProtoUninit;
1357 CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
1359 /* Protocolwide netlib user for incoming connections (also abused for logging) */
1360 nlu.cbSize = sizeof(nlu);
1361 nlu.flags = NUF_INCOMING | NUF_TCHAR | NUF_NOOPTIONS;
1362 nlu.szSettingsModule = SIPSIMPLE_PROTOCOL_NAME;
1363 nlu.minIncomingPorts = 10;
1365 InitializeCriticalSectionAndSpinCount(&sipe_miranda_debug_CriticalSection, 0);
1366 sipe_miranda_incoming_netlibuser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
1368 tmp = sipe_miranda_getGlobalString("public_ip");
1369 if (!tmp) {
1370 sipe_miranda_setGlobalString("public_ip", "0.0.0.0");
1371 } else {
1372 mir_free(tmp);
1375 if (!sipe_miranda_getGlobalWord("iptype", &iptype))
1377 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_LOCAL);
1380 return 0;
1383 __declspec(dllexport) int Unload(void)
1385 Netlib_CloseHandle(sipe_miranda_incoming_netlibuser);
1386 sipe_miranda_incoming_netlibuser = NULL;
1387 DeleteCriticalSection(&sipe_miranda_debug_CriticalSection);
1388 sipe_core_destroy();
1389 return 0;
1392 BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
1394 hInst = hinstDLL;
1395 return TRUE;
1399 Local Variables:
1400 mode: c
1401 c-file-style: "bsd"
1402 indent-tabs-mode: t
1403 tab-width: 8
1404 End: