4 * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
26 #include "nmcontact.h"
27 #include "nmuserrecord.h"
30 /* This is the template that we wrap outgoing messages in, since the other
31 * GW Messenger clients expect messages to be in RTF.
33 #define RTF_TEMPLATE "{\\rtf1\\ansi\n"\
34 "{\\fonttbl{\\f0\\fnil Unknown;}}\n"\
35 "{\\colortbl ;\\red0\\green0\\blue0;}\n"\
36 "\\uc1\\cf1\\f0\\fs24 %s\\par\n}"
37 #define NM_MAX_MESSAGE_SIZE 2048
39 static NMERR_T
nm_process_response(NMUser
* user
);
40 static void _update_contact_list(NMUser
* user
, NMField
* fields
);
41 static void _handle_multiple_get_details_login_cb(NMUser
* user
, NMERR_T ret_code
,
42 gpointer resp_data
, gpointer user_data
);
43 static char * nm_rtfize_text(char *text
);
46 * See header for comments on on "public" functions
50 nm_initialize_user(const char *name
, const char *server_addr
,
51 int port
, gpointer data
, nm_event_cb event_callback
)
54 if (name
== NULL
|| server_addr
== NULL
|| event_callback
== NULL
)
57 user
= g_new0(NMUser
, 1);
62 g_hash_table_new_full(g_str_hash
, nm_utf8_str_equal
,
63 g_free
, (GDestroyNotify
) nm_release_contact
);
66 g_hash_table_new_full(g_str_hash
, nm_utf8_str_equal
, g_free
,
67 (GDestroyNotify
) nm_release_user_record
);
69 user
->display_id_to_dn
= g_hash_table_new_full(g_str_hash
, nm_utf8_str_equal
,
72 user
->name
= g_strdup(name
);
73 user
->conn
= nm_create_conn(server_addr
, port
);
74 user
->conn
->addr
= g_strdup(server_addr
);
75 user
->conn
->port
= port
;
76 user
->evt_callback
= event_callback
;
77 user
->client_data
= data
;
84 nm_deinitialize_user(NMUser
* user
)
86 nm_release_conn(user
->conn
);
89 g_hash_table_destroy(user
->contacts
);
92 if (user
->user_records
) {
93 g_hash_table_destroy(user
->user_records
);
96 if (user
->display_id_to_dn
) {
97 g_hash_table_destroy(user
->display_id_to_dn
);
102 if (user
->user_record
) {
103 nm_release_user_record(user
->user_record
);
106 nm_conference_list_free(user
);
107 nm_destroy_contact_list(user
);
113 nm_send_login(NMUser
* user
, const char *pwd
, const char *my_addr
,
114 const char *user_agent
, nm_response_cb callback
, gpointer data
)
117 NMField
*fields
= NULL
;
119 if (user
== NULL
|| pwd
== NULL
|| user_agent
== NULL
) {
120 return NMERR_BAD_PARM
;
123 fields
= nm_field_add_pointer(fields
, NM_A_SZ_USERID
, 0, NMFIELD_METHOD_VALID
, 0,
124 g_strdup(user
->name
), NMFIELD_TYPE_UTF8
);
126 fields
= nm_field_add_pointer(fields
, NM_A_SZ_CREDENTIALS
, 0, NMFIELD_METHOD_VALID
, 0,
127 g_strdup(pwd
), NMFIELD_TYPE_UTF8
);
129 fields
= nm_field_add_pointer(fields
, NM_A_SZ_USER_AGENT
, 0, NMFIELD_METHOD_VALID
, 0,
130 g_strdup(user_agent
), NMFIELD_TYPE_UTF8
);
132 fields
= nm_field_add_number(fields
, NM_A_UD_BUILD
, 0, NMFIELD_METHOD_VALID
, 0,
133 NM_PROTOCOL_VERSION
, NMFIELD_TYPE_UDWORD
);
135 fields
= nm_field_add_pointer(fields
, NM_A_IP_ADDRESS
, 0, NMFIELD_METHOD_VALID
, 0,
136 g_strdup(my_addr
), NMFIELD_TYPE_UTF8
);
140 rc
= nm_send_request(user
->conn
, "login", fields
, callback
, data
, NULL
);
142 nm_free_fields(&fields
);
147 nm_send_set_status(NMUser
* user
, int status
, const char *text
,
148 const char *auto_resp
, nm_response_cb callback
, gpointer data
)
151 NMField
*fields
= NULL
;
154 return NMERR_BAD_PARM
;
157 fields
= nm_field_add_pointer(fields
, NM_A_SZ_STATUS
, 0, NMFIELD_METHOD_VALID
, 0,
158 g_strdup_printf("%d", status
), NMFIELD_TYPE_UTF8
);
160 /* Add the status text and auto reply text if there is any */
162 fields
= nm_field_add_pointer(fields
, NM_A_SZ_STATUS_TEXT
, 0,
163 NMFIELD_METHOD_VALID
, 0, g_strdup(text
),
168 fields
= nm_field_add_pointer(fields
, NM_A_SZ_MESSAGE_BODY
, 0,
169 NMFIELD_METHOD_VALID
, 0, g_strdup(auto_resp
),
173 rc
= nm_send_request(user
->conn
, "setstatus", fields
, callback
, data
, NULL
);
175 nm_free_fields(&fields
);
180 nm_send_multiple_get_details(NMUser
* user
, GSList
*names
,
181 nm_response_cb callback
, gpointer data
)
184 NMField
*fields
= NULL
;
187 if (user
== NULL
|| names
== NULL
)
188 return NMERR_BAD_PARM
;
190 /* Add in DN or display id */
191 for (node
= names
; node
; node
= node
->next
) {
192 fields
= nm_field_add_pointer(fields
, NM_A_SZ_USERID
, 0, NMFIELD_METHOD_VALID
, 0,
193 g_strdup(node
->data
), NMFIELD_TYPE_UTF8
);
196 rc
= nm_send_request(user
->conn
, "getdetails", fields
, callback
, data
, NULL
);
198 nm_free_fields(&fields
);
203 nm_send_get_details(NMUser
* user
, const char *name
,
204 nm_response_cb callback
, gpointer data
)
207 NMField
*fields
= NULL
;
209 if (user
== NULL
|| name
== NULL
)
210 return NMERR_BAD_PARM
;
212 /* Add in DN or display id */
213 if (strstr("=", name
)) {
214 fields
= nm_field_add_pointer(fields
, NM_A_SZ_DN
, 0, NMFIELD_METHOD_VALID
, 0,
215 g_strdup(name
), NMFIELD_TYPE_DN
);
218 const char *dn
= nm_lookup_dn(user
, name
);
220 fields
= nm_field_add_pointer(fields
, NM_A_SZ_DN
, 0, NMFIELD_METHOD_VALID
, 0,
221 g_strdup(name
), NMFIELD_TYPE_DN
);
224 nm_field_add_pointer(fields
, NM_A_SZ_USERID
, 0, NMFIELD_METHOD_VALID
, 0,
225 g_strdup(name
), NMFIELD_TYPE_UTF8
);
230 rc
= nm_send_request(user
->conn
, "getdetails", fields
, callback
, data
, NULL
);
232 nm_free_fields(&fields
);
237 nm_send_create_conference(NMUser
* user
, NMConference
* conference
,
238 nm_response_cb callback
, gpointer data
)
241 NMField
*fields
= NULL
;
243 NMField
*field
= NULL
;
244 NMRequest
*req
= NULL
;
247 if (user
== NULL
|| conference
== NULL
)
248 return NMERR_BAD_PARM
;
250 /* Add in a blank guid */
251 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
252 g_strdup(BLANK_GUID
), NMFIELD_TYPE_UTF8
);
254 fields
= nm_field_add_pointer(fields
, NM_A_FA_CONVERSATION
, 0,
255 NMFIELD_METHOD_VALID
, 0, tmp
,
260 /* Add participants in */
261 count
= nm_conference_get_participant_count(conference
);
262 for (i
= 0; i
< count
; i
++) {
263 NMUserRecord
*user_record
= nm_conference_get_participant(conference
, i
);
266 fields
= nm_field_add_pointer(fields
, NM_A_SZ_DN
,
267 0, NMFIELD_METHOD_VALID
, 0,
268 g_strdup(nm_user_record_get_dn(user_record
)),
273 /* Add our user in */
274 field
= nm_locate_field(NM_A_SZ_DN
, user
->fields
);
276 fields
= nm_field_add_pointer(fields
, NM_A_SZ_DN
,
277 0, NMFIELD_METHOD_VALID
, 0,
278 g_strdup((char *) field
->ptr_value
),
282 rc
= nm_send_request(user
->conn
, "createconf", fields
, callback
, data
, &req
);
283 if (rc
== NM_OK
&& req
) {
284 nm_conference_add_ref(conference
);
285 nm_request_set_data(req
, conference
);
289 nm_release_request(req
);
291 nm_free_fields(&fields
);
296 nm_send_leave_conference(NMUser
* user
, NMConference
* conference
,
297 nm_response_cb callback
, gpointer data
)
300 NMField
*fields
= NULL
;
302 NMRequest
*req
= NULL
;
304 if (user
== NULL
|| conference
== NULL
)
305 return NMERR_BAD_PARM
;
307 /* Add in the conference guid */
308 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
309 g_strdup(nm_conference_get_guid(conference
)),
312 fields
= nm_field_add_pointer(fields
, NM_A_FA_CONVERSATION
, 0,
313 NMFIELD_METHOD_VALID
, 0, tmp
,
317 /* Send the request to the server */
318 rc
= nm_send_request(user
->conn
, "leaveconf", fields
, callback
, data
, &req
);
319 if (rc
== NM_OK
&& req
)
320 nm_request_set_data(req
, conference
);
323 nm_release_request(req
);
325 nm_free_fields(&fields
);
330 nm_send_join_conference(NMUser
* user
, NMConference
* conference
,
331 nm_response_cb callback
, gpointer data
)
334 NMField
*fields
= NULL
, *tmp
= NULL
;
335 NMRequest
*req
= NULL
;
337 if (user
== NULL
|| conference
== NULL
)
338 return NMERR_BAD_PARM
;
340 /* Add in the conference guid */
341 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
342 g_strdup(nm_conference_get_guid(conference
)),
345 fields
= nm_field_add_pointer(fields
, NM_A_FA_CONVERSATION
, 0,
346 NMFIELD_METHOD_VALID
, 0, tmp
,
350 /* Send the request to the server */
351 rc
= nm_send_request(user
->conn
, "joinconf", fields
, callback
, data
, &req
);
352 if (rc
== NM_OK
&& req
)
353 nm_request_set_data(req
, conference
);
356 nm_release_request(req
);
358 nm_free_fields(&fields
);
363 nm_send_reject_conference(NMUser
* user
, NMConference
* conference
,
364 nm_response_cb callback
, gpointer data
)
367 NMField
*fields
= NULL
;
369 NMRequest
*req
= NULL
;
371 if (user
== NULL
|| conference
== NULL
)
372 return NMERR_BAD_PARM
;
374 /* Add in the conference guid */
375 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
376 g_strdup(nm_conference_get_guid(conference
)),
379 fields
= nm_field_add_pointer(fields
, NM_A_FA_CONVERSATION
, 0,
380 NMFIELD_METHOD_VALID
, 0, tmp
,
384 /* Send the request to the server */
385 rc
= nm_send_request(user
->conn
, "rejectconf", fields
, callback
, data
, &req
);
386 if (rc
== NM_OK
&& req
)
387 nm_request_set_data(req
, conference
);
390 nm_release_request(req
);
392 nm_free_fields(&fields
);
397 nm_send_conference_invite(NMUser
*user
, NMConference
*conference
, NMUserRecord
*user_record
,
398 const char *message
, nm_response_cb callback
, gpointer data
)
401 NMField
*fields
= NULL
;
403 NMRequest
*req
= NULL
;
405 if (user
== NULL
|| conference
== NULL
|| user_record
== NULL
)
406 return NMERR_BAD_PARM
;
408 /* Add in the conference guid */
409 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
410 g_strdup(nm_conference_get_guid(conference
)),
413 fields
= nm_field_add_pointer(fields
, NM_A_FA_CONVERSATION
, 0,
414 NMFIELD_METHOD_VALID
, 0, tmp
,
418 /* Add in DN of user to invite */
419 fields
= nm_field_add_pointer(fields
, NM_A_SZ_DN
, 0, NMFIELD_METHOD_VALID
, 0,
420 g_strdup(nm_user_record_get_dn(user_record
)),
423 /* Add the invite message if there is one */
425 fields
= nm_field_add_pointer(fields
, NM_A_SZ_MESSAGE_BODY
, 0, NMFIELD_METHOD_VALID
, 0,
426 g_strdup(message
), NMFIELD_TYPE_UTF8
);
428 /* Send the request to the server */
429 rc
= nm_send_request(user
->conn
, "sendinvite", fields
, callback
, data
, &req
);
430 if (rc
== NM_OK
&& req
)
431 nm_request_set_data(req
, conference
);
434 nm_release_request(req
);
436 nm_free_fields(&fields
);
441 nm_send_message(NMUser
* user
, NMMessage
* message
, nm_response_cb callback
)
444 char *text
, *rtfized
;
445 NMField
*fields
= NULL
, *tmp
= NULL
;
447 NMUserRecord
*user_record
;
450 if (user
== NULL
|| message
== NULL
) {
451 return NMERR_BAD_PARM
;
454 conf
= nm_message_get_conference(message
);
455 if (!nm_conference_is_instantiated(conf
)) {
456 rc
= NMERR_CONFERENCE_NOT_INSTANTIATED
;
459 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
460 g_strdup(nm_conference_get_guid(conf
)),
464 nm_field_add_pointer(fields
, NM_A_FA_CONVERSATION
, 0, NMFIELD_METHOD_VALID
, 0,
465 tmp
, NMFIELD_TYPE_ARRAY
);
468 /* Add RTF and plain text versions of the message */
469 text
= g_strdup(nm_message_get_text(message
));
471 /* Truncate if necessary */
472 if (strlen(text
) > NM_MAX_MESSAGE_SIZE
)
473 text
[NM_MAX_MESSAGE_SIZE
] = 0;
475 rtfized
= nm_rtfize_text(text
);
477 purple_debug_info("novell", "message text is: %s\n", text
);
478 purple_debug_info("novell", "message rtf is: %s\n", rtfized
);
480 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_MESSAGE_BODY
, 0, NMFIELD_METHOD_VALID
, 0,
481 rtfized
, NMFIELD_TYPE_UTF8
);
483 tmp
= nm_field_add_number(tmp
, NM_A_UD_MESSAGE_TYPE
, 0, NMFIELD_METHOD_VALID
, 0,
484 0, NMFIELD_TYPE_UDWORD
);
486 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_MESSAGE_TEXT
, 0, NMFIELD_METHOD_VALID
, 0,
487 text
, NMFIELD_TYPE_UTF8
);
489 fields
= nm_field_add_pointer(fields
, NM_A_FA_MESSAGE
, 0, NMFIELD_METHOD_VALID
, 0,
490 tmp
, NMFIELD_TYPE_ARRAY
);
493 /* Add participants */
494 count
= nm_conference_get_participant_count(conf
);
495 for (i
= 0; i
< count
; i
++) {
496 user_record
= nm_conference_get_participant(conf
, i
);
499 nm_field_add_pointer(fields
, NM_A_SZ_DN
, 0, NMFIELD_METHOD_VALID
, 0,
500 g_strdup(nm_user_record_get_dn(user_record
)),
505 /* Send the request */
506 rc
= nm_send_request(user
->conn
, "sendmessage", fields
, callback
, NULL
, NULL
);
509 nm_free_fields(&fields
);
514 nm_send_typing(NMUser
* user
, NMConference
* conf
,
515 gboolean typing
, nm_response_cb callback
)
519 NMField
*fields
= NULL
, *tmp
= NULL
;
521 if (user
== NULL
|| conf
== NULL
) {
522 return NMERR_BAD_PARM
;
525 if (!nm_conference_is_instantiated(conf
)) {
526 rc
= NMERR_CONFERENCE_NOT_INSTANTIATED
;
528 /* Add the conference GUID */
529 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
530 g_strdup(nm_conference_get_guid(conf
)),
533 /* Add typing type */
534 str
= g_strdup_printf("%d",
535 (typing
? NMEVT_USER_TYPING
:
536 NMEVT_USER_NOT_TYPING
));
538 tmp
= nm_field_add_pointer(tmp
, NM_A_SZ_TYPE
, 0, NMFIELD_METHOD_VALID
, 0,
539 str
, NMFIELD_TYPE_UTF8
);
542 nm_field_add_pointer(fields
, NM_A_FA_CONVERSATION
, 0, NMFIELD_METHOD_VALID
, 0,
543 tmp
, NMFIELD_TYPE_ARRAY
);
546 rc
= nm_send_request(user
->conn
, "sendtyping", fields
, callback
, NULL
, NULL
);
549 nm_free_fields(&fields
);
554 nm_send_create_contact(NMUser
* user
, NMFolder
* folder
,
555 NMContact
* contact
, nm_response_cb callback
,
559 NMField
*fields
= NULL
;
560 NMRequest
*req
= NULL
;
561 const char *name
= NULL
;
562 const char *display_name
= NULL
;
564 if (user
== NULL
|| folder
== NULL
|| contact
== NULL
) {
565 return NMERR_BAD_PARM
;
569 fields
= nm_field_add_pointer(fields
, NM_A_SZ_PARENT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
570 g_strdup_printf("%d", nm_folder_get_id(folder
)),
573 /* Check to see if userid is current user and return an error? */
575 /* Check to see if contact already exists and return an error? */
577 /* Add userid or dn */
578 name
= nm_contact_get_dn(contact
);
580 return NMERR_BAD_PARM
;
582 if (strstr("=", name
)) {
583 fields
= nm_field_add_pointer(fields
, NM_A_SZ_DN
, 0, NMFIELD_METHOD_VALID
, 0,
584 g_strdup(name
), NMFIELD_TYPE_DN
);
586 fields
= nm_field_add_pointer(fields
, NM_A_SZ_USERID
, 0, NMFIELD_METHOD_VALID
, 0,
587 g_strdup(name
), NMFIELD_TYPE_UTF8
);
590 /* Add display name */
591 display_name
= nm_contact_get_display_name(contact
);
593 fields
= nm_field_add_pointer(fields
, NM_A_SZ_DISPLAY_NAME
, 0, NMFIELD_METHOD_VALID
, 0,
594 g_strdup(display_name
), NMFIELD_TYPE_UTF8
);
596 /* Dispatch the request */
597 rc
= nm_send_request(user
->conn
, "createcontact", fields
, callback
, data
, &req
);
598 if (rc
== NM_OK
&& req
)
599 nm_request_set_data(req
, contact
);
602 nm_release_request(req
);
604 nm_free_fields(&fields
);
609 nm_send_remove_contact(NMUser
* user
, NMFolder
* folder
,
610 NMContact
* contact
, nm_response_cb callback
,
614 NMField
*fields
= NULL
;
615 NMRequest
*req
= NULL
;
617 if (user
== NULL
|| folder
== NULL
|| contact
== NULL
) {
618 return NMERR_BAD_PARM
;
622 fields
= nm_field_add_pointer(fields
, NM_A_SZ_PARENT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
623 g_strdup_printf("%d", nm_folder_get_id(folder
)),
627 fields
= nm_field_add_pointer(fields
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
628 g_strdup_printf("%d", nm_contact_get_id(contact
)),
631 /* Dispatch the request */
632 rc
= nm_send_request(user
->conn
, "deletecontact", fields
, callback
, data
, &req
);
633 if (rc
== NM_OK
&& req
)
634 nm_request_set_data(req
, contact
);
637 nm_release_request(req
);
639 nm_free_fields(&fields
);
644 nm_send_create_folder(NMUser
* user
, const char *name
,
645 nm_response_cb callback
, gpointer data
)
648 NMField
*fields
= NULL
;
649 NMRequest
*req
= NULL
;
651 if (user
== NULL
|| name
== NULL
) {
652 return NMERR_BAD_PARM
;
656 fields
= nm_field_add_pointer(fields
, NM_A_SZ_PARENT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
657 g_strdup("0"), NMFIELD_TYPE_UTF8
);
659 /* Add name of the folder to add */
661 nm_field_add_pointer(fields
, NM_A_SZ_DISPLAY_NAME
, 0, NMFIELD_METHOD_VALID
, 0,
662 g_strdup(name
), NMFIELD_TYPE_UTF8
);
664 /* Add sequence, for now just put it at the bottom */
666 nm_field_add_pointer(fields
, NM_A_SZ_SEQUENCE_NUMBER
, 0, NMFIELD_METHOD_VALID
, 0,
667 g_strdup("-1"), NMFIELD_TYPE_UTF8
);
669 /* Dispatch the request */
670 rc
= nm_send_request(user
->conn
, "createfolder", fields
, callback
, data
, &req
);
671 if (rc
== NM_OK
&& req
)
672 nm_request_set_data(req
, g_strdup(name
));
675 nm_release_request(req
);
677 nm_free_fields(&fields
);
682 nm_send_remove_folder(NMUser
* user
, NMFolder
* folder
,
683 nm_response_cb callback
, gpointer data
)
686 NMField
*fields
= NULL
;
687 NMRequest
*req
= NULL
;
689 if (user
== NULL
|| folder
== NULL
) {
690 return NMERR_BAD_PARM
;
693 /* Add the object id */
694 fields
= nm_field_add_pointer(fields
, NM_A_SZ_OBJECT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
695 g_strdup_printf("%d", nm_folder_get_id(folder
)),
698 /* Dispatch the request */
699 rc
= nm_send_request(user
->conn
, "deletecontact", fields
, callback
, data
, &req
);
700 if (rc
== NM_OK
&& req
)
701 nm_request_set_data(req
, folder
);
704 nm_release_request(req
);
706 nm_free_fields(&fields
);
711 nm_send_get_status(NMUser
* user
, NMUserRecord
* user_record
,
712 nm_response_cb callback
, gpointer data
)
715 NMField
*fields
= NULL
;
716 NMRequest
*req
= NULL
;
719 if (user
== NULL
|| user_record
== NULL
)
720 return NMERR_BAD_PARM
;
722 /* Add DN to field list */
723 dn
= nm_user_record_get_dn(user_record
);
727 fields
= nm_field_add_pointer(fields
, NM_A_SZ_DN
, 0, NMFIELD_METHOD_VALID
, 0,
728 g_strdup(dn
), NMFIELD_TYPE_UTF8
);
730 /* Dispatch the request */
731 rc
= nm_send_request(user
->conn
, "getstatus", fields
, callback
, data
, &req
);
732 if (rc
== NM_OK
&& req
)
733 nm_request_set_data(req
, user_record
);
736 nm_release_request(req
);
738 nm_free_fields(&fields
);
743 nm_send_rename_contact(NMUser
* user
, NMContact
* contact
,
744 const char *new_name
, nm_response_cb callback
,
748 NMField
*field
= NULL
, *fields
= NULL
, *list
= NULL
;
749 NMRequest
*req
= NULL
;
751 if (user
== NULL
|| contact
== NULL
|| new_name
== NULL
)
752 return NMERR_BAD_PARM
;
754 /* Create field list for current contact */
755 field
= nm_contact_to_fields(contact
);
759 nm_field_add_pointer(fields
, NM_A_FA_CONTACT
, 0, NMFIELD_METHOD_DELETE
, 0,
760 field
, NMFIELD_TYPE_ARRAY
);
763 /* Update the contacts display name locally */
764 nm_contact_set_display_name(contact
, new_name
);
766 /* Create field list for updated contact */
767 field
= nm_contact_to_fields(contact
);
770 nm_field_add_pointer(fields
, NM_A_FA_CONTACT
, 0, NMFIELD_METHOD_ADD
, 0,
771 field
, NMFIELD_TYPE_ARRAY
);
776 nm_field_add_pointer(list
, NM_A_FA_CONTACT_LIST
, 0, NMFIELD_METHOD_VALID
,
777 0, fields
, NMFIELD_TYPE_ARRAY
);
780 rc
= nm_send_request(user
->conn
, "updateitem", list
, callback
, data
, &req
);
781 if (rc
== NM_OK
&& req
)
782 nm_request_set_data(req
, contact
);
787 nm_release_request(req
);
790 nm_free_fields(&list
);
796 nm_send_rename_folder(NMUser
* user
, NMFolder
* folder
, const char *new_name
,
797 nm_response_cb callback
, gpointer data
)
800 NMField
*field
= NULL
, *fields
= NULL
, *list
= NULL
;
801 NMRequest
*req
= NULL
;
803 if (user
== NULL
|| folder
== NULL
|| new_name
== NULL
)
804 return NMERR_BAD_PARM
;
806 /* Make sure folder does not already exist!? */
807 if (nm_find_folder(user
, new_name
))
808 return NMERR_FOLDER_EXISTS
;
810 /* Create field list for current folder */
811 field
= nm_folder_to_fields(folder
);
814 fields
= nm_field_add_pointer(fields
, NM_A_FA_FOLDER
, 0, NMFIELD_METHOD_DELETE
, 0,
815 field
, NMFIELD_TYPE_ARRAY
);
818 /* Update the folders display name locally */
819 nm_folder_set_name(folder
, new_name
);
821 /* Create field list for updated folder */
822 field
= nm_folder_to_fields(folder
);
824 fields
= nm_field_add_pointer(fields
, NM_A_FA_FOLDER
, 0, NMFIELD_METHOD_ADD
, 0,
825 field
, NMFIELD_TYPE_ARRAY
);
829 list
= nm_field_add_pointer(list
, NM_A_FA_CONTACT_LIST
, 0, NMFIELD_METHOD_VALID
,
830 0, fields
, NMFIELD_TYPE_ARRAY
);
833 rc
= nm_send_request(user
->conn
, "updateitem", list
, callback
, data
, &req
);
834 if (rc
== NM_OK
&& req
)
835 nm_request_set_data(req
, folder
);
840 nm_release_request(req
);
843 nm_free_fields(&list
);
849 nm_send_move_contact(NMUser
* user
, NMContact
* contact
, NMFolder
* folder
,
850 nm_response_cb callback
, gpointer data
)
853 NMField
*field
= NULL
, *fields
= NULL
, *list
= NULL
;
854 NMRequest
*req
= NULL
;
856 if (user
== NULL
|| contact
== NULL
|| folder
== NULL
)
857 return NMERR_BAD_PARM
;
859 /* Create field list for the contact */
860 field
= nm_contact_to_fields(contact
);
863 fields
= nm_field_add_pointer(fields
, NM_A_FA_CONTACT
, 0, NMFIELD_METHOD_DELETE
, 0,
864 field
, NMFIELD_TYPE_ARRAY
);
867 /* Wrap the contact up and add it to the request field list */
868 list
= nm_field_add_pointer(list
, NM_A_FA_CONTACT_LIST
, 0, NMFIELD_METHOD_VALID
, 0,
869 fields
, NMFIELD_TYPE_ARRAY
);
872 /* Add sequence number */
873 list
= nm_field_add_pointer(list
, NM_A_SZ_SEQUENCE_NUMBER
, 0, NMFIELD_METHOD_VALID
,
874 0, g_strdup("-1"), NMFIELD_TYPE_UTF8
);
877 list
= nm_field_add_pointer(list
, NM_A_SZ_PARENT_ID
, 0, NMFIELD_METHOD_VALID
, 0,
878 g_strdup_printf("%d", nm_folder_get_id(folder
)),
881 /* Dispatch the request */
882 rc
= nm_send_request(user
->conn
, "movecontact", list
, callback
, data
, &req
);
883 if (rc
== NM_OK
&& req
)
884 nm_request_set_data(req
, contact
);
889 nm_release_request(req
);
892 nm_free_fields(&list
);
899 nm_send_create_privacy_item(NMUser
*user
, const char *who
, gboolean allow_list
,
900 nm_response_cb callback
, gpointer data
)
903 NMField
*fields
= NULL
;
906 if (user
== NULL
|| who
== NULL
)
907 return NMERR_BAD_PARM
;
910 tag
= NM_A_SZ_BLOCKING_ALLOW_ITEM
;
912 tag
= NM_A_SZ_BLOCKING_DENY_ITEM
;
914 fields
= nm_field_add_pointer(fields
, tag
, 0, NMFIELD_METHOD_ADD
, 0,
915 g_strdup(who
), NMFIELD_TYPE_UTF8
);
917 rc
= nm_send_request(user
->conn
, "createblock", fields
, callback
, data
, NULL
);
919 nm_free_fields(&fields
);
924 nm_send_remove_privacy_item(NMUser
*user
, const char *dn
, gboolean allow_list
,
925 nm_response_cb callback
, gpointer data
)
928 NMField
*fields
= NULL
;
930 GSList
**list_ptr
, *node
;
932 if (user
== NULL
|| dn
== NULL
)
933 return NMERR_BAD_PARM
;
936 tag
= NM_A_BLOCKING_ALLOW_LIST
;
937 list_ptr
= &user
->allow_list
;
939 tag
= NM_A_BLOCKING_DENY_LIST
;
940 list_ptr
= &user
->deny_list
;
943 /* Remove item from the cached list */
944 if ((node
= g_slist_find_custom(*list_ptr
, dn
, (GCompareFunc
)purple_utf8_strcasecmp
))) {
945 *list_ptr
= g_slist_remove_link(*list_ptr
, node
);
946 g_slist_free_1(node
);
949 fields
= nm_field_add_pointer(fields
, tag
, 0, NMFIELD_METHOD_DELETE
, 0,
950 g_strdup(dn
), NMFIELD_TYPE_DN
);
952 rc
= nm_send_request(user
->conn
, "updateblocks", fields
, callback
, data
, NULL
);
954 nm_free_fields(&fields
);
960 nm_send_set_privacy_default(NMUser
*user
, gboolean default_deny
,
961 nm_response_cb callback
, gpointer data
)
964 NMField
*fields
= NULL
;
967 return NMERR_BAD_PARM
;
969 fields
= nm_field_add_pointer(fields
, NM_A_BLOCKING
, 0, NMFIELD_METHOD_UPDATE
, 0,
970 (default_deny
? g_strdup("1") : g_strdup("0")),
973 rc
= nm_send_request(user
->conn
, "updateblocks", fields
, callback
, data
, NULL
);
975 nm_free_fields(&fields
);
980 nm_send_keepalive(NMUser
*user
, nm_response_cb callback
, gpointer data
)
985 return NMERR_BAD_PARM
;
987 rc
= nm_send_request(user
->conn
, "ping", NULL
, callback
, data
, NULL
);
993 nm_process_new_data(NMUser
* user
)
1000 return NMERR_BAD_PARM
;
1004 /* Check to see if this is an event or a response */
1005 rc
= nm_read_all(conn
, (char *) &val
, sizeof(val
));
1007 if (strncmp((char *) &val
, "HTTP", strlen("HTTP")) == 0)
1008 rc
= nm_process_response(user
);
1010 rc
= nm_process_event(user
, GUINT32_FROM_LE(val
));
1013 if (errno
== EAGAIN
)
1016 rc
= NMERR_PROTOCOL
;
1023 nm_find_conversation(NMUser
* user
, const char *who
)
1025 NMConference
*conference
= NULL
;
1029 if (user
&& user
->conferences
) {
1030 for (cnode
= user
->conferences
; cnode
; cnode
= cnode
->next
) {
1032 if (nm_conference_get_participant_count(tmp
) == 1) {
1033 NMUserRecord
*ur
= nm_conference_get_participant(tmp
, 0);
1036 if (nm_utf8_str_equal(nm_user_record_get_dn(ur
), who
)) {
1049 nm_conference_list_add(NMUser
* user
, NMConference
* conf
)
1051 if (user
== NULL
|| conf
== NULL
)
1054 nm_conference_add_ref(conf
);
1055 user
->conferences
= g_slist_append(user
->conferences
, conf
);
1059 nm_conference_list_remove(NMUser
* user
, NMConference
* conf
)
1061 if (user
== NULL
|| conf
== NULL
)
1064 if (g_slist_find(user
->conferences
, conf
)) {
1065 user
->conferences
= g_slist_remove(user
->conferences
, conf
);
1066 nm_release_conference(conf
);
1071 nm_conference_list_free(NMUser
* user
)
1074 NMConference
*conference
;
1079 if (user
->conferences
) {
1080 for (cnode
= user
->conferences
; cnode
; cnode
= cnode
->next
) {
1081 conference
= cnode
->data
;
1083 nm_release_conference(conference
);
1086 g_slist_free(user
->conferences
);
1087 user
->conferences
= NULL
;
1092 nm_conference_list_find(NMUser
* user
, const char *guid
)
1095 NMConference
*conference
= NULL
, *tmp
;
1097 if (user
== NULL
|| guid
== NULL
)
1100 if (user
->conferences
) {
1101 for (cnode
= user
->conferences
; cnode
; cnode
= cnode
->next
) {
1103 if (nm_are_guids_equal(nm_conference_get_guid(tmp
), guid
)) {
1114 nm_are_guids_equal(const char *guid1
, const char *guid2
)
1116 if (guid1
== NULL
|| guid2
== NULL
)
1119 return (strncmp(guid1
, guid2
, CONF_GUID_END
) == 0);
1123 nm_user_add_contact(NMUser
* user
, NMContact
* contact
)
1125 if (user
== NULL
|| contact
== NULL
)
1128 nm_contact_add_ref(contact
);
1130 g_hash_table_insert(user
->contacts
,
1131 g_utf8_strdown(nm_contact_get_dn(contact
), -1), contact
);
1135 nm_user_add_user_record(NMUser
* user
, NMUserRecord
* user_record
)
1137 const char *display_id
;
1140 if (!user
|| !user_record
)
1143 display_id
= nm_user_record_get_display_id(user_record
);
1144 dn
= nm_user_record_get_dn(user_record
);
1146 if (!dn
|| !display_id
)
1149 nm_user_record_add_ref(user_record
);
1151 g_hash_table_insert(user
->user_records
,
1152 g_utf8_strdown(dn
, -1),
1155 g_hash_table_insert(user
->display_id_to_dn
,
1156 g_utf8_strdown(display_id
, -1),
1157 g_utf8_strdown(dn
, -1));
1161 nm_user_get_event_callback(NMUser
* user
)
1166 return user
->evt_callback
;
1170 nm_user_get_conn(NMUser
* user
)
1179 nm_create_contact_list(NMUser
* user
)
1182 NMField
*locate
= NULL
;
1184 if (user
== NULL
|| user
->fields
== NULL
) {
1185 return NMERR_BAD_PARM
;
1188 /* Create the root folder */
1189 user
->root_folder
= nm_create_folder("");
1191 /* Find the contact list in the login fields */
1192 locate
= nm_locate_field(NM_A_FA_CONTACT_LIST
, user
->fields
);
1193 if (locate
!= NULL
) {
1195 /* Add the folders and then the contacts */
1196 nm_folder_add_contacts_and_folders(user
, user
->root_folder
,
1197 (NMField
*) (locate
->ptr_value
));
1204 gboolean
nm_user_is_privacy_locked(NMUser
*user
)
1207 return user
->privacy_locked
;
1214 _create_privacy_list(NMUser
* user
, NMRequest
*request
)
1216 NMField
*locate
= NULL
;
1217 GSList
*need_details
= NULL
;
1219 /* Are the privacy settings locked */
1220 locate
= nm_locate_field(NM_A_LOCKED_ATTR_LIST
, user
->fields
);
1221 if (locate
&& locate
->ptr_value
) {
1222 if (locate
->type
== NMFIELD_TYPE_UTF8
&&
1223 (purple_utf8_strcasecmp(locate
->ptr_value
, NM_A_BLOCKING
) == 0)) {
1224 user
->privacy_locked
= TRUE
;
1225 } else if (locate
->type
== NMFIELD_TYPE_MV
||
1226 locate
->type
== NMFIELD_TYPE_ARRAY
) {
1227 NMField
*tmp
= (NMField
*)locate
->ptr_value
;
1228 while (tmp
&& tmp
->tag
) {
1229 if (purple_utf8_strcasecmp(tmp
->ptr_value
, NM_A_BLOCKING
) == 0) {
1230 user
->privacy_locked
= TRUE
;
1238 /* Set default deny flag */
1239 locate
= nm_locate_field(NM_A_BLOCKING
, user
->fields
);
1240 if (locate
&& locate
->ptr_value
) {
1241 user
->default_deny
= atoi((char *)locate
->ptr_value
);
1244 /* Read internal blocking allow list */
1245 locate
= nm_locate_field(NM_A_BLOCKING_ALLOW_LIST
, user
->fields
);
1246 if (locate
&& locate
->ptr_value
) {
1248 if (locate
->type
== NMFIELD_TYPE_MV
) {
1249 locate
= (NMField
*)locate
->ptr_value
;
1250 for (; locate
->tag
!= NULL
; locate
++) {
1251 if (locate
->ptr_value
) {
1253 user
->allow_list
= g_slist_append(user
->allow_list
, (char *)locate
->ptr_value
);
1255 if (nm_find_user_record(user
, (char *)locate
->ptr_value
) == NULL
)
1256 need_details
= g_slist_append(need_details
, (char *)locate
->ptr_value
);
1262 user
->allow_list
= g_slist_append(user
->allow_list
, (char *)locate
->ptr_value
);
1264 if (nm_find_user_record(user
, (char *)locate
->ptr_value
) == NULL
)
1265 need_details
= g_slist_append(need_details
, (char *)locate
->ptr_value
);
1270 /* Read internal blocking deny list */
1271 locate
= nm_locate_field(NM_A_BLOCKING_DENY_LIST
, user
->fields
);
1272 if (locate
&& locate
->ptr_value
) {
1274 if (locate
->type
== NMFIELD_TYPE_MV
) {
1275 locate
= (NMField
*)locate
->ptr_value
;
1276 for (; locate
->tag
!= NULL
; locate
++) {
1277 if (locate
->ptr_value
) {
1279 user
->deny_list
= g_slist_append(user
->deny_list
, (char *)locate
->ptr_value
);
1281 if (nm_find_user_record(user
, (char *)locate
->ptr_value
) == NULL
)
1282 need_details
= g_slist_append(need_details
, (char *)locate
->ptr_value
);
1288 user
->deny_list
= g_slist_append(user
->deny_list
, (char *)locate
->ptr_value
);
1290 if (nm_find_user_record(user
, (char *)locate
->ptr_value
) == NULL
)
1291 need_details
= g_slist_append(need_details
, (char *)locate
->ptr_value
);
1298 nm_request_add_ref(request
);
1299 nm_send_multiple_get_details(user
, need_details
,
1300 _handle_multiple_get_details_login_cb
, request
);
1309 nm_destroy_contact_list(NMUser
* user
)
1314 if (user
->root_folder
) {
1315 nm_release_folder(user
->root_folder
);
1316 user
->root_folder
= NULL
;
1321 nm_get_root_folder(NMUser
* user
)
1326 if (user
->root_folder
== NULL
)
1327 nm_create_contact_list(user
);
1329 return user
->root_folder
;
1333 nm_find_contact(NMUser
* user
, const char *name
)
1336 const char *dn
= NULL
;
1337 NMContact
*contact
= NULL
;
1339 if (user
== NULL
|| name
== NULL
)
1342 str
= g_utf8_strdown(name
, -1);
1343 if (strstr(str
, "=")) {
1346 /* Assume that we have a display id instead of a dn */
1347 dn
= (const char *) g_hash_table_lookup(user
->display_id_to_dn
, str
);
1350 /* Find contact object in reference table */
1352 contact
= (NMContact
*) g_hash_table_lookup(user
->contacts
, dn
);
1360 nm_find_contacts(NMUser
* user
, const char *dn
)
1365 GList
*contacts
= NULL
;
1367 if (user
== NULL
|| dn
== NULL
)
1370 /* Check for contact at the root */
1371 contact
= nm_folder_find_contact(user
->root_folder
, dn
);
1373 contacts
= g_list_append(contacts
, contact
);
1377 /* Check for contact in each subfolder */
1378 cnt
= nm_folder_get_subfolder_count(user
->root_folder
);
1379 for (i
= 0; i
< cnt
; i
++) {
1380 folder
= nm_folder_get_subfolder(user
->root_folder
, i
);
1381 contact
= nm_folder_find_contact(folder
, dn
);
1383 contacts
= g_list_append(contacts
, contact
);
1392 nm_find_user_record(NMUser
* user
, const char *name
)
1395 const char *dn
= NULL
;
1396 NMUserRecord
*user_record
= NULL
;
1398 if (user
== NULL
|| name
== NULL
)
1401 str
= g_utf8_strdown(name
, -1);
1402 if (strstr(str
, "=")) {
1405 /* Assume that we have a display id instead of a dn */
1406 dn
= (const char *) g_hash_table_lookup(user
->display_id_to_dn
, str
);
1409 /* Find user record in reference table */
1412 (NMUserRecord
*) g_hash_table_lookup(user
->user_records
, dn
);
1420 nm_lookup_dn(NMUser
* user
, const char *display_id
)
1425 if (user
== NULL
|| display_id
== NULL
)
1428 lower
= g_utf8_strdown(display_id
, -1);
1429 dn
= g_hash_table_lookup(user
->display_id_to_dn
, lower
);
1436 nm_find_folder(NMUser
* user
, const char *name
)
1438 NMFolder
*folder
= NULL
, *temp
;
1440 const char *tname
= NULL
;
1442 if (user
== NULL
|| name
== NULL
)
1446 return user
->root_folder
;
1448 num_folders
= nm_folder_get_subfolder_count(user
->root_folder
);
1449 for (i
= 0; i
< num_folders
; i
++) {
1450 temp
= nm_folder_get_subfolder(user
->root_folder
, i
);
1451 tname
= nm_folder_get_name(temp
);
1452 if (tname
&& purple_strequal(tname
, name
)) {
1462 nm_find_folder_by_id(NMUser
* user
, int object_id
)
1464 NMFolder
*folder
= NULL
, *temp
;
1471 return user
->root_folder
;
1473 num_folders
= nm_folder_get_subfolder_count(user
->root_folder
);
1474 for (i
= 0; i
< num_folders
; i
++) {
1475 temp
= nm_folder_get_subfolder(user
->root_folder
, i
);
1476 if (nm_folder_get_id(temp
) == object_id
) {
1486 _handle_multiple_get_details_login_cb(NMUser
* user
, NMERR_T ret_code
,
1487 gpointer resp_data
, gpointer user_data
)
1490 NMRequest
*request
= user_data
;
1492 if (user
== NULL
|| request
== NULL
)
1495 if ((cb
= nm_request_get_callback(request
))) {
1496 cb(user
, ret_code
, nm_request_get_data(request
),
1497 nm_request_get_user_define(request
));
1498 nm_release_request(request
);
1503 _handle_multiple_get_details_joinconf_cb(NMUser
* user
, NMERR_T ret_code
,
1504 gpointer resp_data
, gpointer user_data
)
1506 NMRequest
*request
= user_data
;
1507 NMUserRecord
*user_record
= resp_data
;
1508 NMConference
*conference
;
1509 GSList
*list
, *node
;
1511 if (user
== NULL
|| resp_data
== NULL
|| user_data
== NULL
)
1514 conference
= nm_request_get_data(request
);
1515 list
= nm_request_get_user_define(request
);
1517 if (ret_code
== 0 && conference
&& list
) {
1519 /* Add the user to the conference */
1520 nm_conference_add_participant(conference
, user_record
);
1522 /* Find the user in the list and remove it */
1523 for (node
= list
; node
; node
= node
->next
) {
1524 if (nm_utf8_str_equal(nm_user_record_get_dn(user_record
),
1525 (const char *) node
->data
)) {
1527 list
= g_slist_delete_link(list
, node
);
1528 nm_request_set_user_define(request
, list
);
1533 /* Time to callback? */
1535 nm_response_cb cb
= nm_request_get_callback(request
);
1538 cb(user
, 0, conference
, conference
);
1540 nm_release_request(request
);
1546 nm_call_handler(NMUser
* user
, NMRequest
* request
, NMField
* fields
)
1548 NMERR_T rc
= NM_OK
, ret_code
= NM_OK
;
1549 NMConference
*conf
= NULL
;
1550 NMUserRecord
*user_record
= NULL
;
1551 NMField
*locate
= NULL
;
1552 NMField
*field
= NULL
;
1555 gboolean done
= TRUE
;
1557 if (user
== NULL
|| request
== NULL
|| fields
== NULL
)
1558 return NMERR_BAD_PARM
;
1560 /* Get the return code */
1561 field
= nm_locate_field(NM_A_SZ_RESULT_CODE
, fields
);
1563 ret_code
= atoi((char *) field
->ptr_value
);
1565 ret_code
= NMERR_PROTOCOL
;
1568 cmd
= nm_request_get_cmd(request
);
1569 if (ret_code
== NM_OK
&& cmd
!= NULL
) {
1571 if (purple_strequal("login", cmd
)) {
1573 user
->user_record
= nm_create_user_record_from_fields(fields
);
1575 /* Save the users fields */
1576 user
->fields
= nm_copy_field_array(fields
);
1578 nm_create_contact_list(user
);
1579 done
= _create_privacy_list(user
, request
);
1581 } else if (purple_strequal("setstatus", cmd
)) {
1585 } else if (purple_strequal("createconf", cmd
)) {
1587 conf
= (NMConference
*) nm_request_get_data(request
);
1589 /* get the convo guid */
1590 locate
= nm_locate_field(NM_A_FA_CONVERSATION
, fields
);
1593 nm_locate_field(NM_A_SZ_OBJECT_ID
, (NMField
*) fields
->ptr_value
);
1595 nm_conference_set_guid(conf
, (char *) field
->ptr_value
);
1599 nm_conference_list_add(user
, conf
);
1600 nm_release_conference(conf
);
1602 } else if (purple_strequal("leaveconf", cmd
)) {
1604 conf
= (NMConference
*) nm_request_get_data(request
);
1605 nm_conference_list_remove(user
, conf
);
1607 } else if (purple_strequal("joinconf", cmd
)) {
1608 GSList
*list
= NULL
, *node
;
1610 conf
= nm_request_get_data(request
);
1612 locate
= nm_locate_field(NM_A_FA_CONTACT_LIST
, fields
);
1613 if (locate
&& locate
->ptr_value
!= 0) {
1615 field
= (NMField
*) locate
->ptr_value
;
1616 while ((field
= nm_locate_field(NM_A_SZ_DN
, field
))) {
1617 if (field
&& field
->ptr_value
!= 0) {
1619 if (nm_utf8_str_equal
1620 (nm_user_record_get_dn(user
->user_record
),
1621 (const char *) field
->ptr_value
)) {
1627 nm_find_user_record(user
,
1628 (const char *) field
->ptr_value
);
1629 if (user_record
== NULL
) {
1631 g_slist_append(list
,
1632 g_strdup((char *) field
->ptr_value
));
1634 nm_conference_add_participant(conf
, user_record
);
1643 nm_request_set_user_define(request
, list
);
1644 nm_request_add_ref(request
);
1645 for (node
= list
; node
; node
= node
->next
) {
1647 nm_send_get_details(user
, (const char *) node
->data
,
1648 _handle_multiple_get_details_joinconf_cb
,
1654 } else if (purple_strequal("getdetails", cmd
)) {
1656 locate
= nm_locate_field(NM_A_FA_RESULTS
, fields
);
1657 while (locate
&& locate
->ptr_value
!= 0) {
1659 user_record
= nm_create_user_record_from_fields(locate
);
1664 nm_find_user_record(user
,
1665 nm_user_record_get_dn(user_record
));
1668 /* Update the existing user record */
1669 nm_user_record_copy(tmp
, user_record
);
1670 nm_release_user_record(user_record
);
1674 nm_user_add_user_record(user
, user_record
);
1675 nm_release_user_record(user_record
);
1678 /* Response data is new user record */
1679 nm_request_set_data(request
, (gpointer
) user_record
);
1682 locate
= nm_locate_field(NM_A_FA_RESULTS
, locate
+1);
1685 } else if (purple_strequal("createfolder", cmd
)) {
1687 _update_contact_list(user
, fields
);
1689 } else if (purple_strequal("createcontact", cmd
)) {
1691 _update_contact_list(user
, fields
);
1694 nm_locate_field(NM_A_SZ_OBJECT_ID
, (NMField
*) fields
->ptr_value
);
1697 NMContact
*new_contact
=
1698 nm_folder_find_item_by_object_id(user
->root_folder
,
1699 atoi((char *)locate
->ptr_value
));
1703 /* Add the contact to our cache */
1704 nm_user_add_contact(user
, new_contact
);
1706 /* Set the contact as the response data */
1707 nm_request_set_data(request
, (gpointer
) new_contact
);
1713 } else if (purple_strequal("deletecontact", cmd
)) {
1715 _update_contact_list(user
, fields
);
1717 } else if (purple_strequal("movecontact", cmd
)) {
1719 _update_contact_list(user
, fields
);
1721 } else if (purple_strequal("getstatus", cmd
)) {
1723 locate
= nm_locate_field(NM_A_SZ_STATUS
, fields
);
1725 nm_user_record_set_status((NMUserRecord
*)
1726 nm_request_get_data(request
),
1727 atoi((char *) locate
->ptr_value
), NULL
);
1730 } else if (purple_strequal("updateitem", cmd
)) {
1732 /* Nothing extra to do here */
1734 } else if (purple_strequal("createblock", cmd
)) {
1735 if ((locate
= nm_locate_field(NM_A_BLOCKING_DENY_LIST
, fields
))) {
1736 if (locate
->ptr_value
) {
1737 user
->deny_list
= g_slist_append(user
->deny_list
, g_strdup((char *)locate
->ptr_value
));
1739 } else if ((locate
= nm_locate_field(NM_A_BLOCKING_ALLOW_LIST
, fields
))) {
1740 if (locate
->ptr_value
) {
1741 user
->allow_list
= g_slist_append(user
->allow_list
, g_strdup((char *)locate
->ptr_value
));
1744 } else if (purple_strequal("updateblocks", cmd
)) {
1745 /* nothing to do here */
1748 /* Nothing to do, just print debug message */
1749 purple_debug(PURPLE_DEBUG_INFO
, "novell",
1750 "nm_call_handler(): Unknown request command, %s\n", cmd
);
1755 if (done
&& (cb
= nm_request_get_callback(request
))) {
1757 cb(user
, ret_code
, nm_request_get_data(request
),
1758 nm_request_get_user_define(request
));
1765 nm_process_response(NMUser
* user
)
1768 NMField
*fields
= NULL
;
1769 NMField
*field
= NULL
;
1770 NMConn
*conn
= user
->conn
;
1771 NMRequest
*req
= NULL
;
1773 rc
= nm_read_header(conn
);
1775 rc
= nm_read_fields(conn
, -1, &fields
);
1779 field
= nm_locate_field(NM_A_SZ_TRANSACTION_ID
, fields
);
1780 if (field
!= NULL
&& field
->ptr_value
!= 0) {
1781 req
= nm_conn_find_request(conn
, atoi((char *) field
->ptr_value
));
1783 rc
= nm_call_handler(user
, req
, fields
);
1784 nm_conn_remove_request_item(conn
, req
);
1791 nm_free_fields(&fields
);
1797 * Some utility functions...haven't figured out where
1802 nm_utf8_str_equal(gconstpointer str1
, gconstpointer str2
)
1804 return (purple_utf8_strcasecmp(str1
, str2
) == 0);
1808 nm_typed_to_dotted(const char *typed
)
1810 unsigned i
= 0, j
= 0;
1816 dotted
= g_new0(char, strlen(typed
));
1820 /* replace comma with a dot */
1827 while (typed
[i
] != '\0' && typed
[i
] != '=')
1830 /* verify that we aren't running off the end */
1831 if (typed
[i
] == '\0') {
1838 /* copy the object name to context */
1839 while (typed
[i
] != '\0' && typed
[i
] != ',') {
1840 dotted
[j
] = typed
[i
];
1845 } while (typed
[i
] != '\0');
1851 nm_error_to_string(NMERR_T err
)
1853 static char *unknown_msg
= NULL
;
1855 g_free(unknown_msg
);
1860 case NMERR_BAD_PARM
:
1861 return _("Required parameters not passed in");
1863 case NMERR_TCP_WRITE
:
1864 return _("Unable to write to network");
1866 case NMERR_TCP_READ
:
1867 return _("Unable to read from network");
1869 case NMERR_PROTOCOL
:
1870 return _("Error communicating with server");
1872 case NMERR_CONFERENCE_NOT_FOUND
:
1873 case NMERR_CONFERENCE_NOT_FOUND_2
:
1874 return _("Conference not found");
1876 case NMERR_CONFERENCE_NOT_INSTANTIATED
:
1877 return _("Conference does not exist");
1879 case NMERR_DUPLICATE_FOLDER
:
1880 case NMERR_FOLDER_EXISTS
:
1881 return _("A folder with that name already exists");
1883 case NMERR_NOT_SUPPORTED
:
1884 return _("Not supported");
1886 case NMERR_PASSWORD_EXPIRED
:
1887 case NMERR_PASSWORD_EXPIRED_2
:
1888 return _("Password has expired");
1890 case NMERR_PASSWORD_INVALID
:
1891 return _("Incorrect password");
1893 case NMERR_USER_NOT_FOUND
:
1894 return _("User not found");
1896 case NMERR_USER_DISABLED
:
1897 return _("Account has been disabled");
1899 case NMERR_DIRECTORY_FAILURE
:
1900 return _("The server could not access the directory");
1902 case NMERR_ADMIN_LOCKED
:
1903 return _("Your system administrator has disabled this operation");
1905 case NMERR_SERVER_BUSY
:
1906 return _("The server is unavailable; try again later");
1908 case NMERR_DUPLICATE_CONTACT
:
1909 return _("Cannot add a contact to the same folder twice");
1911 case NMERR_USER_NOT_ALLOWED
:
1912 return _("Cannot add yourself");
1914 case NMERR_MASTER_ARCHIVE_MISSING
:
1915 return _("Master archive is misconfigured");
1917 case NMERR_AUTHENTICATION_FAILED
:
1918 case NMERR_CREDENTIALS_MISSING
:
1919 return _("Incorrect username or password");
1921 case NMERR_HOST_NOT_FOUND
:
1922 return _("Could not recognize the host of the username you entered");
1924 case NMERR_ACCESS_DENIED
:
1925 return _("Your account has been disabled because too many incorrect passwords were entered");
1927 case NMERR_DUPLICATE_PARTICIPANT
:
1928 return _("You cannot add the same person twice to a conversation");
1930 case NMERR_TOO_MANY_CONTACTS
:
1931 case NMERR_TOO_MANY_FOLDERS
:
1932 return _("You have reached your limit for the number of contacts allowed");
1934 case NMERR_OBJECT_NOT_FOUND
:
1935 return _("You have entered an incorrect username");
1937 case NMERR_DIRECTORY_UPDATE
:
1938 return _("An error occurred while updating the directory");
1940 case NMERR_SERVER_PROTOCOL
:
1941 return _("Incompatible protocol version");
1943 case NMERR_USER_BLOCKED
:
1944 return _("The user has blocked you");
1946 case NMERR_EVAL_CONNECTION_LIMIT
:
1947 return _("This evaluation version does not allow more than ten users to log in at one time");
1949 case NMERR_CONVERSATION_INVITE
:
1950 return _("The user is either offline or you are blocked");
1953 unknown_msg
= g_strdup_printf (_("Unknown error: 0x%X"), err
);
1960 _update_contact_list(NMUser
* user
, NMField
* fields
)
1962 NMField
*list
, *cursor
, *locate
;
1968 if (user
== NULL
|| fields
== NULL
)
1971 /* Is it wrapped in a RESULTS array? */
1972 if (purple_strequal(fields
->tag
, NM_A_FA_RESULTS
)) {
1973 list
= (NMField
*) fields
->ptr_value
;
1978 /* Update the cached contact list */
1979 cursor
= (NMField
*) list
->ptr_value
;
1980 while (cursor
->tag
!= NULL
) {
1981 if ((g_ascii_strcasecmp(cursor
->tag
, NM_A_FA_CONTACT
) == 0) ||
1982 (g_ascii_strcasecmp(cursor
->tag
, NM_A_FA_FOLDER
) == 0)) {
1985 nm_locate_field(NM_A_SZ_OBJECT_ID
, (NMField
*) cursor
->ptr_value
);
1986 if (locate
!= NULL
&& locate
->ptr_value
!= 0) {
1987 objid1
= atoi((char *) locate
->ptr_value
);
1989 nm_folder_find_item_by_object_id(user
->root_folder
, objid1
);
1991 if (cursor
->method
== NMFIELD_METHOD_ADD
) {
1992 if (g_ascii_strcasecmp(cursor
->tag
, NM_A_FA_CONTACT
) == 0) {
1993 contact
= (NMContact
*) item
;
1994 nm_contact_update_list_properties(contact
, cursor
);
1995 } else if (g_ascii_strcasecmp(cursor
->tag
, NM_A_FA_FOLDER
)
1997 folder
= (NMFolder
*) item
;
1998 nm_folder_update_list_properties(folder
, cursor
);
2000 } else if (cursor
->method
== NMFIELD_METHOD_DELETE
) {
2001 if (g_ascii_strcasecmp(cursor
->tag
, NM_A_FA_CONTACT
) == 0) {
2002 contact
= (NMContact
*) item
;
2004 nm_find_folder_by_id(user
,
2005 nm_contact_get_parent_id
2008 nm_folder_remove_contact(folder
, contact
);
2010 } else if (g_ascii_strcasecmp(cursor
->tag
, NM_A_FA_FOLDER
)
2012 /* TODO: write nm_folder_remove_folder */
2013 /* ignoring for now, should not be a big deal */
2014 /* folder = (NMFolder *) item;*/
2015 /* nm_folder_remove_folder(user->root_folder, folder);*/
2020 if (cursor
->method
== NMFIELD_METHOD_ADD
) {
2022 /* Not found, so we need to add it */
2023 if (g_ascii_strcasecmp(cursor
->tag
, NM_A_FA_CONTACT
) == 0) {
2025 const char *dn
= NULL
;
2028 nm_locate_field(NM_A_SZ_DN
,
2029 (NMField
*) cursor
->ptr_value
);
2030 if (locate
!= NULL
&& locate
->ptr_value
!= 0) {
2031 dn
= (const char *) locate
->ptr_value
;
2034 nm_create_contact_from_fields(cursor
);
2036 nm_folder_add_contact_to_list(user
->
2039 nm_release_contact(contact
);
2043 } else if (g_ascii_strcasecmp(cursor
->tag
, NM_A_FA_FOLDER
)
2045 folder
= nm_create_folder_from_fields(cursor
);
2046 nm_folder_add_folder_to_list(user
->root_folder
,
2048 nm_release_folder(folder
);
2059 nm_rtfize_text(char *text
)
2061 GString
*gstr
= NULL
;
2063 char *uni_str
= NULL
, *rtf
= NULL
;
2067 gstr
= g_string_sized_new(strlen(text
)*2);
2068 pch
= (unsigned char *)text
;
2070 if ((*pch
) <= 0x7F) {
2075 gstr
= g_string_append_c(gstr
, '\\');
2076 gstr
= g_string_append_c(gstr
, *pch
);
2079 gstr
= g_string_append(gstr
, "\\par ");
2082 gstr
= g_string_append_c(gstr
, *pch
);
2087 /* convert the utf-8 character to ucs-4 for rtf encoding */
2089 uc
= ((((gunichar
)pch
[0]) & 0x001F) << 6) |
2090 (((gunichar
)pch
[1]) & 0x003F);
2092 } else if(*pch
<= 0xEF) {
2093 uc
= ((((gunichar
)pch
[0]) & 0x000F) << 12) |
2094 ((((gunichar
)pch
[1]) & 0x003F) << 6) |
2095 (((gunichar
)pch
[2]) & 0x003F);
2097 } else if (*pch
<= 0xF7) {
2098 uc
= ((((gunichar
)pch
[0]) & 0x0007) << 18) |
2099 ((((gunichar
)pch
[1]) & 0x003F) << 12) |
2100 ((((gunichar
)pch
[2]) & 0x003F) << 6) |
2101 (((gunichar
)pch
[3]) & 0x003F);
2103 } else if (*pch
<= 0xFB) {
2104 uc
= ((((gunichar
)pch
[0]) & 0x0003) << 24) |
2105 ((((gunichar
)pch
[1]) & 0x003F) << 18) |
2106 ((((gunichar
)pch
[2]) & 0x003F) << 12) |
2107 ((((gunichar
)pch
[3]) & 0x003F) << 6) |
2108 (((gunichar
)pch
[4]) & 0x003F);
2110 } else if (*pch
<= 0xFD) {
2111 uc
= ((((gunichar
)pch
[0]) & 0x0001) << 30) |
2112 ((((gunichar
)pch
[1]) & 0x003F) << 24) |
2113 ((((gunichar
)pch
[2]) & 0x003F) << 18) |
2114 ((((gunichar
)pch
[3]) & 0x003F) << 12) |
2115 ((((gunichar
)pch
[4]) & 0x003F) << 6) |
2116 (((gunichar
)pch
[5]) & 0x003F);
2119 /* should never happen ... bogus utf-8! */
2120 purple_debug_info("novell", "bogus utf-8 lead byte: 0x%X\n", pch
[0]);
2124 uni_str
= g_strdup_printf("\\u%d?", uc
);
2125 purple_debug_info("novell", "unicode escaped char %s\n", uni_str
);
2126 gstr
= g_string_append(gstr
, uni_str
);
2132 rtf
= g_strdup_printf(RTF_TEMPLATE
, gstr
->str
);
2133 g_string_free(gstr
, TRUE
);