Sync up miranda files with current libsipe branch
[siplcs.git] / src / miranda / miranda-plugin.c
blobe6f0e22eedcbc069b855637b81083b9e7b181d8e
1 /**
2 * @file miranda-plugin.c
4 * pidgin-sipe
6 * Copyright (C) 2010 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 #define MIRANDA_VER 0x900
24 #include <windows.h>
25 #include <win2k.h>
26 #include <Richedit.h>
27 #include <stdio.h>
29 #include <glib.h>
31 #include "sipe-common.h"
33 #include "newpluginapi.h"
34 #include "m_protosvc.h"
35 #include "m_protoint.h"
36 #include "m_protomod.h"
37 #include "m_system.h"
38 #include "m_database.h"
39 #include "m_options.h"
40 #include "m_netlib.h"
41 #include "m_chat.h"
42 #include "m_clist.h"
43 #include "m_langpack.h"
45 #include "libsipe.h"
46 #include "sipe-backend.h"
47 #include "sipe-core.h"
48 #include "sipe-core-private.h"
49 #include "sipe-nls.h"
50 #include "sipe-conf.h"
51 #include "sipe-utils.h"
52 #include "sipe-session.h"
53 #include "sipe-chat.h"
54 #include "sipe.h"
55 #include "miranda-private.h"
56 #include "miranda-resource.h"
58 HANDLE sipe_miranda_debug_netlibuser = NULL;
60 /* Sipe core activity <-> Miranda status mapping */
61 static const gchar * const activity_to_miranda[SIPE_ACTIVITY_NUM_TYPES] = {
62 /* SIPE_ACTIVITY_UNSET */ "unset",
63 /* SIPE_ACTIVITY_ONLINE */ "online",
64 /* SIPE_ACTIVITY_INACTIVE */ "idle",
65 /* SIPE_ACTIVITY_BUSY */ "busy",
66 /* SIPE_ACTIVITY_BUSYIDLE */ "busyidle",
67 /* SIPE_ACTIVITY_DND */ "do-not-disturb",
68 /* SIPE_ACTIVITY_BRB */ "be-right-back",
69 /* SIPE_ACTIVITY_AWAY */ "away",
70 /* SIPE_ACTIVITY_LUNCH */ "out-to-lunch",
71 /* SIPE_ACTIVITY_OFFLINE */ "offline",
72 /* SIPE_ACTIVITY_ON_PHONE */ "on-the-phone",
73 /* SIPE_ACTIVITY_IN_CONF */ "in-a-conference",
74 /* SIPE_ACTIVITY_IN_MEETING */ "in-a-meeting",
75 /* SIPE_ACTIVITY_OOF */ "out-of-office",
76 /* SIPE_ACTIVITY_URGENT_ONLY */ "urgent-interruptions-only",
78 GHashTable *miranda_to_activity = NULL;
79 #define MIRANDA_STATUS_TO_ACTIVITY(x) \
80 GPOINTER_TO_UINT(g_hash_table_lookup(miranda_to_activity, (x)))
82 static void sipe_miranda_activity_init(void)
84 sipe_activity index = SIPE_ACTIVITY_UNSET;
85 miranda_to_activity = g_hash_table_new(g_str_hash, g_str_equal);
86 while (index < SIPE_ACTIVITY_NUM_TYPES) {
87 g_hash_table_insert(miranda_to_activity,
88 (gpointer) activity_to_miranda[index],
89 GUINT_TO_POINTER(index));
90 index++;
94 gchar *sipe_backend_version(void)
96 char version[200];
98 if (CallService(MS_SYSTEM_GETVERSIONTEXT, sizeof(version), (LPARAM)version)) {
99 strcpy(version, "Unknown");
102 return g_strdup_printf("Miranda %s SipSimple " __DATE__ " " __TIME__, version );
105 static void sipe_miranda_activity_destroy(void)
107 g_hash_table_destroy(miranda_to_activity);
108 miranda_to_activity = NULL;
112 * Miranda globals
114 * Global variables related to miranda core or UI
116 static BOOL (WINAPI *pfnEnableThemeDialogTexture)(HANDLE, DWORD) = 0;
117 HINSTANCE hInst;
118 PLUGINLINK* pluginLink;
119 struct MM_INTERFACE mmi;
122 * Dialog boxes
124 INT_PTR CALLBACK DlgProcSipSimpleOptsAbout(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
127 switch(msg)
129 case WM_INITDIALOG:
131 const SIPPROTO *pr = (const SIPPROTO *)lParam;
132 gchar *about = sipe_core_about();
133 SETTEXTEX tex;
135 TranslateDialogDefault(hwndDlg);
137 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
139 tex.flags = ST_DEFAULT;
140 tex.codepage = 437;
142 // SendDlgItemMessage(hwndDlg, IDC_ABOUTSIPE, EM_SETTEXTEX, (WPARAM)&tex, (LPARAM)about_txt );
143 SendDlgItemMessage(hwndDlg, IDC_ABOUTSIPE, EM_SETTEXTEX, (WPARAM)&tex, (LPARAM)about );
145 g_free(about);
149 return FALSE;
152 static INT_PTR CALLBACK DlgProcSipSimpleOpts(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
154 static int lock=0;
156 switch(msg)
158 case WM_INITDIALOG:
160 const SIPPROTO *pr = (const SIPPROTO *)lParam;
161 char *str;
163 TranslateDialogDefault(hwndDlg);
165 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
167 lock++;
169 str = DBGetString( NULL, SIPSIMPLE_PROTOCOL_NAME, "debuglog");
170 SetDlgItemTextA(hwndDlg, IDC_DEBUGLOG, str);
171 SendDlgItemMessage(hwndDlg, IDC_DEBUGLOG, EM_SETLIMITTEXT, 100, 0);
172 mir_free(str);
174 str = sipe_miranda_getString(pr, "username");
175 SetDlgItemTextA(hwndDlg, IDC_HANDLE, str);
176 SendDlgItemMessage(hwndDlg, IDC_HANDLE, EM_SETLIMITTEXT, 50, 0);
177 mir_free(str);
179 str = sipe_miranda_getString(pr, "login");
180 SetDlgItemTextA(hwndDlg, IDC_LOGIN, str);
181 SendDlgItemMessage(hwndDlg, IDC_LOGIN, EM_SETLIMITTEXT, 50, 0);
182 mir_free(str);
184 str = sipe_miranda_getString(pr, "password");
185 if (str) CallService(MS_DB_CRYPT_DECODESTRING, strlen(str),(LPARAM)str);
186 SetDlgItemTextA(hwndDlg, IDC_PASSWORD, str);
187 SendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_SETLIMITTEXT, 16, 0);
188 mir_free(str);
190 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("Auto"));
191 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("SSL/TLS"));
192 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_ADDSTRING, 0, (LPARAM)_T("TCP"));
194 str = sipe_miranda_getString(pr, "transport");
195 if (!str || !strcmp(str, "auto"))
196 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("Auto"));
197 else if (!strcmp(str, "tls"))
198 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("SSL/TLS"));
199 else if (!strcmp(str, "tcp"))
200 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, CB_SELECTSTRING, -1, (LPARAM)_T("TCP"));
202 lock--;
203 return TRUE;
206 case WM_COMMAND:
208 int code = wParam >> 16;
209 int id = wParam & 0xffff;
211 if (!lock && (code == EN_CHANGE || code == CBN_SELCHANGE)) {
212 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
214 return TRUE;
217 case WM_NOTIFY:
219 if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
221 char buf[100];
222 TCHAR tbuf[100];
224 const SIPPROTO *pr = (const SIPPROTO *)GetWindowLongPtr(hwndDlg, GWLP_USERDATA);
226 GetDlgItemTextA(hwndDlg, IDC_DEBUGLOG, buf, sizeof(buf));
227 DBWriteContactSettingString(NULL, SIPSIMPLE_PROTOCOL_NAME, "debuglog", buf);
229 GetDlgItemTextA(hwndDlg, IDC_HANDLE, buf, sizeof(buf));
230 sipe_miranda_setString(pr, "username", buf);
232 GetDlgItemTextA(hwndDlg, IDC_LOGIN, buf, sizeof(buf));
233 sipe_miranda_setString(pr, "login", buf);
235 GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf));
236 CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf),(LPARAM)buf);
237 sipe_miranda_setString(pr, "password", buf);
239 SendDlgItemMessage(hwndDlg, IDC_CONNTYPE, WM_GETTEXT, 100, (LPARAM)tbuf );
241 if (!_tcscmp(tbuf, _T("Auto")))
242 sipe_miranda_setString(pr, "transport", "auto");
243 else if (!_tcscmp(tbuf, _T("SSL/TLS")))
244 sipe_miranda_setString(pr, "transport", "tls");
245 else if (!_tcscmp(tbuf, _T("TCP")))
246 sipe_miranda_setString(pr, "transport", "tcp");
248 return TRUE;
250 return TRUE;
255 return FALSE;
258 INT_PTR CALLBACK DlgProcAccMgrUI(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
260 switch(msg)
262 case WM_INITDIALOG:
264 const SIPPROTO *pr = (const SIPPROTO *)lParam;
265 char *str;
267 TranslateDialogDefault(hwndDlg);
269 SetWindowLongPtr(hwndDlg, GWLP_USERDATA, lParam);
272 str = sipe_miranda_getString(pr, "username");
273 SetDlgItemTextA(hwndDlg, IDC_HANDLE, str);
274 mir_free(str);
276 str = sipe_miranda_getString(pr, "login");
277 SetDlgItemTextA(hwndDlg, IDC_LOGIN, str);
278 mir_free(str);
280 str = sipe_miranda_getString(pr, "password");
281 if (str) CallService(MS_DB_CRYPT_DECODESTRING, strlen(str),(LPARAM)str);
282 SetDlgItemTextA(hwndDlg, IDC_PASSWORD, str);
283 mir_free(str);
285 SendDlgItemMessage(hwndDlg, IDC_HANDLE, EM_SETLIMITTEXT, 50, 0);
286 SendDlgItemMessage(hwndDlg, IDC_LOGIN, EM_SETLIMITTEXT, 50, 0);
287 SendDlgItemMessage(hwndDlg, IDC_PASSWORD, EM_SETLIMITTEXT, 16, 0);
289 return TRUE;
292 case WM_COMMAND:
293 if (HIWORD(wParam) == EN_CHANGE && (HWND)lParam == GetFocus())
295 switch(LOWORD(wParam))
297 case IDC_HANDLE:
298 case IDC_LOGIN:
299 case IDC_PASSWORD:
300 SendMessage(GetParent(hwndDlg), PSM_CHANGED, 0, 0);
303 break;
305 case WM_NOTIFY:
306 if (((LPNMHDR)lParam)->code == (UINT)PSN_APPLY)
308 char buf[100];
310 const SIPPROTO *pr = (const SIPPROTO *)lParam;
312 GetDlgItemTextA(hwndDlg, IDC_HANDLE, buf, sizeof(buf));
313 sipe_miranda_setString(pr, "username", buf);
315 GetDlgItemTextA(hwndDlg, IDC_LOGIN, buf, sizeof(buf));
316 sipe_miranda_setString(pr, "login", buf);
318 GetDlgItemTextA(hwndDlg, IDC_PASSWORD, buf, sizeof(buf));
319 CallService(MS_DB_CRYPT_ENCODESTRING, sizeof(buf),(LPARAM)buf);
320 sipe_miranda_setString(pr, "password", buf);
322 return TRUE;
324 break;
327 return FALSE;
332 * Miranda service support functions
334 * Functions called by our service functions
336 static void set_if_defined(SIPPROTO *pr, GHashTable *store, HANDLE hContact, sipe_buddy_info_fields field, char *label)
338 char *value = (char *)g_hash_table_lookup(store, (gpointer)field);
339 if (value)
340 sipe_miranda_setContactStringUtf(pr, hContact, label, value);
343 static INT_PTR StartChat(SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
345 HANDLE hContact = (HANDLE)wParam;
346 struct sipe_core_public *sipe_public = pr->sip;
347 struct sipe_core_private *sipe_private = SIPE_CORE_PRIVATE;
349 DBVARIANT dbv;
350 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
351 if (SIPE_CORE_PRIVATE_FLAG_IS(OCS2007))
353 sipe_conf_add(sipe_private, dbv.pszVal);
355 else /* 2005- multiparty chat */
357 gchar *self = sip_uri_self(sipe_private);
358 struct sip_session *session;
360 session = sipe_session_add_chat(sipe_private,
361 NULL,
362 TRUE,
363 self);
364 session->chat_session->backend = sipe_backend_chat_create(SIPE_CORE_PUBLIC,
365 session->chat_session,
366 session->chat_session->title,
367 self);
368 g_free(self);
370 sipe_invite(sipe_private, session, dbv.pszVal, NULL, NULL, NULL, FALSE);
372 DBFreeVariant( &dbv );
373 return TRUE;
376 return FALSE;
379 static void OnModulesLoaded(SIPPROTO *pr)
381 TCHAR descr[MAX_PATH];
382 NETLIBUSER nlu = {0};
383 char service_name[200];
384 GCREGISTER gcr;
385 CLISTMENUITEM mi = {0};
387 SIPE_DEBUG_INFO_NOFORMAT("OnEvent::OnModulesLoaded");
389 nlu.cbSize = sizeof(nlu);
390 nlu.flags = NUF_OUTGOING | NUF_TCHAR;
391 nlu.szSettingsModule = pr->proto.m_szModuleName;
392 _sntprintf(descr, SIZEOF(descr), TranslateT("%s server connection"), pr->proto.m_tszUserName );
393 nlu.ptszDescriptiveName = descr;
395 pr->m_hServerNetlibUser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
397 mi.cbSize = sizeof( mi );
398 mi.pszContactOwner = pr->proto.m_szModuleName;
399 mi.pszService = service_name;
401 mir_snprintf(service_name, sizeof(service_name), "%s%s", pr->proto.m_szModuleName, "/StartChat");
402 CreateProtoService(pr, "/StartChat",&StartChat);
403 mi.position=-2000005060;
404 mi.icolibItem = NULL; //GetIconHandle("block");
405 mi.pszName = LPGEN("&Start Chat");
406 mi.flags=0; //CMIF_ICONFROMICOLIB|CMIF_HIDDEN;
407 CallService(MS_CLIST_ADDCONTACTMENUITEM,0,(LPARAM)&mi);
409 gcr.cbSize = sizeof(gcr);
410 gcr.dwFlags = 0;
411 gcr.pszModule = pr->proto.m_szModuleName;
412 gcr.pszModuleDispName = "Sip/Simple";
413 gcr.iMaxText = 0;
414 gcr.nColors = 0;
416 if (CallService(MS_GC_REGISTER, 0, (LPARAM)&gcr))
418 SIPE_DEBUG_INFO_NOFORMAT("OnEvent::OnModulesLoaded Failed to register chat");
423 int OnOptionsInit(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
425 OPTIONSDIALOGPAGE odp = {0};
426 HMODULE hUxTheme = 0;
428 if (IsWinVerXPPlus())
430 hUxTheme = GetModuleHandleA("uxtheme.dll");
431 if (hUxTheme)
432 pfnEnableThemeDialogTexture = (BOOL (WINAPI *)(HANDLE, DWORD))GetProcAddress(hUxTheme, "EnableThemeDialogTexture");
435 odp.cbSize = sizeof(odp);
436 odp.position = -800000000;
437 odp.hInstance = hInst;
438 odp.ptszGroup = LPGENT("Network");
439 odp.dwInitParam = (LPARAM)pr;
440 odp.ptszTitle = pr->proto.m_tszUserName;
441 odp.flags = ODPF_BOLDGROUPS | ODPF_TCHAR;
443 odp.ptszTab = LPGENT("Account");
444 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE);
445 odp.pfnDlgProc = DlgProcSipSimpleOpts;
446 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
448 odp.ptszTab = LPGENT("About");
449 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_SIPSIMPLE_ABOUT);
450 odp.pfnDlgProc = DlgProcSipSimpleOptsAbout;
451 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
453 #if 0
455 odp.ptszTab = LPGENT("Features");
456 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQFEATURES);
457 odp.pfnDlgProc = DlgProcIcqFeaturesOpts;
458 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
460 odp.ptszTab = LPGENT("Privacy");
461 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_ICQPRIVACY);
462 odp.pfnDlgProc = DlgProcIcqPrivacyOpts;
463 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
465 if (bPopUpService)
467 odp.position = 100000000;
468 odp.pszTemplate = MAKEINTRESOURCEA(IDD_OPT_POPUPS);
469 odp.groupPosition = 900000000;
470 odp.pfnDlgProc = DlgProcIcqPopupOpts;
471 odp.ptszGroup = LPGENT("Popups");
472 odp.ptszTab = NULL;
473 CallService( MS_OPT_ADDPAGE, wParam, ( LPARAM )&odp );
475 #endif
476 return 0;
479 static void sipe_miranda_close( SIPPROTO *pr)
481 struct sipe_core_public *sipe_public = pr->sip;
483 if (sipe_public) {
484 sipe_core_deallocate(sipe_public);
486 // sipe_purple_chat_destroy_rejoin(purple_private);
487 // g_free(purple_private);
491 static void set_buddies_offline(const SIPPROTO* pr)
493 HANDLE hContact;
495 hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDFIRST, 0, 0);
496 while (hContact) {
497 char* szProto = (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO, (WPARAM)hContact, 0);
498 if (szProto != NULL && !lstrcmpA(szProto, pr->proto.m_szModuleName)) {
499 if (DBGetContactSettingByte(hContact, pr->proto.m_szModuleName, "ChatRoom", 0) == 0)
500 DBWriteContactSettingWord(hContact, pr->proto.m_szModuleName, "Status", ID_STATUS_OFFLINE);
502 hContact = (HANDLE)CallService(MS_DB_CONTACT_FINDNEXT, (WPARAM)hContact, 0);
506 static void sipe_miranda_login(SIPPROTO *pr) {
507 gchar *username = sipe_miranda_getString(pr, "username");
508 gchar *login = sipe_miranda_getString(pr, "login");
509 gchar *email = sipe_miranda_getString(pr, "email");
510 gchar *email_url = sipe_miranda_getString(pr, "email_url");
511 gchar **domain_user = g_strsplit_set(login, "/\\", 2);
512 const gchar *errmsg;
513 gchar *password;
514 char *tmp = (char*)mir_calloc(1024);
516 if (sipe_miranda_getStaticString(pr, NULL, "password", tmp, 1024 )) tmp[0] = '\0';
517 CallService(MS_DB_CRYPT_DECODESTRING, sizeof(tmp),(LPARAM)tmp);
518 password = g_strdup(tmp);
519 mir_free(tmp);
521 pr->sip = sipe_core_allocate(username,
522 domain_user[0], domain_user[1],
523 password,
524 email,
525 email_url,
526 &errmsg);
528 pr->sip->backend_private = pr;
530 mir_free(username);
531 mir_free(login);
532 mir_free(email);
533 mir_free(email_url);
534 g_strfreev(domain_user);
535 g_free(password);
537 if (!pr->sip) {
538 /* FIXME: Flag connection error */
539 return;
542 //sipe_miranda_chat_setup_rejoin(pr);
544 #ifdef HAVE_LIBKRB5
545 // if (purple_account_get_bool(account, "krb5", FALSE))
546 // SIPE_CORE_FLAG_SET(KRB5);
547 #endif
548 // /* @TODO: is this correct?
549 // "sso" is only available when Kerberos support is compiled in */
550 // if (purple_account_get_bool(account, "sso", TRUE))
551 // SIPE_CORE_FLAG_SET(SSO);
553 /* Set display name */
554 sipe_miranda_setStringUtf(pr, "Nick", pr->sip->sip_name);
556 /* Update connection progress */
557 pr->proto.m_iStatus = ID_STATUS_CONNECTING;
558 SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)pr->proto.m_iStatus, ID_STATUS_CONNECTING);
561 username_split = g_strsplit(purple_account_get_string(account, "server", ""), ":", 2);
562 if (sipe_strequal(transport, "auto")) {
563 type = (username_split[0] == NULL) ?
564 SIPE_TRANSPORT_AUTO : SIPE_TRANSPORT_TLS;
565 } else if (sipe_strequal(transport, "tls")) {
566 type = SIPE_TRANSPORT_TLS;
567 } else {
568 type = SIPE_TRANSPORT_TCP;
571 sipe_core_transport_sip_connect(pr->sip,
572 type,
573 username_split[0],
574 username_split[0] ? username_split[1] : NULL);
575 g_strfreev(username_split);
577 sipe_core_transport_sip_connect(pr->sip,
578 SIPE_TRANSPORT_AUTO,
579 NULL,
580 NULL);
583 static gboolean
584 miranda_sipe_get_info_cb(struct sipe_core_public *sipe_public, const char* uri, GHashTable *results, void* data )
586 SIPPROTO *pr = sipe_public->backend_private;
587 HANDLE hContact = (HANDLE) data;
589 GHashTableIter iter;
590 const char *id, *value;
592 g_hash_table_iter_init( &iter, results);
593 while (g_hash_table_iter_next (&iter, (gpointer *)&id, (gpointer *)&value)) {
594 SIPE_DEBUG_INFO("miranda_sipe_get_info_cb: user info field <%d> = <%s>", id, value ? value : "(none)");
596 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_EMAIL, "e-mail");
597 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_CITY, "City");
598 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_STATE, "State");
599 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_COUNTRY, "Country");
600 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_COMPANY, "Company");
601 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_JOB_TITLE, "CompanyPosition");
602 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_WORK_PHONE, "CompanyPhone");
603 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_STREET, "CompanyStreet");
604 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_ZIPCODE, "CompanyZIP");
605 set_if_defined(pr, results, hContact, SIPE_BUDDY_INFO_DEPARTMENT, "CompanyDepartment");
607 SendBroadcast(pr, hContact, ACKTYPE_GETINFO, ACKRESULT_SUCCESS, (HANDLE) 1, (LPARAM) 0);
608 return TRUE;
611 void sipsimple_search_contact_cb( GList *columns, GList *results, GHashTable *opts, void *data )
613 SIPPROTO *pr = (SIPPROTO *)data;
614 GList *row, *col;
615 HANDLE hProcess = g_hash_table_lookup(opts, "searchid");
616 PROTOSEARCHRESULT psr = { 0 };
618 psr.cbSize = sizeof(psr);
620 row = results;
621 while (row)
623 col = (GList*)row->data;
624 psr.nick = (PROTOCHAR*)col->data;
626 col = g_list_next(col);
627 psr.lastName = (PROTOCHAR*)col->data;
629 col = g_list_next(col);
630 /* company */
632 col = g_list_next(col);
633 /* country */
635 col = g_list_next(col);
636 psr.email = (PROTOCHAR*)col->data;
638 row = g_list_next(row);
639 SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_DATA, hProcess, (LPARAM) & psr);
642 SendBroadcast(pr, NULL, ACKTYPE_SEARCH, ACKRESULT_SUCCESS, hProcess, 0);
646 static int OnGroupChange( const SIPPROTO *pr, WPARAM w, LPARAM l )
648 CLISTGROUPCHANGE *gi = (CLISTGROUPCHANGE*)l;
649 HANDLE hContact = (HANDLE)w;
650 DBVARIANT dbv;
651 char *who;
653 /* No contact => it's a group add/rename/remove */
654 if (!hContact)
656 /* No old name => add */
657 if (!gi->pszOldName)
659 return 0;
661 /* No new name => delete */
662 else if (!gi->pszNewName)
664 SIPE_DEBUG_INFO("Removing group <l%s>", gi->pszOldName);
665 sipe_remove_group(pr->sip, TCHAR2CHAR(gi->pszOldName));
666 return 0;
669 SIPE_DEBUG_INFO("Renaming group <%ls> to <%ls>", gi->pszOldName, gi->pszNewName);
670 sipe_rename_group(pr->sip, TCHAR2CHAR(gi->pszOldName), TCHAR2CHAR(gi->pszNewName));
671 return 0;
674 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
675 who = g_strdup(dbv.pszVal);
676 DBFreeVariant( &dbv );
678 if ( !DBGetContactSettingString( hContact, "Clist", "Group", &dbv )) {
679 SIPE_DEBUG_INFO("Moving buddy <%s> from group <%ls> to group <%ls>", who, dbv.pszVal, gi->pszNewName);
680 sipe_core_buddy_group(pr->sip, who, dbv.pszVal, TCHAR2CHAR(gi->pszNewName));
681 DBFreeVariant( &dbv );
682 } else {
683 const gchar *name = TCHAR2CHAR(gi->pszNewName);
684 const gchar *newname;
686 SIPE_DEBUG_INFO("Really adding buddy <%s> to list in group <%ls>", who, gi->pszNewName);
687 newname = sipe_core_buddy_add(pr->sip, who, name);
689 if (!sipe_strequal(name,newname))
691 sipe_miranda_setContactString( pr, hContact, SIP_UNIQUEID, newname);
695 g_free(who);
698 return TRUE;
701 static int OnChatEvent(const SIPPROTO *pr, WPARAM w, LPARAM l )
703 GCHOOK *hook = (GCHOOK*)l;
704 GCDEST *dst = hook->pDest;
706 if (dst->iType == GC_USER_MESSAGE) {
707 GCDEST gcd = {0};
708 GCEVENT gce = {0};
709 struct sipe_chat_session *session;
711 gcd.pszModule = pr->proto.m_szModuleName;
712 gcd.pszID = dst->pszID;
713 gcd.iType = GC_EVENT_GETITEMDATA;
715 gce.cbSize = sizeof(gce);
716 gce.pDest = &gcd;
719 if ((session = CallService( MS_GC_EVENT, 0, (LPARAM)&gce )) == NULL)
721 SIPE_DEBUG_WARNING_NOFORMAT("Failed to get chat session");
722 return 0;
725 sipe_core_chat_send(pr->sip, session, hook->pszText);
726 return TRUE;
727 } else if (dst->iType == GC_USER_PRIVMESS) {
730 return FALSE;
733 int OnPreBuildContactMenu(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
735 HANDLE hContact = (HANDLE)wParam;
737 return 0;
740 INT_PTR SvcCreateAccMgrUI(const SIPPROTO *pr, WPARAM wParam, LPARAM lParam)
742 return (INT_PTR)CreateDialogParam(hInst, MAKEINTRESOURCE(IDD_ACCMGRUI), (HWND)lParam, DlgProcAccMgrUI, (LPARAM)pr);
745 static void GetAwayMsgThread(SIPPROTO *pr, HANDLE hContact)
747 const gchar *status;
748 gchar *name = sipe_miranda_getContactString(pr, hContact, SIP_UNIQUEID);
749 gchar *tmp = NULL;
751 if (!name)
753 SIPE_DEBUG_INFO("Could not find name for contact <%08x>", hContact);
754 SendProtoAck(pr, hContact, 1, ACKRESULT_FAILED, ACKTYPE_AWAYMSG, NULL);
755 return;
758 status = sipe_core_buddy_status(pr->sip,
759 name,
760 SIPE_ACTIVITY_BUSYIDLE,
761 "dummy test string");
763 if (status)
764 tmp = sipe_miranda_eliminate_html(status, strlen(status));
766 SendProtoAck(pr, hContact, 1, ACKRESULT_SUCCESS, ACKTYPE_AWAYMSG, tmp);
768 mir_free(tmp);
769 mir_free(name);
774 * Miranda service functions
776 * The functions in our plugin that get called directly by core Miranda
778 static DWORD_PTR GetCaps( SIPPROTO *pr, int type, HANDLE hContact )
780 switch (type) {
781 case PFLAGNUM_1:
782 return PF1_IM | PF1_CHAT | PF1_FILE | PF1_MODEMSG
783 | PF1_SERVERCLIST | PF1_AUTHREQ | PF1_ADDED
784 | PF1_BASICSEARCH | PF1_ADDSEARCHRES
785 | PF1_SEARCHBYEMAIL | PF1_USERIDISEMAIL
786 | PF1_SEARCHBYNAME
789 case PFLAGNUM_2:
790 return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY
791 | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND
792 | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;
794 case PFLAGNUM_3:
795 return PF2_ONLINE | PF2_INVISIBLE | PF2_SHORTAWAY
796 | PF2_LONGAWAY | PF2_LIGHTDND | PF2_HEAVYDND
797 | PF2_OUTTOLUNCH | PF2_ONTHEPHONE | PF2_IDLE;
799 case PFLAGNUM_4:
800 return PF4_NOCUSTOMAUTH | PF4_IMSENDUTF | PF4_SUPPORTTYPING
801 | PF4_SUPPORTIDLE;
803 case PFLAGNUM_5:
804 return 0;
806 case PFLAG_UNIQUEIDSETTING:
807 return (DWORD_PTR) SIP_UNIQUEID;
808 break;
809 default:
810 SIPE_DEBUG_INFO("GetCaps: unknown type <%x>", type);
814 return NULL;
817 static HICON GetIcon( SIPPROTO *pr, int iconIndex )
819 SIPE_DEBUG_INFO("GetIcon: unknown index <%x>", iconIndex);
820 return NULL;
823 static int OnEvent( SIPPROTO *pr, PROTOEVENTTYPE eventType, WPARAM wParam, LPARAM lParam )
825 SIPE_DEBUG_INFO("OnEvent: type <%x>", eventType);
827 switch (eventType)
829 case EV_PROTO_ONLOAD:
830 OnModulesLoaded(pr);
831 break;
833 case EV_PROTO_ONREADYTOEXIT:
834 break;
836 case EV_PROTO_ONEXIT:
837 break;
839 case EV_PROTO_ONRENAME:
840 break;
842 case EV_PROTO_ONOPTIONS:
843 return OnOptionsInit( pr, wParam, lParam );
844 break;
846 case EV_PROTO_ONERASE:
847 break;
851 return 0;
854 static int SetStatus( SIPPROTO *pr, int iNewStatus )
856 int oldStatus;
857 if (!pr->m_hServerNetlibUser) return 0;
858 if (pr->proto.m_iDesiredStatus == iNewStatus) return 0;
860 oldStatus = pr->proto.m_iStatus;
861 pr->proto.m_iDesiredStatus = iNewStatus;
863 SIPE_DEBUG_INFO("SetStatus: newstatus <%x>", iNewStatus);
865 if (iNewStatus == ID_STATUS_OFFLINE) {
866 sipe_miranda_close(pr);
867 set_buddies_offline(pr);
868 pr->proto.m_iStatus = iNewStatus;
869 SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, iNewStatus);
870 } else {
871 gchar *note = sipe_miranda_getString(pr, "note");
872 if (pr->proto.m_iStatus == ID_STATUS_OFFLINE) {
873 sipe_miranda_login(pr);
875 pr->proto.m_iStatus = pr->proto.m_iDesiredStatus;
876 sipe_core_set_status(pr->sip, note, MirandaStatusToSipe(iNewStatus));
877 SendBroadcast(pr, NULL, ACKTYPE_STATUS, ACKRESULT_SUCCESS, (HANDLE)oldStatus, pr->proto.m_iStatus);
878 mir_free(note);
883 //Will send an ack with:
884 //type=ACKTYPE_STATUS, result=ACKRESULT_SUCCESS, hProcess=(HANDLE)previousMode, lParam=newMode
885 //when the change completes. This ack is sent for all changes, not just ones
886 //caused by calling this function.
887 //Note that newMode can be ID_STATUS_CONNECTING<=newMode<ID_STATUS_CONNECTING+
888 //MAX_CONNECT_RETRIES to signify that it's connecting and it's the nth retry.
889 //Protocols are initially always in offline mode.
890 //Non-network-level protocol modules do not have the concept of a status and
891 //should leave this service unimplemented
892 //If a protocol doesn't support the specific status mode, it should pick the
895 return 0;
898 static int UserIsTyping( SIPPROTO *pr, HANDLE hContact, int type )
900 SIPE_DEBUG_INFO("UserIsTyping: type <%x>", type);
901 if (hContact)
903 DBVARIANT dbv;
904 char *name;
906 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
907 name = g_strdup(dbv.pszVal);
908 DBFreeVariant(&dbv);
909 } else {
910 return 1;
913 switch (type) {
914 case PROTOTYPE_SELFTYPING_ON:
915 sipe_core_user_feedback_typing(pr->sip, name);
916 g_free(name);
917 return 0;
919 case PROTOTYPE_SELFTYPING_OFF:
920 /* Not supported anymore? */
921 g_free(name);
922 return 0;
925 g_free(name);
928 return 1;
931 static HANDLE AddToListByEvent( SIPPROTO *pr, int flags, int iContact, HANDLE hDbEvent )
933 _NIF();
934 SIPE_DEBUG_INFO("AddToListByEvent: flags <%x> iContact <%x>", flags, iContact);
935 return NULL;
938 static int Authorize( SIPPROTO *pr, HANDLE hContact )
940 _NIF();
941 SIPE_DEBUG_INFO_NOFORMAT("Authorize");
942 return 0;
945 static int AuthDeny( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szReason )
947 _NIF();
948 SIPE_DEBUG_INFO("AuthDeny: reason <%s>", szReason);
949 return 0;
952 static int AuthRecv( SIPPROTO *pr, HANDLE hContact, PROTORECVEVENT* evt )
954 _NIF();
955 SIPE_DEBUG_INFO_NOFORMAT("AuthRecv");
956 return 0;
959 static int AuthRequest( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szMessage )
961 _NIF();
962 SIPE_DEBUG_INFO("AuthRequest: message <%s>", szMessage);
963 return 0;
966 static HANDLE ChangeInfo( SIPPROTO *pr, int iInfoType, void* pInfoData )
968 _NIF();
969 SIPE_DEBUG_INFO("ChangeInfo: infotype <%x>", iInfoType);
970 return NULL;
973 static HANDLE FileAllow( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szPath )
975 _NIF();
976 SIPE_DEBUG_INFO("FileAllow: path <%s>", szPath);
977 return NULL;
980 static int FileCancel( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer )
982 _NIF();
983 SIPE_DEBUG_INFO_NOFORMAT("FileCancel");
984 return 0;
987 static int FileDeny( SIPPROTO *pr, HANDLE hContact, HANDLE hTransfer, const PROTOCHAR* szReason )
989 _NIF();
990 SIPE_DEBUG_INFO("FileDeny: reason <%s>", szReason);
991 return 0;
994 static int FileResume( SIPPROTO *pr, HANDLE hTransfer, int* action, const PROTOCHAR** szFilename )
996 _NIF();
997 SIPE_DEBUG_INFO("FileResume: action <%x>", action);
998 return 0;
1001 static int GetInfo( SIPPROTO *pr, HANDLE hContact, int infoType )
1003 DBVARIANT dbv;
1005 SIPE_DEBUG_INFO("GetInfo: infotype <%x>", infoType);
1007 if ( !DBGetContactSettingString( hContact, pr->proto.m_szModuleName, SIP_UNIQUEID, &dbv )) {
1008 sipe_get_info(pr->sip, dbv.pszVal, miranda_sipe_get_info_cb, hContact);
1009 DBFreeVariant( &dbv );
1012 return 0;
1015 static HANDLE SearchBasic( SIPPROTO *pr, const PROTOCHAR* id )
1017 return NULL;
1020 static HWND SearchAdvanced( SIPPROTO *pr, HWND owner )
1022 _NIF();
1023 return NULL;
1026 static HWND CreateExtendedSearchUI( SIPPROTO *pr, HWND owner )
1028 _NIF();
1029 return NULL;
1032 static HANDLE SearchByEmail( SIPPROTO *pr, const PROTOCHAR* email )
1034 GHashTable *query = g_hash_table_new(NULL,NULL);
1036 SIPE_DEBUG_INFO("SearchByEmail: email <%s>", email);
1038 g_hash_table_insert(query, "email", (gpointer)email);
1040 return (HANDLE)sipe_search_contact_with_cb( pr->sip, query, sipsimple_search_contact_cb, pr);
1044 static HANDLE SearchByName( SIPPROTO *pr, const PROTOCHAR* nick, const PROTOCHAR* firstName, const PROTOCHAR* lastName)
1046 GHashTable *query = g_hash_table_new(NULL,NULL);
1048 SIPE_DEBUG_INFO("SearchByName: nick <%s> firstname <%s> lastname <%s>", nick, firstName, lastName);
1050 g_hash_table_insert(query, "givenName", (gpointer)mir_t2a(firstName));
1051 g_hash_table_insert(query, "sn", (gpointer)mir_t2a(lastName));
1053 return (HANDLE)sipe_search_contact_with_cb( pr->sip, query, sipsimple_search_contact_cb, pr);
1056 static HANDLE AddToList( SIPPROTO *pr, int flags, PROTOSEARCHRESULT* psr )
1058 HANDLE hContact;
1059 gchar *nick = g_strdup(mir_t2a(psr->nick));
1061 /* Prepend sip: if needed */
1062 if (strncmp("sip:", nick, 4)) {
1063 gchar *tmp = nick;
1064 nick = sip_uri_from_name(tmp);
1065 g_free(tmp);
1068 hContact = sipe_backend_buddy_find(pr->sip, nick, NULL);
1069 if (hContact) {
1070 g_free(nick);
1071 return hContact;
1074 hContact = ( HANDLE )CallService( MS_DB_CONTACT_ADD, 0, 0 );
1075 CallService( MS_PROTO_ADDTOCONTACT, (WPARAM)hContact, (LPARAM)pr->proto.m_szModuleName );
1076 sipe_miranda_setString( hContact, SIP_UNIQUEID, nick ); // name
1077 if (psr->lastName) sipe_miranda_setStringUtf( hContact, "Nick", mir_t2a(psr->lastName) ); // server_alias
1079 g_free(nick);
1080 return hContact;
1083 static int SetAwayMsg( SIPPROTO *pr, int m_iStatus, const PROTOCHAR* msg )
1085 const gchar *note = TCHAR2CHAR(msg);
1087 SIPE_DEBUG_INFO("SetAwayMsg: status <%x> msg <%ls>", m_iStatus, msg);
1088 sipe_miranda_setString(pr, "note", note);
1089 if (pr->sip)
1090 sipe_core_set_status(pr->sip, note, MirandaStatusToSipe(pr->proto.m_iStatus));
1091 return 0;
1094 static HANDLE GetAwayMsg( SIPPROTO *pr, HANDLE hContact )
1096 ForkThread( pr, ( SipSimpleThreadFunc )&GetAwayMsgThread, hContact );
1097 return (HANDLE)1;
1100 static HANDLE SendFile( SIPPROTO *pr, HANDLE hContact, const PROTOCHAR* szDescription, PROTOCHAR** ppszFiles )
1102 _NIF();
1103 SIPE_DEBUG_INFO("SendFile: desc <%ls>", szDescription);
1104 return 0;
1109 * Main Miranda interface
1111 * The structures and functions that allow Miranda to recovnize and load
1112 * our plugin.
1115 /* Plugin information structure */
1116 PLUGININFOEX pluginInfo = {
1117 sizeof(PLUGININFOEX),
1118 "SIP/Simple Protocol",
1119 PLUGIN_MAKE_VERSION(9,12,19,12),
1120 "Support for SIP/Simple as used by Communicator 2007.",
1121 "Miranda support by Jochen De Smet, for core sipe support see homepage",
1122 "jochen.libsipe@leahnim.org",
1123 "(C)2009-2010",
1124 "https://sourceforge.net/projects/sipe",
1125 UNICODE_AWARE,
1126 0, //doesn't replace anything built-in
1127 #if defined( _UNICODE )
1128 { 0x842395ed, 0x4e56, 0x40e5, { 0x94, 0x25, 0x28, 0x29, 0xd8, 0xab, 0xae, 0xa5 } } // {842395ED-4E56-40e5-9425-2829D8ABAEA5}
1129 #else
1130 { 0x1ef8af37, 0xdec1, 0x4757, { 0x89, 0x78, 0xe8, 0xad, 0xd0, 0xd8, 0x6e, 0x7f } } // {1EF8AF37-DEC1-4757-8978-E8ADD0D86E7F}
1131 #endif
1134 __declspec(dllexport) PLUGININFOEX *MirandaPluginInfoEx(DWORD mirandaVersion)
1136 // Only load for 0.8.0.29 or greater
1137 // We need the core stubs for PS_GETNAME and PS_GETSTATUS
1138 if (mirandaVersion < PLUGIN_MAKE_VERSION(0, 9, 0, 0))
1140 MessageBoxA(
1141 NULL,
1142 "SIP/Simple plugin cannot be loaded. It requires Miranda IM 0.9.0.0 or later.",
1143 "SIP/Simple Plugin",
1144 MB_OK | MB_ICONWARNING | MB_SETFOREGROUND | MB_TOPMOST
1146 return NULL;
1149 return &pluginInfo;
1152 static const MUUID interfaces[] = {MIID_PROTOCOL, MIID_LAST};
1153 __declspec(dllexport) const MUUID* MirandaPluginInterfaces(void)
1155 return interfaces;
1158 static PROTO_INTERFACE* sipsimpleProtoInit( const char* pszProtoName, const TCHAR* tszUserName )
1160 SIPPROTO *pr = (SIPPROTO *)mir_calloc(sizeof(SIPPROTO));
1161 pr->proto.vtbl = (PROTO_INTERFACE_VTBL*)mir_calloc(sizeof(PROTO_INTERFACE_VTBL));
1163 SIPE_DEBUG_INFO("protoname <%s> username <%ls>", pszProtoName, tszUserName);
1165 pr->proto.m_iVersion = 2;
1166 pr->proto.m_szModuleName = mir_strdup(pszProtoName);
1167 pr->proto.m_tszUserName = mir_tstrdup(tszUserName);
1168 pr->proto.m_szProtoName = mir_strdup(pszProtoName);
1170 set_buddies_offline(pr);
1172 /* Fill the function table */
1173 pr->proto.vtbl->GetCaps = GetCaps;
1174 pr->proto.vtbl->GetIcon = GetIcon;
1175 pr->proto.vtbl->OnEvent = OnEvent;
1176 pr->proto.vtbl->SetStatus = SetStatus;
1177 pr->proto.vtbl->UserIsTyping = UserIsTyping;
1178 pr->proto.vtbl->SendMsg = sipe_miranda_SendMsg;
1179 pr->proto.vtbl->RecvMsg = sipe_miranda_RecvMsg;
1180 pr->proto.vtbl->AddToListByEvent = AddToListByEvent;
1181 pr->proto.vtbl->Authorize = Authorize;
1182 pr->proto.vtbl->AuthDeny = AuthDeny;
1183 pr->proto.vtbl->AuthRecv = AuthRecv;
1184 pr->proto.vtbl->AuthRequest = AuthRequest;
1185 pr->proto.vtbl->ChangeInfo = ChangeInfo;
1186 pr->proto.vtbl->FileAllow = FileAllow;
1187 pr->proto.vtbl->FileCancel = FileCancel;
1188 pr->proto.vtbl->FileDeny = FileDeny;
1189 pr->proto.vtbl->FileResume = FileResume;
1190 pr->proto.vtbl->GetInfo = GetInfo;
1191 pr->proto.vtbl->SearchBasic = SearchBasic;
1192 pr->proto.vtbl->SearchAdvanced = SearchAdvanced;
1193 pr->proto.vtbl->CreateExtendedSearchUI = CreateExtendedSearchUI;
1194 pr->proto.vtbl->SearchByEmail = SearchByEmail;
1195 pr->proto.vtbl->SearchByName = SearchByName;
1196 pr->proto.vtbl->AddToList = AddToList;
1197 pr->proto.vtbl->SetAwayMsg = SetAwayMsg;
1198 pr->proto.vtbl->GetAwayMsg = GetAwayMsg;
1200 /* Setup services */
1201 CreateProtoService(pr, PS_CREATEACCMGRUI, &SvcCreateAccMgrUI );
1203 HookProtoEvent(pr, ME_OPT_INITIALISE, &OnOptionsInit);
1204 HookProtoEvent(pr, ME_CLIST_GROUPCHANGE, &OnGroupChange );
1205 HookProtoEvent(pr, ME_GC_EVENT, &OnChatEvent );
1206 HookProtoEvent(pr, ME_CLIST_PREBUILDCONTACTMENU, &OnPreBuildContactMenu );
1208 return (PROTO_INTERFACE*)pr;
1211 static int sipsimpleProtoUninit( PROTO_INTERFACE* _pr )
1213 SIPPROTO *pr = (SIPPROTO *)_pr;
1215 Netlib_CloseHandle(pr->m_hServerNetlibUser);
1216 mir_free(pr->proto.m_szProtoName);
1217 mir_free(pr->proto.m_szModuleName);
1218 mir_free(pr->proto.m_tszUserName);
1219 mir_free(pr->proto.vtbl);
1220 mir_free(pr);
1222 return 0;
1225 __declspec(dllexport) int Load(PLUGINLINK *link)
1227 PROTOCOLDESCRIPTOR pd = {0};
1228 NETLIBUSER nlu = {0};
1229 TCHAR descr[MAX_PATH];
1231 pluginLink = link;
1233 sipe_core_init("");
1234 sipe_miranda_activity_init();
1236 mir_getMMI( &mmi );
1238 /* Register the module */
1239 pd.cbSize = sizeof(pd);
1240 pd.szName = SIPSIMPLE_PROTOCOL_NAME;
1241 pd.type = PROTOTYPE_PROTOCOL;
1242 pd.fnInit = sipsimpleProtoInit;
1243 pd.fnUninit = sipsimpleProtoUninit;
1244 CallService(MS_PROTO_REGISTERMODULE, 0, (LPARAM)&pd);
1246 /* Protocolwide netlib user for logging */
1247 nlu.cbSize = sizeof(nlu);
1248 nlu.flags = NUF_OUTGOING | NUF_TCHAR;
1249 nlu.szSettingsModule = SIPSIMPLE_PROTOCOL_NAME;
1250 _sntprintf(descr, SIZEOF(descr), TranslateT("%ls logging connection"), CHAR2TCHAR(SIPSIMPLE_PROTOCOL_NAME) );
1251 nlu.ptszDescriptiveName = descr;
1253 sipe_miranda_debug_netlibuser = (HANDLE)CallService(MS_NETLIB_REGISTERUSER, 0, (LPARAM)&nlu);
1255 return 0;
1258 __declspec(dllexport) int Unload(void)
1260 Netlib_CloseHandle(sipe_miranda_debug_netlibuser);
1261 sipe_miranda_activity_destroy();
1262 sipe_core_destroy();
1263 return 0;
1266 BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
1268 hInst = hinstDLL;
1269 return TRUE;
1273 Local Variables:
1274 mode: c
1275 c-file-style: "bsd"
1276 indent-tabs-mode: t
1277 tab-width: 8
1278 End: