2 * @file miranda-buddy.c
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
28 #include "newpluginapi.h"
29 #include "m_protosvc.h"
30 #include "m_protoint.h"
31 #include "m_protomod.h"
32 #include "m_database.h"
35 #include "sipe-backend.h"
36 #include "sipe-core.h"
37 #include "miranda-private.h"
39 /* Status identifiers (see also: sipe_status_types()) */
40 #define SIPE_STATUS_ID_UNKNOWN "unset" /* Unset (primitive) */
41 #define SIPE_STATUS_ID_OFFLINE "offline" /* Offline (primitive) */
42 #define SIPE_STATUS_ID_AVAILABLE "available" /* Online */
43 /* PURPLE_STATUS_UNAVAILABLE: */
44 #define SIPE_STATUS_ID_BUSY "busy" /* Busy */
45 #define SIPE_STATUS_ID_BUSYIDLE "busyidle" /* BusyIdle */
46 #define SIPE_STATUS_ID_DND "do-not-disturb" /* Do Not Disturb */
47 #define SIPE_STATUS_ID_IN_MEETING "in-a-meeting" /* In a meeting */
48 #define SIPE_STATUS_ID_IN_CONF "in-a-conference" /* In a conference */
49 #define SIPE_STATUS_ID_ON_PHONE "on-the-phone" /* On the phone */
50 #define SIPE_STATUS_ID_INVISIBLE "invisible" /* Appear Offline */
51 /* PURPLE_STATUS_AWAY: */
52 #define SIPE_STATUS_ID_IDLE "idle" /* Idle/Inactive */
53 #define SIPE_STATUS_ID_BRB "be-right-back" /* Be Right Back */
54 #define SIPE_STATUS_ID_AWAY "away" /* Away (primitive) */
55 /** Reuters status (user settable) */
56 #define SIPE_STATUS_ID_LUNCH "out-to-lunch" /* Out To Lunch */
57 /* ??? PURPLE_STATUS_EXTENDED_AWAY */
58 /* ??? PURPLE_STATUS_MOBILE */
59 /* ??? PURPLE_STATUS_TUNE */
61 #define ADD_PROP(key,value) g_hash_table_insert(info_to_property_table, (gpointer)key, value)
63 static GHashTable
*info_to_property_table
= NULL
;
66 init_property_hash(void)
68 info_to_property_table
= g_hash_table_new(NULL
, NULL
);
70 // ADD_PROP(SIPE_BUDDY_INFO_DISPLAY_NAME, ALIAS_PROP);
71 ADD_PROP(SIPE_BUDDY_INFO_EMAIL
, "e-mail");
72 ADD_PROP(SIPE_BUDDY_INFO_WORK_PHONE
, "CompanyPhone");
73 // ADD_PROP(SIPE_BUDDY_INFO_WORK_PHONE_DISPLAY, PHONE_DISPLAY_PROP);
74 // ADD_PROP(SIPE_BUDDY_INFO_SITE , SITE_PROP);
75 ADD_PROP(SIPE_BUDDY_INFO_COMPANY
, "Company");
76 ADD_PROP(SIPE_BUDDY_INFO_DEPARTMENT
, "CompanyDepartment");
77 ADD_PROP(SIPE_BUDDY_INFO_JOB_TITLE
, "CompanyPosition");
78 // ADD_PROP(SIPE_BUDDY_INFO_OFFICE , OFFICE_PROP);
79 ADD_PROP(SIPE_BUDDY_INFO_STREET
, "CompanyStreet");
80 ADD_PROP(SIPE_BUDDY_INFO_CITY
, "CompanyCity");
81 ADD_PROP(SIPE_BUDDY_INFO_STATE
, "CompanyState");
82 ADD_PROP(SIPE_BUDDY_INFO_ZIPCODE
, "CompanyZIP");
83 ADD_PROP(SIPE_BUDDY_INFO_COUNTRY
, "CompanyCountry");
86 SetValue(hwndDlg,IDC_NICK,hContact,szProto,"Nick",0);
87 SetValue(hwndDlg,IDC_FIRSTNAME,hContact,szProto,"FirstName",0);
88 SetValue(hwndDlg,IDC_LASTNAME,hContact,szProto,"LastName",0);
89 SetValue(hwndDlg,IDC_EMAIL,hContact,szProto,"e-mail",0);
90 SetValue(hwndDlg,IDC_AGE,hContact,szProto,"Age",SVS_ZEROISUNSPEC);
91 SetValue(hwndDlg,IDC_GENDER,hContact,szProto,"Gender",SVS_GENDER);
92 SetValue(hwndDlg,IDC_DOBDAY,hContact,szProto,"BirthDay",0);
93 SetValue(hwndDlg,IDC_DOBMONTH,hContact,szProto,"BirthMonth",SVS_MONTH);
94 SetValue(hwndDlg,IDC_DOBYEAR,hContact,szProto,"BirthYear",0);
97 SetValue(hwndDlg,IDC_STREET,hContact,szProto,"Street",SVS_ZEROISUNSPEC);
98 SetValue(hwndDlg,IDC_CITY,hContact,szProto,"City",SVS_ZEROISUNSPEC);
99 SetValue(hwndDlg,IDC_STATE,hContact,szProto,"State",SVS_ZEROISUNSPEC);
100 SetValue(hwndDlg,IDC_ZIP,hContact,szProto,"ZIP",SVS_ZEROISUNSPEC);
101 SetValue(hwndDlg,IDC_COUNTRY,hContact,szProto,"Country",SVS_COUNTRY);
102 SetValue(hwndDlg,IDC_LANGUAGE1,hContact,szProto,"Language1",SVS_ZEROISUNSPEC);
103 SetValue(hwndDlg,IDC_LANGUAGE2,hContact,szProto,"Language2",SVS_ZEROISUNSPEC);
104 SetValue(hwndDlg,IDC_LANGUAGE3,hContact,szProto,"Language3",SVS_ZEROISUNSPEC);
105 SetValue(hwndDlg,IDC_TIMEZONE,hContact,szProto,"Timezone",SVS_TIMEZONE);
108 SetValue(hwndDlg,IDC_COMPANY,hContact,szProto,"Company",SVS_ZEROISUNSPEC);
109 SetValue(hwndDlg,IDC_DEPARTMENT,hContact,szProto,"CompanyDepartment",SVS_ZEROISUNSPEC);
110 SetValue(hwndDlg,IDC_POSITION,hContact,szProto,"CompanyPosition",SVS_ZEROISUNSPEC);
111 SetValue(hwndDlg,IDC_STREET,hContact,szProto,"CompanyStreet",SVS_ZEROISUNSPEC);
112 SetValue(hwndDlg,IDC_CITY,hContact,szProto,"CompanyCity",SVS_ZEROISUNSPEC);
113 SetValue(hwndDlg,IDC_STATE,hContact,szProto,"CompanyState",SVS_ZEROISUNSPEC);
114 SetValue(hwndDlg,IDC_ZIP,hContact,szProto,"CompanyZIP",SVS_ZEROISUNSPEC);
115 SetValue(hwndDlg,IDC_COUNTRY,hContact,szProto,"CompanyCountry",SVS_COUNTRY);
116 SetValue(hwndDlg,IDC_WEBPAGE,hContact,szProto,"CompanyHomepage",SVS_ZEROISUNSPEC);
119 SetValue(hwndDlg,IDC_WEBPAGE,hContact,szProto,"Homepage",SVS_ZEROISUNSPEC);
122 if(DBGetContactSettingTString(hContact,szProto,"e-mail",&dbv))
123 mir_snprintf(idstr, SIZEOF(idstr), "e-mail%d", i );
124 mir_snprintf(idstr, SIZEOF(idstr), "Mye-mail%d",i);
125 if(!DBGetContactSettingTString(hContact,szProto,"Phone",&dbv)) {
126 if(!DBGetContactSettingTString(hContact,szProto,"Fax",&dbv)) {
127 if(!DBGetContactSettingTString(hContact,szProto,"Cellular",&dbv)) {
128 if(!DBGetContactSettingTString(hContact,szProto,"CompanyPhone",&dbv)) {
129 if(!DBGetContactSettingTString(hContact,szProto,"CompanyFax",&dbv)) {
130 mir_snprintf(idstr, SIZEOF(idstr), "MyPhone%d",i);
135 static int SipeStatusToMiranda(const gchar
*status
) {
137 if (!strcmp(status
, SIPE_STATUS_ID_OFFLINE
))
138 return ID_STATUS_OFFLINE
;
140 if (!strcmp(status
, SIPE_STATUS_ID_AVAILABLE
))
141 return ID_STATUS_ONLINE
;
143 if (!strcmp(status
, SIPE_STATUS_ID_ON_PHONE
))
144 return ID_STATUS_ONTHEPHONE
;
146 if (!strcmp(status
, SIPE_STATUS_ID_DND
))
147 return ID_STATUS_DND
;
149 if (!strcmp(status
, SIPE_STATUS_ID_AWAY
))
152 if (!strcmp(status
, SIPE_STATUS_ID_LUNCH
))
153 return ID_STATUS_OUTTOLUNCH
;
155 if (!strcmp(status
, SIPE_STATUS_ID_BUSY
))
156 return ID_STATUS_OCCUPIED
;
158 if (!strcmp(status
, SIPE_STATUS_ID_INVISIBLE
))
159 return ID_STATUS_INVISIBLE
;
161 if (!strcmp(status
, SIPE_STATUS_ID_BRB
))
162 return ID_STATUS_AWAY
;
164 if (!strcmp(status
, SIPE_STATUS_ID_UNKNOWN
))
165 return ID_STATUS_OFFLINE
;
167 /* None of those? We'll have to guess. Online seems ok. */
168 return ID_STATUS_ONLINE
;
170 /* Don't have SIPE equivalent of these:
177 sipe_info_to_miranda_property(sipe_buddy_info_fields info
)
179 if (!info_to_property_table
)
180 init_property_hash();
181 return (const char *)g_hash_table_lookup(info_to_property_table
, (gconstpointer
)info
);
184 sipe_backend_buddy
sipe_miranda_buddy_find(SIPPROTO
*pr
,
189 SIPE_DEBUG_INFO("buddy_name <%s> group <%s>", name
, group
);
191 hContact
= (HANDLE
)CallService(MS_DB_CONTACT_FINDFIRST
, 0, 0);
193 gchar
* szProto
= (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO
, (WPARAM
)hContact
, 0);
194 if (szProto
!= NULL
&& !lstrcmpA(szProto
, pr
->proto
.m_szModuleName
)) {
196 if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
197 int tCompareResult
= lstrcmpiA( dbv
.pszVal
, name
);
198 DBFreeVariant( &dbv
);
199 if ( !tCompareResult
) {
203 if ( !DBGetContactSettingStringUtf(hContact
, "CList", "Group", &dbv
)) {
204 int tCompareResult
= lstrcmpiA( dbv
.pszVal
, group
);
205 SIPE_DEBUG_INFO("group compare <%s> vs <%s>", dbv
.pszVal
, group
);
206 DBFreeVariant( &dbv
);
207 if ( !tCompareResult
)
215 hContact
= (HANDLE
)CallService(MS_DB_CONTACT_FINDNEXT
, (WPARAM
)hContact
, 0);
220 sipe_backend_buddy
sipe_backend_buddy_find(struct sipe_core_public
*sipe_public
,
224 return sipe_miranda_buddy_find(sipe_public
->backend_private
, name
, group
);
227 GSList
* sipe_miranda_buddy_find_all(SIPPROTO
*pr
,
228 const gchar
*buddy_name
,
229 const gchar
*group_name
)
233 SIPE_DEBUG_INFO("buddy_name <%s> group <%d>", buddy_name
, group_name
);
235 hContact
= (HANDLE
)CallService(MS_DB_CONTACT_FINDFIRST
, 0, 0);
237 gchar
* szProto
= (char*)CallService(MS_PROTO_GETCONTACTBASEPROTO
, (WPARAM
)hContact
, 0);
238 if (szProto
!= NULL
&& !lstrcmpA(szProto
, pr
->proto
.m_szModuleName
)) {
239 if (DBGetContactSettingByte(hContact
, pr
->proto
.m_szModuleName
, "ChatRoom", 0) == 0) {
242 res
= g_slist_append(res
, hContact
);
243 else if ( !DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
)) {
244 int tCompareResult
= lstrcmpiA( dbv
.pszVal
, buddy_name
);
245 DBFreeVariant( &dbv
);
246 if ( !tCompareResult
) {
248 res
= g_slist_append(res
, hContact
);
250 else if ( !DBGetContactSettingStringUtf(hContact
, "CList", "Group", &dbv
)) {
251 int tCompareResult
= lstrcmpiA( dbv
.pszVal
, group_name
);
252 SIPE_DEBUG_INFO("group compare <%s> vs <%s>", dbv
.pszVal
, group_name
);
253 DBFreeVariant( &dbv
);
254 if ( !tCompareResult
)
255 res
= g_slist_append(res
, hContact
);
259 SIPE_DEBUG_INFO_NOFORMAT("Could not get SIP id from contact");
263 hContact
= (HANDLE
)CallService(MS_DB_CONTACT_FINDNEXT
, (WPARAM
)hContact
, 0);
266 SIPE_DEBUG_INFO("found <%d> buddies", g_slist_length(res
));
270 GSList
* sipe_backend_buddy_find_all(struct sipe_core_public
*sipe_public
,
271 const gchar
*buddy_name
,
272 const gchar
*group_name
)
274 return sipe_miranda_buddy_find_all(sipe_public
->backend_private
, buddy_name
, group_name
);
277 gchar
* sipe_backend_buddy_get_name(struct sipe_core_public
*sipe_public
,
278 const sipe_backend_buddy who
)
281 HANDLE hContact
= (HANDLE
)who
;
283 SIPPROTO
*pr
= sipe_public
->backend_private
;
284 const gchar
*module
= pr
->proto
.m_szModuleName
;
286 if ( !DBGetContactSettingString( hContact
, module
, SIP_UNIQUEID
, &dbv
)) {
287 alias
= g_strdup(dbv
.pszVal
);
288 DBFreeVariant( &dbv
);
295 gchar
* sipe_backend_buddy_get_alias(struct sipe_core_public
*sipe_public
,
296 const sipe_backend_buddy who
)
299 HANDLE hContact
= (HANDLE
)who
;
301 SIPPROTO
*pr
= sipe_public
->backend_private
;
302 const gchar
*module
= pr
->proto
.m_szModuleName
;
304 if ( DBGetContactSettingString( hContact
, module
, "Nick", &dbv
)
305 && DBGetContactSettingString( hContact
, module
, "Alias", &dbv
)
306 && DBGetContactSettingString( hContact
, module
, SIP_UNIQUEID
, &dbv
))
309 alias
= g_strdup(dbv
.pszVal
);
310 DBFreeVariant( &dbv
);
314 gchar
* sipe_backend_buddy_get_server_alias(struct sipe_core_public
*sipe_public
,
315 const sipe_backend_buddy who
)
318 HANDLE hContact
= (HANDLE
)who
;
320 SIPPROTO
*pr
= sipe_public
->backend_private
;
321 const gchar
*module
= pr
->proto
.m_szModuleName
;
323 if ( !DBGetContactSettingString( hContact
, module
, "Alias", &dbv
)) {
324 alias
= g_strdup(dbv
.pszVal
);
325 DBFreeVariant( &dbv
);
332 gchar
* sipe_backend_buddy_get_group_name(struct sipe_core_public
*sipe_public
,
333 const sipe_backend_buddy who
)
336 HANDLE hContact
= (HANDLE
)who
;
338 SIPPROTO
*pr
= sipe_public
->backend_private
;
339 const gchar
*module
= pr
->proto
.m_szModuleName
;
341 if ( !DBGetContactSettingString( hContact
, "CList", "Group", &dbv
)) {
342 alias
= g_strdup(dbv
.pszVal
);
343 DBFreeVariant( &dbv
);
350 void sipe_backend_buddy_set_alias(struct sipe_core_public
*sipe_public
,
351 const sipe_backend_buddy who
,
354 SIPPROTO
*pr
= sipe_public
->backend_private
;
355 HANDLE hContact
= (HANDLE
)who
;
357 SIPE_DEBUG_INFO("miranda_sipe_set_buddy_alias: Set alias of contact <%x> to <%s>", who
, alias
);
358 sipe_miranda_setContactStringUtf( pr
, hContact
, "Nick", alias
);
361 void sipe_backend_buddy_set_server_alias(struct sipe_core_public
*sipe_public
,
362 const sipe_backend_buddy who
,
365 HANDLE hContact
= (HANDLE
)who
;
366 SIPPROTO
*pr
= sipe_public
->backend_private
;
368 SIPE_DEBUG_INFO("Set alias of contact <%x> to <%s>", who
, alias
);
369 sipe_miranda_setContactStringUtf( pr
, hContact
, "Alias", alias
);
372 gchar
* sipe_backend_buddy_get_string(struct sipe_core_public
*sipe_public
,
373 sipe_backend_buddy buddy
,
374 const sipe_buddy_info_fields key
)
376 SIPPROTO
*pr
= sipe_public
->backend_private
;
377 const gchar
*module
= pr
->proto
.m_szModuleName
;
378 const gchar
*prop_name
= sipe_info_to_miranda_property(key
);
385 tmp
= sipe_miranda_getContactString(pr
, buddy
, prop_name
);
386 prop_str
= g_strdup(tmp
);
392 void sipe_backend_buddy_set_string(struct sipe_core_public
*sipe_public
,
393 sipe_backend_buddy buddy
,
394 const sipe_buddy_info_fields key
,
397 SIPPROTO
*pr
= sipe_public
->backend_private
;
398 const gchar
*module
= pr
->proto
.m_szModuleName
;
399 const gchar
*prop_name
= sipe_info_to_miranda_property(key
);
401 SIPE_DEBUG_INFO("miranda_sipe_buddy_set_string: buddy <%x> key <%d = %s> val <%s>", buddy
, key
, prop_name
, val
);
405 sipe_miranda_setContactString(pr
, buddy
, prop_name
, val
);
408 sipe_backend_buddy
sipe_backend_buddy_add(struct sipe_core_public
*sipe_public
,
411 const gchar
*groupname
)
413 SIPPROTO
*pr
= sipe_public
->backend_private
;
416 SIPE_DEBUG_INFO("miranda_sipe_add_buddy: Adding miranda contact for buddy <%s> alias <%s> in <%s>", name
, alias
, groupname
);
417 hContact
= ( HANDLE
)CallService( MS_DB_CONTACT_ADD
, 0, 0 );
418 CallService( MS_PROTO_ADDTOCONTACT
, ( WPARAM
)hContact
,( LPARAM
)pr
->proto
.m_szModuleName
);
419 sipe_miranda_setContactString( pr
, hContact
, SIP_UNIQUEID
, name
); // name
420 if (alias
) sipe_miranda_setContactStringUtf( pr
, hContact
, "Nick", alias
);
421 DBWriteContactSettingString( hContact
, "CList", "Group", groupname
);
422 sipe_miranda_setContactString( pr
, hContact
, "Group", groupname
);
423 return (sipe_backend_buddy
)hContact
;
426 void sipe_backend_buddy_remove(struct sipe_core_public
*sipe_public
,
427 const sipe_backend_buddy who
)
429 CallService( MS_DB_CONTACT_DELETE
, (WPARAM
)who
, 0 );
432 void sipe_backend_buddy_request_authorization(struct sipe_core_public
*sipe_public
,
436 sipe_backend_buddy_request_authorization_cb auth_cb
,
437 sipe_backend_buddy_request_authorization_cb deny_cb
,
444 void sipe_backend_buddy_request_add(struct sipe_core_public
*sipe_public
,
451 gboolean
sipe_backend_buddy_is_blocked(struct sipe_core_public
*sipe_public
,
458 void sipe_backend_buddy_set_blocked_status(struct sipe_core_public
*sipe_public
,
465 void sipe_backend_buddy_set_status(struct sipe_core_public
*sipe_public
,
467 const gchar
*status_id
)
469 SIPPROTO
*pr
= sipe_public
->backend_private
;
470 const gchar
*module
= pr
->proto
.m_szModuleName
;
471 GSList
*contacts
= sipe_backend_buddy_find_all(sipe_public
, who
, NULL
);
473 CONTACTS_FOREACH(contacts
)
474 sipe_miranda_setWord(pr
, hContact
, "Status", SipeStatusToMiranda(status_id
));
475 CONTACTS_FOREACH_END
;
479 gboolean
sipe_backend_buddy_group_add(struct sipe_core_public
*sipe_public
,
480 const gchar
*group_name
)
482 TCHAR
*mir_group_name
= mir_a2t(group_name
);
483 HANDLE hGroup
= (HANDLE
)CallService(MS_CLIST_GROUPCREATE
, 0, (LPARAM
)mir_group_name
);
484 mir_free(mir_group_name
);
485 return (hGroup
?TRUE
:FALSE
);
488 int sipe_miranda_buddy_delete(SIPPROTO
*pr
, HANDLE hContact
, LPARAM lParam
)
494 SIPE_DEBUG_INFO("Deleting contact <%08x>", hContact
);
496 if ( DBGetContactSettingString( hContact
, pr
->proto
.m_szModuleName
, SIP_UNIQUEID
, &dbv
))
499 name
= g_strdup(dbv
.pszVal
);
500 DBFreeVariant( &dbv
);
502 if ( DBGetContactSettingString( hContact
, "CList", "Group", &dbv
))
508 groupname
= g_strdup(dbv
.pszVal
);
509 DBFreeVariant( &dbv
);
512 sipe_core_buddy_remove(pr
->sip
, name
, groupname
);