webticket: cache ADFS token
[siplcs.git] / src / miranda / miranda-plugin.c
blob77538c950e5feab0923d5d35a30d8deb695cef3c
1 /**
2 * @file miranda-plugin.c
4 * pidgin-sipe
6 * Copyright (C) 2010-11 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 struct sipe_core_public *sipe_public;
627 // CloseHandle((HANDLE) mir_forkthreadex(show_vlc, NULL, 65536, NULL));
629 if (sipe_miranda_getStaticString(pr, NULL, "password", tmp, 1024 )) tmp[0] = '\0';
630 CallService(MS_DB_CRYPT_DECODESTRING, sizeof(tmp),(LPARAM)tmp);
631 password = g_strdup(tmp);
632 mir_free(tmp);
634 LOCK;
635 pr->sip = sipe_core_allocate(username,
636 domain_user[0], domain_user[0] != NULL ? domain_user[1] : "",
637 password,
638 email,
639 email_url,
640 &errmsg);
641 if (pr->sip) pr->sip->backend_private = pr;
642 sipe_public = pr->sip;
643 UNLOCK;
645 mir_free(username);
646 mir_free(login);
647 mir_free(email);
648 mir_free(email_url);
649 g_strfreev(domain_user);
650 g_free(password);
652 if (!pr->sip) {
653 sipe_miranda_connection_error_reason(pr,
654 SIPE_CONNECTION_ERROR_INVALID_USERNAME,
655 errmsg);
656 return;
659 //sipe_miranda_chat_setup_rejoin(pr);
661 #ifdef HAVE_LIBKRB5
662 if (sipe_miranda_getBool(pr, "krb5", FALSE))
663 SIPE_CORE_FLAG_SET(KRB5);
664 #endif
665 // /* @TODO: is this correct?
666 // "sso" is only available when Kerberos support is compiled in */
667 if (sipe_miranda_getBool(pr, "sso", FALSE))
668 SIPE_CORE_FLAG_SET(SSO);
670 /* Set display name */
671 sipe_miranda_setStringUtf(pr, "Nick", pr->sip->sip_name);
673 /* Update connection progress */
674 tmpstatus = pr->proto.m_iStatus;
675 pr->proto.m_iStatus = ID_STATUS_CONNECTING;
676 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)tmpstatus, ID_STATUS_CONNECTING);
678 tmp = sipe_miranda_getString(pr, "transport");
679 if (sipe_strequal(tmp, "auto")) {
680 ttype = SIPE_TRANSPORT_AUTO;
681 } else if (sipe_strequal(tmp, "tls")) {
682 ttype = SIPE_TRANSPORT_TLS;
683 } else {
684 ttype = SIPE_TRANSPORT_TCP;
686 mir_free(tmp);
688 LOCK;
689 sipe_core_transport_sip_connect(pr->sip,
690 ttype,
691 NULL,
692 NULL);
693 UNLOCK;
696 void sipsimple_search_contact_cb( GList *columns, GList *results, GHashTable *opts, void *data )
698 SIPPROTO *pr = (SIPPROTO *)data;
699 GList *row, *col;
700 HANDLE hProcess = g_hash_table_lookup(opts, "searchid");
701 PROTOSEARCHRESULT psr = { 0 };
703 psr.cbSize = sizeof(psr);
705 row = results;
706 while (row)
708 gchar **name;
710 col = (GList*)row->data;
711 psr.id = (PROTOCHAR*)col->data;
713 col = g_list_next(col);
714 name = g_strsplit_set(col->data, ",", 2);
715 psr.nick = (FNAMECHAR*)col->data;
716 psr.firstName = (PROTOCHAR*)(name[0] ? name[1] : NULL);
717 psr.lastName = (PROTOCHAR*)name[0];
719 col = g_list_next(col);
720 /* company */
722 col = g_list_next(col);
723 /* country */
725 col = g_list_next(col);
726 psr.email = (PROTOCHAR*)col->data;
728 row = g_list_next(row);
729 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, hProcess, (LPARAM) & psr);
730 g_strfreev(name);
733 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hProcess, 0);
737 static int OnGroupChange(SIPPROTO *pr, WPARAM w, LPARAM l )
739 CLISTGROUPCHANGE *gi = (CLISTGROUPCHANGE*)l;
740 HANDLE hContact = (HANDLE)w;
741 DBVARIANT dbv;
743 /* No contact => it's a group add/rename/remove */
744 if (!hContact)
746 gchar *oldname, *newname;
748 /* No old name => add */
749 if (!gi->pszOldName)
751 return 0;
753 /* No new name => delete */
754 else if (!gi->pszNewName)
756 SIPE_DEBUG_INFO("Removing group <%ls>", gi->pszOldName);
757 oldname = mir_t2a(gi->pszOldName);
758 LOCK;
759 sipe_core_group_remove(pr->sip, oldname);
760 UNLOCK;
761 mir_free(oldname);
762 return 0;
765 SIPE_DEBUG_INFO("Renaming group <%S> to <%S>", gi->pszOldName, gi->pszNewName);
766 oldname = mir_t2a(gi->pszOldName);
767 newname = mir_t2a(gi->pszNewName);
768 LOCK;
769 sipe_core_group_rename(pr->sip, oldname, newname);
770 UNLOCK;
771 mir_free(oldname);
772 mir_free(newname);
773 return 0;
776 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
777 gchar *oldgroup;
778 gchar *who = g_strdup(dbv.pszVal);
779 DBFreeVariant( &dbv );
781 if (oldgroup = sipe_miranda_getContactString(pr, hContact, "Group"))
783 SIPE_DEBUG_INFO("Moving buddy <%s> from group <%ls> to group <%ls>", who, oldgroup, gi->pszNewName);
784 LOCK;
785 sipe_core_buddy_group(pr->sip, who, oldgroup, TCHAR2CHAR(gi->pszNewName));
786 UNLOCK;
787 mir_free(oldgroup);
788 } else {
789 gchar *name = mir_t2a(gi->pszNewName);
791 if (!g_str_has_prefix(name, "sip:")) {
792 gchar *newname = sip_uri_from_name(name);
793 mir_free(name);
794 name = mir_strdup(newname);
795 g_free(newname);
798 SIPE_DEBUG_INFO("Really adding buddy <%s> to list in group <%s>", who, name);
799 LOCK;
800 sipe_core_buddy_add(pr->sip, who, name);
801 UNLOCK;
802 mir_free(name);
805 g_free(who);
808 return TRUE;
811 static int sipe_miranda_build_chat_menu(SIPPROTO *pr, WPARAM w, LPARAM lParam )
813 GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;
815 if (gcmi->Type == MENU_ON_NICKLIST)
817 static struct gc_item Item[] = {
818 {"&Make Leader", 1, MENU_ITEM, FALSE},
821 gcmi->nItems = sizeof(Item)/sizeof(Item[0]);
822 gcmi->Item = &Item[0];
825 return 0;
828 static int OnChatEvent(SIPPROTO *pr, WPARAM w, LPARAM l )
830 GCHOOK *hook = (GCHOOK*)l;
831 GCDEST *dst = hook->pDest;
833 if (dst->iType == GC_USER_MESSAGE) {
834 GCDEST gcd = {0};
835 GCEVENT gce = {0};
836 struct sipe_chat_session *session;
838 gcd.pszModule = pr->proto.m_szModuleName;
839 gcd.pszID = dst->pszID;
840 gcd.iType = GC_EVENT_GETITEMDATA;
842 gce.cbSize = sizeof(gce);
843 gce.pDest = &gcd;
846 if ((session = (struct sipe_chat_session*)CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)
848 SIPE_DEBUG_WARNING_NOFORMAT("Failed to get chat session");
849 return 0;
852 LOCK;
853 sipe_core_chat_send(pr->sip, session, hook->pszText);
854 UNLOCK;
856 return TRUE;
857 } else if (dst->iType == GC_USER_PRIVMESS) {
858 } else if (dst->iType == GC_USER_NICKLISTMENU) {
859 if (hook->dwData == 1)
861 SIPE_DEBUG_INFO("make leader <%s>", hook->pszUID);
865 return FALSE;
868 int OnPreBuildContactMenu(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
870 HANDLE hContact = (HANDLE)wParam;
871 int chatcount = CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)pr->proto.m_szModuleName);
872 int idx;
873 CLISTMENUITEM mi = {0};
874 GC_INFO gci = {0};
875 gpointer tmp;
877 mi.cbSize = sizeof(mi);
878 gci.pszModule = pr->proto.m_szModuleName;
880 /* Remove the old list */
881 while (pr->contactMenuChatItems)
883 SIPE_DEBUG_INFO("Removing old menuitem <%08x>", pr->contactMenuChatItems->data);
884 CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)pr->contactMenuChatItems->data, 0);
885 pr->contactMenuChatItems = g_slist_remove(pr->contactMenuChatItems, pr->contactMenuChatItems->data);
888 /* Add the main entry */
889 mi.pszName = "Invite to chat";
890 mi.flags = CMIF_NOTOFFLINE;
891 mi.position = 20;
892 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
893 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
895 mi.pszName = "New chat";
896 mi.hParentMenu = pr->contactMenuChatItems->data;
897 mi.flags = CMIF_ROOTHANDLE;
898 mi.popupPosition = 0;
899 mi.position=-10;
900 mi.pszService = g_strdup_printf("%s/StartChat", pr->proto.m_szModuleName);
901 mi.pszContactOwner = pr->proto.m_szModuleName;
902 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
903 g_free(mi.pszService);
904 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
906 for (idx=0 ; idx<chatcount ; idx++)
908 SIPE_DEBUG_INFO("Chat <%d> Menuitem <%08x>", idx, pr->contactMenuChatItems);
909 gci.iItem = idx;
910 gci.Flags = BYINDEX | NAME | ID;
911 if(!CallServiceSync( MS_GC_GETINFO, 0, (LPARAM)&gci )) {
912 SIPE_DEBUG_INFO("Chat <%s>", gci.pszName);
914 mi.pszName = gci.pszName;
915 mi.hParentMenu = pr->contactMenuChatItems->data;
916 mi.flags = CMIF_ROOTHANDLE;
917 mi.popupPosition = g_strdup(gci.pszID);
918 mi.position = idx;
919 mi.pszService = g_strdup_printf("%s/InviteToChat", pr->proto.m_szModuleName);
920 mi.pszContactOwner = pr->proto.m_szModuleName;
921 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
922 g_free(mi.pszService);
923 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
927 return 0;
930 INT_PTR SvcCreateAccMgrUI(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
932 return (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ACCMGRUI), (HWND)lParam, DlgProcAccMgrUI, (LPARAM)pr);
937 * Miranda service functions
939 * The functions in our plugin that get called directly by core Miranda
941 static DWORD_PTR GetCaps( SIPPROTO *pr, int type, HANDLE hContact )
943 switch (type) {
944 case PFLAGNUM_1:
945 return PF1_IM | PF1_CHAT | PF1_FILE | PF1_MODEMSG
946 | PF1_SERVERCLIST | PF1_ADDED
947 | PF1_BASICSEARCH | PF1_ADDSEARCHRES
948 | PF1_SEARCHBYEMAIL | PF1_USERIDISEMAIL
949 | PF1_SEARCHBYNAME | PF1_EXTSEARCH
952 case PFLAGNUM_2:
953 return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY
954 | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND
955 | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;
957 case PFLAGNUM_3:
958 return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY
959 | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND
960 | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;
962 case PFLAGNUM_4:
963 return PF4_NOCUSTOMAUTH | PF4_IMSENDUTF | PF4_SUPPORTTYPING
964 | PF4_SUPPORTIDLE;
966 case PFLAGNUM_5:
967 return 0;
969 case PFLAG_UNIQUEIDSETTING:
970 return (DWORD_PTR) SIP_UNIQUEID;
971 break;
972 default:
973 SIPE_DEBUG_INFO("GetCaps: unknown type <%x>", type);
977 return 0;
980 static HICON GetIcon( SIPPROTO *pr, int iconIndex )
982 SIPE_DEBUG_INFO("GetIcon: unknown index <%x>", iconIndex);
983 return NULL;
986 static int OnEvent( SIPPROTO *pr, PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam )
988 SIPE_DEBUG_INFO("OnEvent: type <%x>", eventType);
990 switch (eventType)
992 case EV_PROTO_ONLOAD:
993 OnModulesLoaded(pr);
994 break;
996 case EV_PROTO_ONREADYTOEXIT:
997 break;
999 case EV_PROTO_ONEXIT:
1000 break;
1002 case EV_PROTO_ONRENAME:
1003 break;
1005 case EV_PROTO_ONOPTIONS:
1006 return OnOptionsInit( pr, wParam, lParam );
1007 break;
1009 case EV_PROTO_ONERASE:
1010 break;
1014 return 0;
1017 static HANDLE AddToListByEvent( SIPPROTO *pr, int flags, int iContact, HANDLE hDbEvent )
1019 DBEVENTINFO dbei = {0};
1021 dbei.cbSize = sizeof(dbei);
1022 if ((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) == -1)
1023 return 0;
1025 dbei.pBlob = (PBYTE)_alloca(dbei.cbBlob + 1);
1026 dbei.pBlob[dbei.cbBlob] = '\0';
1028 if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei))
1029 return 0; // failed to get event
1031 if (strcmp(dbei.szModule, pr->proto.m_szModuleName))
1032 return 0; // this event is not ours
1034 _NIF();
1035 SIPE_DEBUG_INFO("AddToListByEvent: flags <%x> iContact <%x>", flags, iContact);
1036 return NULL;
1039 static int Authorize( SIPPROTO *pr, HANDLE hContact )
1041 _NIF();
1042 SIPE_DEBUG_INFO_NOFORMAT("Authorize");
1043 return 0;
1046 static int AuthDeny( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szReason )
1048 _NIF();
1049 SIPE_DEBUG_INFO("AuthDeny: reason <%s>", szReason);
1050 return 0;
1053 static int AuthRecv( SIPPROTO *pr, HANDLE hContact, PROTORECVEVENT* evt )
1055 _NIF();
1056 SIPE_DEBUG_INFO_NOFORMAT("AuthRecv");
1057 return 0;
1060 static int AuthRequest( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szMessage )
1062 _NIF();
1063 SIPE_DEBUG_INFO("AuthRequest: message <%s>", szMessage);
1064 return 0;
1067 static HANDLE ChangeInfo( SIPPROTO *pr, int iInfoType, void* pInfoData )
1069 _NIF();
1070 SIPE_DEBUG_INFO("ChangeInfo: infotype <%x>", iInfoType);
1071 return NULL;
1074 static int FileCancel( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer )
1076 _NIF();
1077 SIPE_DEBUG_INFO_NOFORMAT("FileCancel");
1078 return 0;
1081 static int FileResume( SIPPROTO *pr, HANDLE hTransfer, int* action, const PROTOCHAR** szFilename )
1083 _NIF();
1084 SIPE_DEBUG_INFO("FileResume: action <%x>", action);
1085 return 0;
1088 static HANDLE SearchBasic( SIPPROTO *pr, const PROTOCHAR* id )
1090 return NULL;
1093 static HWND CreateExtendedSearchUI( SIPPROTO *pr, HWND owner )
1095 return CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SEARCHUI), (HWND)owner, NULL, (LPARAM)pr);
1098 static HANDLE AddToList( SIPPROTO *pr, int flags, PROTOSEARCHRESULT* psr )
1100 HANDLE hContact;
1101 gchar *id = g_strdup(TCHAR2CHAR(psr->id));
1103 /* Prepend sip: if needed */
1104 if (strncmp("sip:", id, 4)) {
1105 gchar *tmp = id;
1106 id = sip_uri_from_name(tmp);
1107 g_free(tmp);
1110 hContact = sipe_miranda_buddy_find(pr, id, NULL);
1111 if (hContact) {
1112 g_free(id);
1113 return hContact;
1116 hContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );
1117 CallService( MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)pr->proto.m_szModuleName );
1118 sipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, id ); // name
1119 if (psr->nick)
1121 /* server_alias */
1122 gchar *tmp = mir_t2a(psr->nick);
1123 sipe_miranda_setContactStringUtf( pr, hContact, "Nick", tmp );
1124 mir_free(tmp);
1127 g_free(id);
1128 return hContact;
1132 sipe_miranda_window_closed(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
1134 MessageWindowEventData* evt = (MessageWindowEventData*)lParam;
1136 SIPE_DEBUG_INFO("contact <%08x> module <%s> type <%02x> flags <%02x>",
1137 evt->hContact, evt->szModule, evt->uType, evt->uFlags);
1139 return 0;
1142 static int
1143 sipe_miranda_invite_to_chat(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
1145 HANDLE hContact = (HANDLE)wParam;
1146 gchar *id = (gchar*)lParam;
1147 GCDEST gcd = {0};
1148 GCEVENT gce = {0};
1149 struct sipe_chat_session *session;
1150 gchar *uid;
1152 gcd.pszModule = pr->proto.m_szModuleName;
1153 gcd.pszID = id;
1154 gcd.iType = GC_EVENT_GETITEMDATA;
1156 gce.cbSize = sizeof(gce);
1157 gce.pDest = &gcd;
1159 if ((session = (struct sipe_chat_session*)CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)
1161 SIPE_DEBUG_WARNING_NOFORMAT("Failed to get chat session");
1162 return 0;
1165 uid = sipe_miranda_getContactString(pr, hContact, SIP_UNIQUEID);
1166 sipe_core_chat_invite(pr->sip, session, uid);
1168 mir_free(uid);
1169 g_free(id);
1170 return 0;
1174 * Main Miranda interface
1176 * The structures and functions that allow Miranda to recovnize and load
1177 * our plugin.
1180 /* Plugin information structure */
1181 PLUGININFOEX pluginInfo = {
1182 sizeof(PLUGININFOEX),
1183 "Office Communicator Protocol",
1184 PLUGIN_MAKE_VERSION(0,11,2,1),
1185 "Support for Microsoft Office Communicator",
1186 "Miranda support by Jochen De Smet, for core sipe support see homepage",
1187 "jochen.libsipe@leahnim.org",
1188 "(C)2009-2011",
1189 "https://sourceforge.net/projects/sipe",
1190 UNICODE_AWARE,
1191 0, //doesn't replace anything built-in
1192 #if defined( _UNICODE )
1193 { 0x842395ed, 0x4e56, 0x40e5, { 0x94, 0x25, 0x28, 0x29, 0xd8, 0xab, 0xae, 0xa5 } } // {842395ED-4E56-40e5-9425-2829D8ABAEA5}
1194 #else
1195 { 0x1ef8af37, 0xdec1, 0x4757, { 0x89, 0x78, 0xe8, 0xad, 0xd0, 0xd8, 0x6e, 0x7f } } // {1EF8AF37-DEC1-4757-8978-E8ADD0D86E7F}
1196 #endif
1199 __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
1201 // Only load for 0.8.0.29 or greater
1202 // We need the core stubs for PS_GETNAME and PS_GETSTATUS
1203 if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 9, 0, 0))
1205 MessageBoxA(
1206 NULL,
1207 "SIP/Simple plugin cannot be loaded. It requires Miranda IM 0.9.0.0 or later.",
1208 "SIP/Simple Plugin",
1209 MB_OK | MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST
1211 return NULL;
1214 return &pluginInfo;
1217 static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST};
1218 __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
1220 return interfaces;
1223 static PROTO_INTERFACE* sipsimpleProtoInit( const char* pszProtoName, const TCHAR* tszUserName )
1225 gchar *tmp;
1226 SIPPROTO *pr = (SIPPROTO *)mir_calloc(sizeof(SIPPROTO));
1227 pr->proto.vtbl = (PROTO_INTERFACE_VTBL*)mir_calloc(sizeof(PROTO_INTERFACE_VTBL));
1229 SIPE_DEBUG_INFO("protoname <%s> username <%ls>", pszProtoName, tszUserName);
1231 if (!InitializeCriticalSectionAndSpinCount(&pr->CriticalSection, 0))
1233 SIPE_DEBUG_ERROR_NOFORMAT("Can't initialize critical section");
1234 return NULL;
1237 tmp = sipe_miranda_getString(pr, "transport");
1238 if (!tmp)
1240 sipe_miranda_setString(pr, "transport", "auto");
1241 } else {
1242 mir_free(tmp);
1245 /* To make it easy to detect when a SIPPROTO* isn't a SIPPROTO* */
1246 strncpy(pr->_SIGNATURE, "AbandonAllHope..", sizeof(pr->_SIGNATURE));
1248 pr->main_thread_id = GetCurrentThreadId();
1249 pr->proto.m_iVersion = 2;
1250 pr->proto.m_szModuleName = mir_strdup(pszProtoName);
1251 pr->proto.m_tszUserName = mir_tstrdup(tszUserName);
1252 pr->proto.m_szProtoName = mir_strdup(pszProtoName);
1254 // set_buddies_offline(pr);
1255 fix_contact_groups(pr);
1257 /* Fill the function table */
1258 pr->proto.vtbl->AddToList = AddToList;
1259 pr->proto.vtbl->AddToListByEvent = AddToListByEvent;
1261 pr->proto.vtbl->Authorize = Authorize;
1262 pr->proto.vtbl->AuthDeny = AuthDeny;
1263 pr->proto.vtbl->AuthRecv = AuthRecv;
1264 pr->proto.vtbl->AuthRequest = AuthRequest;
1266 pr->proto.vtbl->ChangeInfo = ChangeInfo;
1268 pr->proto.vtbl->FileAllow = sipe_miranda_FileAllow;
1269 pr->proto.vtbl->FileCancel = FileCancel;
1270 pr->proto.vtbl->FileDeny = sipe_miranda_FileDeny;
1271 pr->proto.vtbl->FileResume = FileResume;
1273 pr->proto.vtbl->GetCaps = GetCaps;
1274 pr->proto.vtbl->GetIcon = GetIcon;
1275 pr->proto.vtbl->GetInfo = sipe_miranda_GetInfo;
1277 pr->proto.vtbl->SearchBasic = SearchBasic;
1278 pr->proto.vtbl->SearchByEmail = sipe_miranda_SearchByEmail;
1279 pr->proto.vtbl->SearchByName = sipe_miranda_SearchByName;
1280 pr->proto.vtbl->SearchAdvanced = sipe_miranda_SearchAdvanced;
1281 pr->proto.vtbl->CreateExtendedSearchUI = CreateExtendedSearchUI;
1283 pr->proto.vtbl->RecvMsg = sipe_miranda_RecvMsg;
1285 pr->proto.vtbl->SendMsg = sipe_miranda_SendMsg;
1287 pr->proto.vtbl->SetStatus = sipe_miranda_SetStatus;
1289 pr->proto.vtbl->GetAwayMsg = sipe_miranda_GetAwayMsg;
1290 pr->proto.vtbl->SetAwayMsg = sipe_miranda_SetAwayMsg;
1292 pr->proto.vtbl->UserIsTyping = sipe_miranda_UserIsTyping;
1294 pr->proto.vtbl->SendFile = sipe_miranda_SendFile;
1295 pr->proto.vtbl->RecvFile = sipe_miranda_RecvFile;
1297 pr->proto.vtbl->OnEvent = OnEvent;
1299 /* Setup services */
1300 CreateProtoService(pr, PS_CREATEACCMGRUI, &SvcCreateAccMgrUI );
1301 CreateProtoService(pr, "/InviteToChat", &sipe_miranda_invite_to_chat);
1302 CreateProtoService(pr, "/StartChat",&sipe_miranda_start_chat);
1304 #define HOOKEVENT(evt,func) HookEventObj(evt, func, pr)
1305 HOOKEVENT(ME_OPT_INITIALISE, &OnOptionsInit);
1306 HOOKEVENT(ME_CLIST_GROUPCHANGE, &OnGroupChange);
1307 HOOKEVENT(ME_GC_EVENT, &OnChatEvent);
1308 HOOKEVENT(ME_CLIST_PREBUILDCONTACTMENU, &OnPreBuildContactMenu);
1309 HOOKEVENT(ME_DB_CONTACT_DELETED, &sipe_miranda_buddy_delete);
1310 HOOKEVENT(ME_MSG_WINDOWEVENT, &sipe_miranda_window_closed);
1311 HOOKEVENT(ME_GC_BUILDMENU, &sipe_miranda_build_chat_menu);
1313 return (PROTO_INTERFACE*)pr;
1316 static int sipsimpleProtoUninit( PROTO_INTERFACE* _pr )
1318 SIPPROTO *pr = (SIPPROTO *)_pr;
1320 DeleteCriticalSection(&pr->CriticalSection);
1322 Netlib_CloseHandle(pr->m_hServerNetlibUser);
1323 mir_free(pr->proto.m_szProtoName);
1324 mir_free(pr->proto.m_szModuleName);
1325 mir_free(pr->proto.m_tszUserName);
1326 mir_free(pr->proto.vtbl);
1327 mir_free(pr);
1329 return 0;
1332 __declspec(dllexport) int Load(PLUGINLINK *link)
1334 PROTOCOLDESCRIPTOR pd = {0};
1335 NETLIBUSER nlu = {0};
1336 char *tmp;
1337 WORD iptype;
1339 pluginLink = link;
1341 sipe_core_init("");
1343 mir_getMMI( &mmi );
1345 /* Register the module */
1346 pd.cbSize = sizeof(pd);
1347 pd.szName = SIPSIMPLE_PROTOCOL_NAME;
1348 pd.type = PROTOTYPE_PROTOCOL;
1349 pd.fnInit = sipsimpleProtoInit;
1350 pd.fnUninit = sipsimpleProtoUninit;
1351 CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
1353 /* Protocolwide netlib user for incoming connections (also abused for logging) */
1354 nlu.cbSize = sizeof(nlu);
1355 nlu.flags = NUF_INCOMING | NUF_TCHAR | NUF_NOOPTIONS;
1356 nlu.szSettingsModule = SIPSIMPLE_PROTOCOL_NAME;
1357 nlu.minIncomingPorts = 10;
1359 InitializeCriticalSectionAndSpinCount(&sipe_miranda_debug_CriticalSection, 0);
1360 sipe_miranda_incoming_netlibuser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
1362 tmp = sipe_miranda_getGlobalString("public_ip");
1363 if (!tmp) {
1364 sipe_miranda_setGlobalString("public_ip", "0.0.0.0");
1365 } else {
1366 mir_free(tmp);
1369 if (!sipe_miranda_getGlobalWord("iptype", &iptype))
1371 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_LOCAL);
1374 return 0;
1377 __declspec(dllexport) int Unload(void)
1379 Netlib_CloseHandle(sipe_miranda_incoming_netlibuser);
1380 sipe_miranda_incoming_netlibuser = NULL;
1381 DeleteCriticalSection(&sipe_miranda_debug_CriticalSection);
1382 sipe_core_destroy();
1383 return 0;
1386 BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
1388 hInst = hinstDLL;
1389 return TRUE;
1393 Local Variables:
1394 mode: c
1395 c-file-style: "bsd"
1396 indent-tabs-mode: t
1397 tab-width: 8
1398 End: