ucs: add initial presence subscription
[siplcs.git] / src / miranda / miranda-plugin.c
blobe411d2d2cf06e881699b9a97493308cc4b0ae604
1 /**
2 * @file miranda-plugin.c
4 * pidgin-sipe
6 * Copyright (C) 2010-2013 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;
87 int hLangpack;
90 * Dialog boxes
92 static void
93 EnableDlgItem(HWND hwndDlg, UINT control, gboolean enable)
95 EnableWindow(GetDlgItem(hwndDlg, control), enable);
98 static void
99 CheckDlgItem(HWND hwndDlg, UINT control, int state)
101 Button_SetCheck(GetDlgItem(hwndDlg, control), state);
104 INT_PTR CALLBACK DlgProcSipSimpleOptsAbout(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
107 switch(msg)
109 case WM_INITDIALOG:
111 SIPPROTO *pr = (SIPPROTO *)lParam;
112 SETTEXTEX tex;
113 gchar *tmp, *about;
114 LOCK;
115 tmp = sipe_core_about();
116 about = sipe_miranda_html2rtf(tmp);
117 g_free(tmp);
118 UNLOCK;
120 TranslateDialogDefault(hwndDlg);
122 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
124 tex.flags = ST_DEFAULT;
125 tex.codepage = 437;
127 SendDlgItemMessage(hwndDlg, IDC_ABOUTSIPE, EM_SETTEXTEX, (WPARAM)&tex, (LPARAM)about );
129 g_free(about);
133 return FALSE;
136 static INT_PTR CALLBACK DlgProcSipSimpleOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
138 static int lock=0;
140 switch(msg)
142 case WM_INITDIALOG:
144 const SIPPROTO *pr = (const SIPPROTO *)lParam;
145 char *str;
146 gboolean state;
147 WORD iptype;
149 TranslateDialogDefault(hwndDlg);
151 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
153 lock++;
155 #if defined(HAVE_LIBKRB5) || defined(HAVE_SSPI)
156 state = sipe_miranda_getBool(pr, "sso", FALSE);
157 if (state)
159 CheckDlgItem(hwndDlg, IDC_USESSO, BST_CHECKED);
160 EnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);
161 EnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);
162 } else {
163 #endif
164 CheckDlgItem(hwndDlg, IDC_USESSO, BST_UNCHECKED);
165 EnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);
166 EnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);
167 #if defined(HAVE_LIBKRB5) || defined(HAVE_SSPI)
169 #endif
171 str = sipe_miranda_getString(pr, "username");
172 SetDlgItemTextA(hwndDlg, IDC_HANDLE, str);
173 SendDlgItemMessage(hwndDlg, IDC_HANDLE, EM_SETLIMITTEXT, 50, 0);
174 mir_free(str);
176 str = sipe_miranda_getString(pr, "login");
177 SetDlgItemTextA(hwndDlg, IDC_LOGIN, str);
178 SendDlgItemMessage(hwndDlg, IDC_LOGIN, EM_SETLIMITTEXT, 50, 0);
179 mir_free(str);
181 str = sipe_miranda_getString(pr, "password");
182 if (str) CallService(MS_DB_CRYPT_DECODESTRING, strlen(str),(LPARAM)str);
183 SetDlgItemTextA(hwndDlg, IDC_PASSWORD, str);
184 SendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_SETLIMITTEXT, 16, 0);
185 mir_free(str);
187 SendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_ADDSTRING, 0, (LPARAM)_T("NTLM"));
188 #if defined(HAVE_LIBKRB5) || defined(HAVE_SSPI)
189 SendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_ADDSTRING, 0, (LPARAM)_T("Kerberos"));
190 #endif
191 SendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_ADDSTRING, 0, (LPARAM)_T("TLS-DSK"));
193 sipe_miranda_getWord(pr, NULL, "authscheme", &iptype);
194 if (iptype == SIPE_AUTHENTICATION_TYPE_NTLM)
195 SendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("NTLM"));
196 else if (iptype == SIPE_AUTHENTICATION_TYPE_KERBEROS)
197 SendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("Kerberos"));
198 else if (!strcmp(str, "tls-dsk"))
199 SendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("TLS-DSK"));
200 else
201 SendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("NTLM"));
203 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("Auto"));
204 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("SSL/TLS"));
205 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("TCP"));
207 str = sipe_miranda_getString(pr, "transport");
208 if (!str || !strcmp(str, "auto"))
209 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("Auto"));
210 else if (!strcmp(str, "tls"))
211 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("SSL/TLS"));
212 else if (!strcmp(str, "tcp"))
213 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("TCP"));
215 str = sipe_miranda_getGlobalString("public_ip");
216 SetDlgItemTextA(hwndDlg, IDC_PUBLICIP, str);
217 SendDlgItemMessage(hwndDlg, IDC_PUBLICIP, EM_SETLIMITTEXT, 20, 0);
218 mir_free(str);
220 str = sipe_miranda_getGlobalString("ipprog");
221 SetDlgItemTextA(hwndDlg, IDC_IPPROGEXE, str);
222 SendDlgItemMessage(hwndDlg, IDC_IPPROGEXE, EM_SETLIMITTEXT, 60, 0);
223 mir_free(str);
225 str = sipe_miranda_get_local_ip();
226 SetDlgItemTextA(hwndDlg, IDC_IPLOCALFOUND, str);
228 sipe_miranda_getGlobalWord("iptype", &iptype);
229 if (iptype == SIPE_MIRANDA_IP_LOCAL)
231 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPLOCAL);
232 EnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);
233 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);
234 } else if (iptype == SIPE_MIRANDA_IP_MANUAL) {
235 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPMANUAL);
236 EnableDlgItem(hwndDlg, IDC_PUBLICIP, TRUE);
237 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);
238 } else {
239 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPPROG);
240 EnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);
241 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, TRUE);
244 lock--;
245 return TRUE;
248 case WM_COMMAND:
250 int code = wParam >> 16;
251 int id = wParam & 0xffff;
253 if (LOWORD(wParam) == IDC_IPLOCAL)
255 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPLOCAL);
256 EnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);
257 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);
258 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
259 } else if (LOWORD(wParam) == IDC_IPMANUAL) {
260 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPMANUAL);
261 EnableDlgItem(hwndDlg, IDC_PUBLICIP, TRUE);
262 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, FALSE);
263 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
264 } else if (LOWORD(wParam) == IDC_IPPROG) {
265 CheckRadioButton(hwndDlg, IDC_IPLOCAL, IDC_IPPROG, IDC_IPPROG);
266 EnableDlgItem(hwndDlg, IDC_PUBLICIP, FALSE);
267 EnableDlgItem(hwndDlg, IDC_IPPROGEXE, TRUE);
268 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
269 } else if (LOWORD(wParam) == IDC_USESSO) {
270 if (IsDlgButtonChecked(hwndDlg, IDC_USESSO) == BST_CHECKED)
272 EnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);
273 EnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);
274 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
275 } else {
276 CheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_MSO);
277 EnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);
278 EnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);
280 } else if (!lock && (code == EN_CHANGE || code == CBN_SELCHANGE)) {
281 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
283 return TRUE;
286 case WM_NOTIFY:
288 if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
290 char buf[100];
291 TCHAR tbuf[100];
293 const SIPPROTO *pr = (const SIPPROTO *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
295 GetDlgItemTextA(hwndDlg, IDC_HANDLE, buf, sizeof(buf));
296 sipe_miranda_setString(pr, "username", buf);
298 GetDlgItemTextA(hwndDlg, IDC_LOGIN, buf, sizeof(buf));
299 sipe_miranda_setString(pr, "login", buf);
301 GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf));
302 CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf),(LPARAM)buf);
303 sipe_miranda_setString(pr, "password", buf);
305 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, WM_GETTEXT, 100, (LPARAM)tbuf );
307 if (!_tcscmp(tbuf, _T("Auto")))
308 sipe_miranda_setString(pr, "transport", "auto");
309 else if (!_tcscmp(tbuf, _T("SSL/TLS")))
310 sipe_miranda_setString(pr, "transport", "tls");
311 else if (!_tcscmp(tbuf, _T("TCP")))
312 sipe_miranda_setString(pr, "transport", "tcp");
314 SendDlgItemMessage(hwndDlg, IDC_AUTHTYPE, WM_GETTEXT, 100, (LPARAM)tbuf );
316 if (!_tcscmp(tbuf, _T("NTLM")))
317 sipe_miranda_setWord(pr, NULL, "authscheme", SIPE_AUTHENTICATION_TYPE_NTLM);
318 else if (!_tcscmp(tbuf, _T("Kerberos")))
319 sipe_miranda_setWord(pr, NULL, "authscheme", SIPE_AUTHENTICATION_TYPE_KERBEROS);
320 else if (!_tcscmp(tbuf, _T("TLS-DSK")))
321 sipe_miranda_setWord(pr, NULL, "authscheme", SIPE_AUTHENTICATION_TYPE_TLS_DSK);
323 GetDlgItemTextA(hwndDlg, IDC_PUBLICIP, buf, sizeof(buf));
324 sipe_miranda_setGlobalString("public_ip", buf);
326 GetDlgItemTextA(hwndDlg, IDC_IPPROGEXE, buf, sizeof(buf));
327 sipe_miranda_setGlobalString("ipprog", buf);
329 if (IsDlgButtonChecked(hwndDlg, IDC_IPLOCAL) == BST_CHECKED)
331 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_LOCAL);
332 } else if (IsDlgButtonChecked(hwndDlg, IDC_IPMANUAL) == BST_CHECKED) {
333 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_MANUAL);
334 } else {
335 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_PROG);
337 return TRUE;
339 return TRUE;
344 return FALSE;
347 INT_PTR CALLBACK DlgProcAccMgrUI(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
349 switch(msg)
351 case WM_INITDIALOG:
353 const SIPPROTO *pr = (const SIPPROTO *)lParam;
354 char *str;
355 gboolean sso;
357 TranslateDialogDefault(hwndDlg);
359 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
361 sso = sipe_miranda_getBool(pr, "sso", FALSE);
362 if (sso)
364 CheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_SSO);
365 EnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);
366 EnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);
367 } else {
368 CheckRadioButton(hwndDlg, IDC_SSO, IDC_MSO, IDC_MSO);
369 EnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);
370 EnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);
373 str = sipe_miranda_getString(pr, "username");
374 SetDlgItemTextA(hwndDlg, IDC_HANDLE, str);
375 mir_free(str);
377 str = sipe_miranda_getString(pr, "login");
378 SetDlgItemTextA(hwndDlg, IDC_LOGIN, str);
379 mir_free(str);
381 str = sipe_miranda_getString(pr, "password");
382 if (str) CallService(MS_DB_CRYPT_DECODESTRING, strlen(str),(LPARAM)str);
383 SetDlgItemTextA(hwndDlg, IDC_PASSWORD, str);
384 mir_free(str);
386 SendDlgItemMessage(hwndDlg, IDC_HANDLE, EM_SETLIMITTEXT, 50, 0);
387 SendDlgItemMessage(hwndDlg, IDC_LOGIN, EM_SETLIMITTEXT, 50, 0);
388 SendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_SETLIMITTEXT, 16, 0);
390 return TRUE;
393 case WM_COMMAND:
394 if (LOWORD(wParam) == IDC_SSO)
396 EnableDlgItem(hwndDlg, IDC_LOGIN, FALSE);
397 EnableDlgItem(hwndDlg, IDC_PASSWORD, FALSE);
398 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
399 } else if (LOWORD(wParam) == IDC_MSO) {
400 EnableDlgItem(hwndDlg, IDC_LOGIN, TRUE);
401 EnableDlgItem(hwndDlg, IDC_PASSWORD, TRUE);
402 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
403 } else if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus()) {
404 switch(LOWORD(wParam))
406 case IDC_HANDLE:
407 case IDC_LOGIN:
408 case IDC_PASSWORD:
409 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
410 break;
413 break;
415 case WM_NOTIFY:
416 if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
418 char buf[100];
420 const SIPPROTO *pr = (const SIPPROTO *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
422 if (IsDlgButtonChecked(hwndDlg, IDC_SSO) == BST_CHECKED)
424 sipe_miranda_setBool(pr, "sso", TRUE);
425 } else {
426 sipe_miranda_setBool(pr, "sso", FALSE);
429 GetDlgItemTextA(hwndDlg, IDC_HANDLE, buf, sizeof(buf));
430 sipe_miranda_setString(pr, "username", buf);
432 GetDlgItemTextA(hwndDlg, IDC_LOGIN, buf, sizeof(buf));
433 sipe_miranda_setString(pr, "login", buf);
435 GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf));
436 CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf),(LPARAM)buf);
437 sipe_miranda_setString(pr, "password", buf);
439 return TRUE;
441 break;
444 return FALSE;
449 * Miranda service support functions
451 * Functions called by our service functions
453 static void fix_contact_groups(SIPPROTO *pr)
455 GSList *contacts = sipe_miranda_buddy_find_all(pr, NULL, NULL);
456 char *group;
458 CONTACTS_FOREACH(contacts)
459 group = DBGetString(hContact, "CList", "Group");
460 sipe_miranda_setContactString(pr, hContact, "Group", group);
461 mir_free(group);
462 CONTACTS_FOREACH_END
466 static INT_PTR sipe_miranda_start_chat(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
468 HANDLE hContact = (HANDLE)wParam;
469 struct sipe_core_public *sipe_public = pr->sip;
471 DBVARIANT dbv;
472 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
473 LOCK;
474 sipe_core_buddy_new_chat(sipe_public, dbv.pszVal);
475 UNLOCK;
476 DBFreeVariant( &dbv );
477 return TRUE;
480 return FALSE;
483 static void OnModulesLoaded(SIPPROTO *pr)
485 TCHAR descr[MAX_PATH];
486 NETLIBUSER nlu = {0};
487 GCREGISTER gcr;
488 DBEVENTTYPEDESCR eventType = {0};
490 SIPE_DEBUG_INFO_NOFORMAT("OnEvent::OnModulesLoaded");
492 nlu.cbSize = sizeof(nlu);
493 nlu.flags = NUF_OUTGOING | NUF_INCOMING | NUF_TCHAR;
494 nlu.szSettingsModule = pr->proto.m_szModuleName;
495 _sntprintf(descr, SIZEOF(descr), TranslateT("%s server connection"), pr->proto.m_tszUserName );
496 nlu.ptszDescriptiveName = descr;
498 pr->m_hServerNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
500 gcr.cbSize = sizeof(gcr);
501 gcr.dwFlags = 0;
502 gcr.pszModule = pr->proto.m_szModuleName;
503 gcr.pszModuleDispName = "Sip/Simple";
504 gcr.iMaxText = 0;
505 gcr.nColors = 0;
507 if (CallService(MS_GC_REGISTER, 0, (LPARAM)&gcr))
509 SIPE_DEBUG_INFO_NOFORMAT("OnEvent::OnModulesLoaded Failed to register chat");
512 // Register custom database events
513 eventType.cbSize = DBEVENTTYPEDESCR_SIZE;
514 eventType.module = pr->proto.m_szModuleName;
515 eventType.eventType = SIPE_EVENTTYPE_ERROR_NOTIFY;
516 eventType.descr = "Message error notification";
517 eventType.textService = SIPE_DB_GETEVENTTEXT_ERROR_NOTIFY;
518 eventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
519 // for now keep default "message" icon
520 CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);
522 eventType.cbSize = DBEVENTTYPEDESCR_SIZE;
523 eventType.module = pr->proto.m_szModuleName;
524 eventType.eventType = SIPE_EVENTTYPE_INFO_NOTIFY;
525 eventType.descr = "Message info notification";
526 eventType.textService = SIPE_DB_GETEVENTTEXT_INFO_NOTIFY;
527 eventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
528 // for now keep default "message" icon
529 CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);
531 eventType.cbSize = DBEVENTTYPEDESCR_SIZE;
532 eventType.module = pr->proto.m_szModuleName;
533 eventType.eventType = SIPE_EVENTTYPE_IM_TOPIC;
534 eventType.descr = "Chat topic set";
535 eventType.textService = SIPE_DB_GETEVENTTEXT_IM_TOPIC;
536 eventType.flags = DETF_HISTORY | DETF_MSGWINDOW;
537 // for now keep default "message" icon
538 CallService(MS_DB_EVENT_REGISTERTYPE, 0, (LPARAM)&eventType);
542 int OnOptionsInit(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
544 OPTIONSDIALOGPAGE odp = {0};
545 HMODULE hUxTheme = 0;
547 if (IsWinVerXPPlus())
549 hUxTheme = GetModuleHandleA("uxtheme.dll");
550 if (hUxTheme)
551 pfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
554 odp.cbSize = sizeof(odp);
555 odp.position = -800000000;
556 odp.hInstance = hInst;
557 odp.ptszGroup = LPGENT("Network");
558 odp.dwInitParam = (LPARAM)pr;
559 odp.ptszTitle = pr->proto.m_tszUserName;
560 odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
562 odp.ptszTab = LPGENT("Account");
563 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE);
564 odp.pfnDlgProc = DlgProcSipSimpleOpts;
565 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
567 odp.ptszTab = LPGENT("About");
568 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE_ABOUT);
569 odp.pfnDlgProc = DlgProcSipSimpleOptsAbout;
570 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
572 #if 0
574 odp.ptszTab = LPGENT("Features");
575 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQFEATURES);
576 odp.pfnDlgProc = DlgProcIcqFeaturesOpts;
577 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
579 odp.ptszTab = LPGENT("Privacy");
580 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQPRIVACY);
581 odp.pfnDlgProc = DlgProcIcqPrivacyOpts;
582 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
584 if (bPopUpService)
586 odp.position = 100000000;
587 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUPS);
588 odp.groupPosition = 900000000;
589 odp.pfnDlgProc = DlgProcIcqPopupOpts;
590 odp.ptszGroup = LPGENT("Popups");
591 odp.ptszTab = NULL;
592 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
594 #endif
595 return 0;
598 void sipe_miranda_close(SIPPROTO *pr)
600 struct sipe_core_public *sipe_public = pr->sip;
602 if (sipe_public) {
603 LOCK;
604 sipe_core_deallocate(sipe_public);
605 pr->sip = NULL;
606 UNLOCK;
608 // sipe_purple_chat_destroy_rejoin(purple_private);
609 // g_free(purple_private);
613 void set_buddies_offline(const SIPPROTO* pr)
615 HANDLE hContact;
617 hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
618 while (hContact) {
619 char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
620 if (szProto != NULL && !lstrcmpA(szProto, pr->proto.m_szModuleName)) {
621 if (DBGetContactSettingByte(hContact, pr->proto.m_szModuleName, "ChatRoom", 0) == 0)
622 DBWriteContactSettingWord(hContact, pr->proto.m_szModuleName, "Status", ID_STATUS_OFFLINE);
624 hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
628 int __stdcall show_vlc(void *data);
629 void sipe_miranda_login(SIPPROTO *pr) {
630 gchar *username = sipe_miranda_getString(pr, "username");
631 gchar *login = sipe_miranda_getString(pr, "login");
632 gchar *email = sipe_miranda_getString(pr, "email");
633 gchar *email_url = sipe_miranda_getString(pr, "email_url");
634 gchar **domain_user = g_strsplit_set(login, "/\\", 2);
635 const gchar *errmsg;
636 gchar *password;
637 gchar *tmp = (char*)mir_calloc(1024);
638 int tmpstatus;
639 int ttype;
640 guint authentication_type;
641 struct sipe_core_public *sipe_public;
643 // CloseHandle((HANDLE) mir_forkthreadex(show_vlc, NULL, 65536, NULL));
645 if (sipe_miranda_getStaticString(pr, NULL, "password", tmp, 1024 )) tmp[0] = '\0';
646 CallService(MS_DB_CRYPT_DECODESTRING, sizeof(tmp),(LPARAM)tmp);
647 password = g_strdup(tmp);
648 mir_free(tmp);
650 LOCK;
651 pr->sip = sipe_core_allocate(username,
652 // /* @TODO: is this correct?
653 // "sso" is only available when SSPI/Kerberos support is compiled in */
654 sipe_miranda_getBool(pr, "sso", FALSE),
655 domain_user[0], domain_user[0] != NULL ? domain_user[1] : "",
656 password,
657 email,
658 email_url,
659 &errmsg);
660 if (pr->sip) pr->sip->backend_private = pr;
661 sipe_public = pr->sip;
662 UNLOCK;
664 mir_free(username);
665 mir_free(login);
666 mir_free(email);
667 mir_free(email_url);
668 g_strfreev(domain_user);
669 g_free(password);
671 if (!pr->sip) {
672 sipe_miranda_connection_error_reason(pr,
673 SIPE_CONNECTION_ERROR_INVALID_USERNAME,
674 errmsg);
675 return;
678 //sipe_miranda_chat_setup_rejoin(pr);
680 /* default is NTLM */
681 sipe_miranda_getWord(pr, NULL, "authscheme", &authentication_type);
683 /* Set display name */
684 sipe_miranda_setStringUtf(pr, "Nick", pr->sip->sip_name);
686 /* Update connection progress */
687 tmpstatus = pr->proto.m_iStatus;
688 pr->proto.m_iStatus = ID_STATUS_CONNECTING;
689 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)tmpstatus, ID_STATUS_CONNECTING);
691 tmp = sipe_miranda_getString(pr, "transport");
692 if (sipe_strequal(tmp, "auto")) {
693 ttype = SIPE_TRANSPORT_AUTO;
694 } else if (sipe_strequal(tmp, "tls")) {
695 ttype = SIPE_TRANSPORT_TLS;
696 } else {
697 ttype = SIPE_TRANSPORT_TCP;
699 mir_free(tmp);
701 LOCK;
702 sipe_core_transport_sip_connect(pr->sip,
703 ttype,
704 authentication_type,
705 NULL,
706 NULL);
707 UNLOCK;
710 void sipsimple_search_contact_cb( GList *columns, GList *results, GHashTable *opts, void *data )
712 SIPPROTO *pr = (SIPPROTO *)data;
713 GList *row, *col;
714 HANDLE hProcess = g_hash_table_lookup(opts, "searchid");
715 PROTOSEARCHRESULT psr = { 0 };
717 psr.cbSize = sizeof(psr);
719 row = results;
720 while (row)
722 gchar **name;
724 col = (GList*)row->data;
725 psr.id = (PROTOCHAR*)col->data;
727 col = g_list_next(col);
728 name = g_strsplit_set(col->data, ",", 2);
729 psr.nick = (FNAMECHAR*)col->data;
730 psr.firstName = (PROTOCHAR*)(name[0] ? name[1] : NULL);
731 psr.lastName = (PROTOCHAR*)name[0];
733 col = g_list_next(col);
734 /* company */
736 col = g_list_next(col);
737 /* country */
739 col = g_list_next(col);
740 psr.email = (PROTOCHAR*)col->data;
742 row = g_list_next(row);
743 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, hProcess, (LPARAM) & psr);
744 g_strfreev(name);
747 sipe_miranda_SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hProcess, 0);
751 static int OnGroupChange(SIPPROTO *pr, WPARAM w, LPARAM l )
753 CLISTGROUPCHANGE *gi = (CLISTGROUPCHANGE*)l;
754 HANDLE hContact = (HANDLE)w;
755 DBVARIANT dbv;
757 /* No contact => it's a group add/rename/remove */
758 if (!hContact)
760 gchar *oldname, *newname;
762 /* No old name => add */
763 if (!gi->pszOldName)
765 return 0;
767 /* No new name => delete */
768 else if (!gi->pszNewName)
770 SIPE_DEBUG_INFO("Removing group <%ls>", gi->pszOldName);
771 oldname = mir_t2a(gi->pszOldName);
772 LOCK;
773 sipe_core_group_remove(pr->sip, oldname);
774 UNLOCK;
775 mir_free(oldname);
776 return 0;
779 SIPE_DEBUG_INFO("Renaming group <%S> to <%S>", gi->pszOldName, gi->pszNewName);
780 oldname = mir_t2a(gi->pszOldName);
781 newname = mir_t2a(gi->pszNewName);
782 LOCK;
783 sipe_core_group_rename(pr->sip, oldname, newname);
784 UNLOCK;
785 mir_free(oldname);
786 mir_free(newname);
787 return 0;
790 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
791 gchar *oldgroup;
792 gchar *who = g_strdup(dbv.pszVal);
793 DBFreeVariant( &dbv );
795 if (oldgroup = sipe_miranda_getContactString(pr, hContact, "Group"))
797 SIPE_DEBUG_INFO("Moving buddy <%s> from group <%ls> to group <%ls>", who, oldgroup, gi->pszNewName);
798 LOCK;
799 sipe_core_buddy_group(pr->sip, who, oldgroup, TCHAR2CHAR(gi->pszNewName));
800 UNLOCK;
801 mir_free(oldgroup);
802 } else {
803 gchar *name = mir_t2a(gi->pszNewName);
805 if (!g_str_has_prefix(name, "sip:")) {
806 gchar *newname = sip_uri_from_name(name);
807 mir_free(name);
808 name = mir_strdup(newname);
809 g_free(newname);
812 SIPE_DEBUG_INFO("Really adding buddy <%s> to list in group <%s>", who, name);
813 LOCK;
814 sipe_core_buddy_add(pr->sip, who, name);
815 UNLOCK;
816 mir_free(name);
819 g_free(who);
822 return TRUE;
825 static int sipe_miranda_build_chat_menu(SIPPROTO *pr, WPARAM w, LPARAM lParam )
827 GCMENUITEMS *gcmi= (GCMENUITEMS*) lParam;
829 if (gcmi->Type == MENU_ON_NICKLIST)
831 static struct gc_item Item[] = {
832 {"&Make Leader", 1, MENU_ITEM, FALSE},
835 gcmi->nItems = sizeof(Item)/sizeof(Item[0]);
836 gcmi->Item = &Item[0];
839 return 0;
842 static int OnChatEvent(SIPPROTO *pr, WPARAM w, LPARAM l )
844 GCHOOK *hook = (GCHOOK*)l;
845 GCDEST *dst = hook->pDest;
847 if (dst->iType == GC_USER_MESSAGE) {
848 GCDEST gcd = {0};
849 GCEVENT gce = {0};
850 struct sipe_chat_session *session;
852 gcd.pszModule = pr->proto.m_szModuleName;
853 gcd.pszID = dst->pszID;
854 gcd.iType = GC_EVENT_GETITEMDATA;
856 gce.cbSize = sizeof(gce);
857 gce.pDest = &gcd;
860 if ((session = (struct sipe_chat_session*)CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)
862 SIPE_DEBUG_WARNING_NOFORMAT("Failed to get chat session");
863 return 0;
866 LOCK;
867 sipe_core_chat_send(pr->sip, session, hook->pszText);
868 UNLOCK;
870 return TRUE;
871 } else if (dst->iType == GC_USER_PRIVMESS) {
872 } else if (dst->iType == GC_USER_NICKLISTMENU) {
873 if (hook->dwData == 1)
875 SIPE_DEBUG_INFO("make leader <%s>", hook->pszUID);
879 return FALSE;
882 int OnPreBuildContactMenu(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
884 HANDLE hContact = (HANDLE)wParam;
885 int chatcount = CallService(MS_GC_GETSESSIONCOUNT, 0, (LPARAM)pr->proto.m_szModuleName);
886 int idx;
887 CLISTMENUITEM mi = {0};
888 GC_INFO gci = {0};
889 gpointer tmp;
891 mi.cbSize = sizeof(mi);
892 gci.pszModule = pr->proto.m_szModuleName;
894 /* Remove the old list */
895 while (pr->contactMenuChatItems)
897 SIPE_DEBUG_INFO("Removing old menuitem <%08x>", pr->contactMenuChatItems->data);
898 CallService(MS_CLIST_REMOVECONTACTMENUITEM, (WPARAM)pr->contactMenuChatItems->data, 0);
899 pr->contactMenuChatItems = g_slist_remove(pr->contactMenuChatItems, pr->contactMenuChatItems->data);
902 /* Add the main entry */
903 mi.pszName = "Invite to chat";
904 mi.flags = CMIF_NOTOFFLINE;
905 mi.position = 20;
906 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
907 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
909 mi.pszName = "New chat";
910 mi.hParentMenu = pr->contactMenuChatItems->data;
911 mi.flags = CMIF_ROOTHANDLE;
912 mi.popupPosition = 0;
913 mi.position=-10;
914 mi.pszService = g_strdup_printf("%s/StartChat", pr->proto.m_szModuleName);
915 mi.pszContactOwner = pr->proto.m_szModuleName;
916 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
917 g_free(mi.pszService);
918 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
920 for (idx=0 ; idx<chatcount ; idx++)
922 SIPE_DEBUG_INFO("Chat <%d> Menuitem <%08x>", idx, pr->contactMenuChatItems);
923 gci.iItem = idx;
924 gci.Flags = BYINDEX | NAME | ID;
925 if(!CallServiceSync( MS_GC_GETINFO, 0, (LPARAM)&gci )) {
926 SIPE_DEBUG_INFO("Chat <%s>", gci.pszName);
928 mi.pszName = gci.pszName;
929 mi.hParentMenu = pr->contactMenuChatItems->data;
930 mi.flags = CMIF_ROOTHANDLE;
931 mi.popupPosition = g_strdup(gci.pszID);
932 mi.position = idx;
933 mi.pszService = g_strdup_printf("%s/InviteToChat", pr->proto.m_szModuleName);
934 mi.pszContactOwner = pr->proto.m_szModuleName;
935 tmp = (gpointer)CallService(MS_CLIST_ADDCONTACTMENUITEM, 0, (LPARAM)&mi);
936 g_free(mi.pszService);
937 pr->contactMenuChatItems = g_slist_append(pr->contactMenuChatItems, tmp);
941 return 0;
944 INT_PTR SvcCreateAccMgrUI(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
946 return (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ACCMGRUI), (HWND)lParam, DlgProcAccMgrUI, (LPARAM)pr);
951 * Miranda service functions
953 * The functions in our plugin that get called directly by core Miranda
955 static DWORD_PTR GetCaps( SIPPROTO *pr, int type, HANDLE hContact )
957 switch (type) {
958 case PFLAGNUM_1:
959 return PF1_IM | PF1_CHAT | PF1_FILE | PF1_MODEMSG
960 | PF1_SERVERCLIST | PF1_ADDED
961 | PF1_BASICSEARCH | PF1_ADDSEARCHRES
962 | PF1_SEARCHBYEMAIL | PF1_USERIDISEMAIL
963 | PF1_SEARCHBYNAME | PF1_EXTSEARCH
966 case PFLAGNUM_2:
967 return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY
968 | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND
969 | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;
971 case PFLAGNUM_3:
972 return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY
973 | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND
974 | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;
976 case PFLAGNUM_4:
977 return PF4_NOCUSTOMAUTH | PF4_IMSENDUTF | PF4_SUPPORTTYPING
978 | PF4_SUPPORTIDLE;
980 case PFLAGNUM_5:
981 return 0;
983 case PFLAG_UNIQUEIDSETTING:
984 return (DWORD_PTR) SIP_UNIQUEID;
985 break;
986 default:
987 SIPE_DEBUG_INFO("GetCaps: unknown type <%x>", type);
991 return 0;
994 static HICON GetIcon( SIPPROTO *pr, int iconIndex )
996 SIPE_DEBUG_INFO("GetIcon: unknown index <%x>", iconIndex);
997 return NULL;
1000 static int OnEvent( SIPPROTO *pr, PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam )
1002 SIPE_DEBUG_INFO("OnEvent: type <%x>", eventType);
1004 switch (eventType)
1006 case EV_PROTO_ONLOAD:
1007 OnModulesLoaded(pr);
1008 break;
1010 case EV_PROTO_ONREADYTOEXIT:
1011 break;
1013 case EV_PROTO_ONEXIT:
1014 break;
1016 case EV_PROTO_ONRENAME:
1017 break;
1019 case EV_PROTO_ONOPTIONS:
1020 return OnOptionsInit( pr, wParam, lParam );
1021 break;
1023 case EV_PROTO_ONERASE:
1024 break;
1028 return 0;
1031 static HANDLE AddToListByEvent( SIPPROTO *pr, int flags, int iContact, HANDLE hDbEvent )
1033 DBEVENTINFO dbei = {0};
1035 dbei.cbSize = sizeof(dbei);
1036 if ((dbei.cbBlob = CallService(MS_DB_EVENT_GETBLOBSIZE, (WPARAM)hDbEvent, 0)) == -1)
1037 return 0;
1039 dbei.pBlob = (PBYTE)_alloca(dbei.cbBlob + 1);
1040 dbei.pBlob[dbei.cbBlob] = '\0';
1042 if (CallService(MS_DB_EVENT_GET, (WPARAM)hDbEvent, (LPARAM)&dbei))
1043 return 0; // failed to get event
1045 if (strcmp(dbei.szModule, pr->proto.m_szModuleName))
1046 return 0; // this event is not ours
1048 _NIF();
1049 SIPE_DEBUG_INFO("AddToListByEvent: flags <%x> iContact <%x>", flags, iContact);
1050 return NULL;
1053 static int Authorize( SIPPROTO *pr, HANDLE hContact )
1055 _NIF();
1056 SIPE_DEBUG_INFO_NOFORMAT("Authorize");
1057 return 0;
1060 static int AuthDeny( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szReason )
1062 _NIF();
1063 SIPE_DEBUG_INFO("AuthDeny: reason <%s>", szReason);
1064 return 0;
1067 static int AuthRecv( SIPPROTO *pr, HANDLE hContact, PROTORECVEVENT* evt )
1069 _NIF();
1070 SIPE_DEBUG_INFO_NOFORMAT("AuthRecv");
1071 return 0;
1074 static int AuthRequest( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szMessage )
1076 _NIF();
1077 SIPE_DEBUG_INFO("AuthRequest: message <%s>", szMessage);
1078 return 0;
1081 static HANDLE ChangeInfo( SIPPROTO *pr, int iInfoType, void* pInfoData )
1083 _NIF();
1084 SIPE_DEBUG_INFO("ChangeInfo: infotype <%x>", iInfoType);
1085 return NULL;
1088 static int FileCancel( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer )
1090 _NIF();
1091 SIPE_DEBUG_INFO_NOFORMAT("FileCancel");
1092 return 0;
1095 static int FileResume( SIPPROTO *pr, HANDLE hTransfer, int* action, const PROTOCHAR** szFilename )
1097 _NIF();
1098 SIPE_DEBUG_INFO("FileResume: action <%x>", action);
1099 return 0;
1102 static HANDLE SearchBasic( SIPPROTO *pr, const PROTOCHAR* id )
1104 return NULL;
1107 static HWND CreateExtendedSearchUI( SIPPROTO *pr, HWND owner )
1109 return CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_SEARCHUI), (HWND)owner, NULL, (LPARAM)pr);
1112 static HANDLE AddToList( SIPPROTO *pr, int flags, PROTOSEARCHRESULT* psr )
1114 HANDLE hContact;
1115 gchar *id = g_strdup(TCHAR2CHAR(psr->id));
1117 /* Prepend sip: if needed */
1118 if (strncmp("sip:", id, 4)) {
1119 gchar *tmp = id;
1120 id = sip_uri_from_name(tmp);
1121 g_free(tmp);
1124 hContact = sipe_miranda_buddy_find(pr, id, NULL);
1125 if (hContact) {
1126 g_free(id);
1127 return hContact;
1130 hContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );
1131 CallService( MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)pr->proto.m_szModuleName );
1132 sipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, id ); // name
1133 if (psr->nick)
1135 /* server_alias */
1136 gchar *tmp = mir_t2a(psr->nick);
1137 sipe_miranda_setContactStringUtf( pr, hContact, "Nick", tmp );
1138 mir_free(tmp);
1141 g_free(id);
1142 return hContact;
1146 sipe_miranda_window_closed(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
1148 MessageWindowEventData* evt = (MessageWindowEventData*)lParam;
1150 SIPE_DEBUG_INFO("contact <%08x> module <%s> type <%02x> flags <%02x>",
1151 evt->hContact, evt->szModule, evt->uType, evt->uFlags);
1153 return 0;
1156 static int
1157 sipe_miranda_invite_to_chat(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
1159 HANDLE hContact = (HANDLE)wParam;
1160 gchar *id = (gchar*)lParam;
1161 GCDEST gcd = {0};
1162 GCEVENT gce = {0};
1163 struct sipe_chat_session *session;
1164 gchar *uid;
1166 gcd.pszModule = pr->proto.m_szModuleName;
1167 gcd.pszID = id;
1168 gcd.iType = GC_EVENT_GETITEMDATA;
1170 gce.cbSize = sizeof(gce);
1171 gce.pDest = &gcd;
1173 if ((session = (struct sipe_chat_session*)CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)
1175 SIPE_DEBUG_WARNING_NOFORMAT("Failed to get chat session");
1176 return 0;
1179 uid = sipe_miranda_getContactString(pr, hContact, SIP_UNIQUEID);
1180 sipe_core_chat_invite(pr->sip, session, uid);
1182 mir_free(uid);
1183 g_free(id);
1184 return 0;
1188 * Main Miranda interface
1190 * The structures and functions that allow Miranda to recovnize and load
1191 * our plugin.
1194 /* Plugin information structure */
1195 PLUGININFOEX pluginInfo = {
1196 sizeof(PLUGININFOEX),
1197 "Office Communicator Protocol",
1198 PLUGIN_MAKE_VERSION(0,11,2,1),
1199 "Support for Microsoft Office Communicator",
1200 "Miranda support by Jochen De Smet, for core sipe support see homepage",
1201 "jochen.libsipe@leahnim.org",
1202 "(C)2009-2011",
1203 "https://sourceforge.net/projects/sipe",
1204 UNICODE_AWARE,
1205 0, //doesn't replace anything built-in
1206 #if defined( _UNICODE )
1207 { 0x842395ed, 0x4e56, 0x40e5, { 0x94, 0x25, 0x28, 0x29, 0xd8, 0xab, 0xae, 0xa5 } } // {842395ED-4E56-40e5-9425-2829D8ABAEA5}
1208 #else
1209 { 0x1ef8af37, 0xdec1, 0x4757, { 0x89, 0x78, 0xe8, 0xad, 0xd0, 0xd8, 0x6e, 0x7f } } // {1EF8AF37-DEC1-4757-8978-E8ADD0D86E7F}
1210 #endif
1213 __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
1215 // Only load for 0.8.0.29 or greater
1216 // We need the core stubs for PS_GETNAME and PS_GETSTATUS
1217 if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 9, 0, 0))
1219 MessageBoxA(
1220 NULL,
1221 "SIP/Simple plugin cannot be loaded. It requires Miranda IM 0.9.0.0 or later.",
1222 "SIP/Simple Plugin",
1223 MB_OK | MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST
1225 return NULL;
1228 return &pluginInfo;
1231 static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST};
1232 __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
1234 return interfaces;
1237 static PROTO_INTERFACE* sipsimpleProtoInit( const char* pszProtoName, const TCHAR* tszUserName )
1239 gchar *tmp;
1240 SIPPROTO *pr = (SIPPROTO *)mir_calloc(sizeof(SIPPROTO));
1241 pr->proto.vtbl = (PROTO_INTERFACE_VTBL*)mir_calloc(sizeof(PROTO_INTERFACE_VTBL));
1243 SIPE_DEBUG_INFO("protoname <%s> username <%ls>", pszProtoName, tszUserName);
1245 if (!InitializeCriticalSectionAndSpinCount(&pr->CriticalSection, 0))
1247 SIPE_DEBUG_ERROR_NOFORMAT("Can't initialize critical section");
1248 return NULL;
1251 tmp = sipe_miranda_getString(pr, "transport");
1252 if (!tmp)
1254 sipe_miranda_setString(pr, "transport", "auto");
1255 } else {
1256 mir_free(tmp);
1259 /* To make it easy to detect when a SIPPROTO* isn't a SIPPROTO* */
1260 strncpy(pr->_SIGNATURE, "AbandonAllHope..", sizeof(pr->_SIGNATURE));
1262 pr->main_thread_id = GetCurrentThreadId();
1263 pr->proto.m_iVersion = 2;
1264 pr->proto.m_szModuleName = mir_strdup(pszProtoName);
1265 pr->proto.m_tszUserName = mir_tstrdup(tszUserName);
1266 pr->proto.m_szProtoName = mir_strdup(pszProtoName);
1268 // set_buddies_offline(pr);
1269 fix_contact_groups(pr);
1271 /* Fill the function table */
1272 #define PROTO_FUNC(name,func) ((struct sipe_backend_private)(pr->proto)).vtbl->name = func;
1274 pr->proto.vtbl->AddToList = AddToList;
1275 pr->proto.vtbl->AddToListByEvent = AddToListByEvent;
1277 pr->proto.vtbl->Authorize = Authorize;
1278 pr->proto.vtbl->AuthDeny = AuthDeny;
1279 pr->proto.vtbl->AuthRecv = AuthRecv;
1280 pr->proto.vtbl->AuthRequest = AuthRequest;
1282 pr->proto.vtbl->ChangeInfo = ChangeInfo;
1284 pr->proto.vtbl->FileAllow = sipe_miranda_FileAllow;
1285 pr->proto.vtbl->FileCancel = FileCancel;
1286 pr->proto.vtbl->FileDeny = sipe_miranda_FileDeny;
1287 pr->proto.vtbl->FileResume = FileResume;
1289 pr->proto.vtbl->GetCaps = GetCaps;
1290 pr->proto.vtbl->GetIcon = GetIcon;
1291 pr->proto.vtbl->GetInfo = sipe_miranda_GetInfo;
1293 pr->proto.vtbl->SearchBasic = SearchBasic;
1294 pr->proto.vtbl->SearchByEmail = sipe_miranda_SearchByEmail;
1295 pr->proto.vtbl->SearchByName = sipe_miranda_SearchByName;
1296 pr->proto.vtbl->SearchAdvanced = sipe_miranda_SearchAdvanced;
1297 pr->proto.vtbl->CreateExtendedSearchUI = CreateExtendedSearchUI;
1299 pr->proto.vtbl->RecvMsg = sipe_miranda_RecvMsg;
1301 pr->proto.vtbl->SendMsg = sipe_miranda_SendMsg;
1303 pr->proto.vtbl->SetStatus = sipe_miranda_SetStatus;
1305 pr->proto.vtbl->GetAwayMsg = sipe_miranda_GetAwayMsg;
1306 pr->proto.vtbl->SetAwayMsg = sipe_miranda_SetAwayMsg;
1308 pr->proto.vtbl->UserIsTyping = sipe_miranda_UserIsTyping;
1310 pr->proto.vtbl->SendFile = sipe_miranda_SendFile;
1311 pr->proto.vtbl->RecvFile = sipe_miranda_RecvFile;
1313 pr->proto.vtbl->OnEvent = OnEvent;
1315 /* Setup services */
1316 CreateProtoService(pr, PS_CREATEACCMGRUI, &SvcCreateAccMgrUI );
1317 CreateProtoService(pr, "/InviteToChat", &sipe_miranda_invite_to_chat);
1318 CreateProtoService(pr, "/StartChat",&sipe_miranda_start_chat);
1320 #define HOOKEVENT(evt,func) HookEventObj(evt, func, pr)
1321 HOOKEVENT(ME_OPT_INITIALISE, &OnOptionsInit);
1322 HOOKEVENT(ME_CLIST_GROUPCHANGE, &OnGroupChange);
1323 HOOKEVENT(ME_GC_EVENT, &OnChatEvent);
1324 HOOKEVENT(ME_CLIST_PREBUILDCONTACTMENU, &OnPreBuildContactMenu);
1325 HOOKEVENT(ME_DB_CONTACT_DELETED, &sipe_miranda_buddy_delete);
1326 HOOKEVENT(ME_MSG_WINDOWEVENT, &sipe_miranda_window_closed);
1327 HOOKEVENT(ME_GC_BUILDMENU, &sipe_miranda_build_chat_menu);
1329 return (PROTO_INTERFACE*)pr;
1332 static int sipsimpleProtoUninit( PROTO_INTERFACE* _pr )
1334 SIPPROTO *pr = (SIPPROTO *)_pr;
1336 DeleteCriticalSection(&pr->CriticalSection);
1338 Netlib_CloseHandle(pr->m_hServerNetlibUser);
1339 mir_free(pr->proto.m_szProtoName);
1340 mir_free(pr->proto.m_szModuleName);
1341 mir_free(pr->proto.m_tszUserName);
1342 mir_free(pr->proto.vtbl);
1343 mir_free(pr);
1345 return 0;
1348 __declspec(dllexport) int Load(PLUGINLINK *link)
1350 PROTOCOLDESCRIPTOR pd = {0};
1351 NETLIBUSER nlu = {0};
1352 char *tmp;
1353 WORD iptype;
1355 pluginLink = link;
1357 sipe_core_init("");
1359 mir_getMMI( &mmi );
1361 /* Register the module */
1362 pd.cbSize = sizeof(pd);
1363 pd.szName = SIPSIMPLE_PROTOCOL_NAME;
1364 pd.type = PROTOTYPE_PROTOCOL;
1365 pd.fnInit = sipsimpleProtoInit;
1366 pd.fnUninit = sipsimpleProtoUninit;
1367 CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
1369 /* Protocolwide netlib user for incoming connections (also abused for logging) */
1370 nlu.cbSize = sizeof(nlu);
1371 nlu.flags = NUF_INCOMING | NUF_TCHAR | NUF_NOOPTIONS;
1372 nlu.szSettingsModule = SIPSIMPLE_PROTOCOL_NAME;
1373 nlu.minIncomingPorts = 10;
1375 InitializeCriticalSectionAndSpinCount(&sipe_miranda_debug_CriticalSection, 0);
1376 sipe_miranda_incoming_netlibuser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
1378 tmp = sipe_miranda_getGlobalString("public_ip");
1379 if (!tmp) {
1380 sipe_miranda_setGlobalString("public_ip", "0.0.0.0");
1381 } else {
1382 mir_free(tmp);
1385 if (!sipe_miranda_getGlobalWord("iptype", &iptype))
1387 sipe_miranda_setGlobalWord("iptype", SIPE_MIRANDA_IP_LOCAL);
1390 return 0;
1393 __declspec(dllexport) int Unload(void)
1395 Netlib_CloseHandle(sipe_miranda_incoming_netlibuser);
1396 sipe_miranda_incoming_netlibuser = NULL;
1397 DeleteCriticalSection(&sipe_miranda_debug_CriticalSection);
1398 sipe_core_destroy();
1399 return 0;
1402 BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
1404 hInst = hinstDLL;
1405 return TRUE;
1409 Local Variables:
1410 mode: c
1411 c-file-style: "bsd"
1412 indent-tabs-mode: t
1413 tab-width: 8
1414 End: