Mercurial > pidgin.yaz
diff src/protocols/novell/nmevent.c @ 8675:9ee2542d1104
[gaim-migrate @ 9428]
A GroupWise plugin from Novell.
committer: Tailor Script <tailor@pidgin.im>
author | Sean Egan <seanegan@gmail.com> |
---|---|
date | Sat, 17 Apr 2004 13:55:28 +0000 |
parents | |
children | 046dd8ef2920 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/protocols/novell/nmevent.c Sat Apr 17 13:55:28 2004 +0000 @@ -0,0 +1,973 @@ +/* + * nmevent.c + * + * Copyright © 2004 Unpublished Work of Novell, Inc. All Rights Reserved. + * + * THIS WORK IS AN UNPUBLISHED WORK OF NOVELL, INC. NO PART OF THIS WORK MAY BE + * USED, PRACTICED, PERFORMED, COPIED, DISTRIBUTED, REVISED, MODIFIED, + * TRANSLATED, ABRIDGED, CONDENSED, EXPANDED, COLLECTED, COMPILED, LINKED, + * RECAST, TRANSFORMED OR ADAPTED WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, + * INC. ANY USE OR EXPLOITATION OF THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT + * THE PERPETRATOR TO CRIMINAL AND CIVIL LIABILITY. + * + * AS BETWEEN [GAIM] AND NOVELL, NOVELL GRANTS [GAIM] THE RIGHT TO REPUBLISH + * THIS WORK UNDER THE GPL (GNU GENERAL PUBLIC LICENSE) WITH ALL RIGHTS AND + * LICENSES THEREUNDER. IF YOU HAVE RECEIVED THIS WORK DIRECTLY OR INDIRECTLY + * FROM [GAIM] AS PART OF SUCH A REPUBLICATION, YOU HAVE ALL RIGHTS AND LICENSES + * GRANTED BY [GAIM] UNDER THE GPL. IN CONNECTION WITH SUCH A REPUBLICATION, IF + * ANYTHING IN THIS NOTICE CONFLICTS WITH THE TERMS OF THE GPL, SUCH TERMS + * PREVAIL. + * + */ + +#include <glib.h> +#include <string.h> +#include <time.h> +#include "nmevent.h" +#include "nmfield.h" +#include "nmconn.h" +#include "nmuserrecord.h" + +struct _NMEvent +{ + + /* Event type */ + int type; + + /* The DN of the event source */ + char *source; + + /* Timestamp of the event */ + guint32 gmt; + + /* Conference to associate with the event */ + NMConference *conference; + + /* User record to associate with the event */ + NMUserRecord *user_record; + + /* Text associated with the event */ + char *text; + + /* Reference count for event structure */ + int ref_count; + +}; + +/* Return a copy of src minus the RTF */ +static char * +_strip_rtf(const char *src, int len) +{ + const char *p = src; + char *q; + char *dest = g_new0(char, len + 1); + int level = 0; + + /* Make sure we are dealing with rtf */ + if (strncmp("{\\rtf1", src, strlen("{\\rtf1")) != 0) { + strncpy(dest, src, len); + return dest; + } + p += strlen("{\\rtf1"); + + q = dest; + while (*p != '\0') { + if (*p == '\\') { + if (level == 0) { + if (*(p + 1) == '\\' || *(p + 1) == '{' || *(p + 1) == '}') { + *q++ = *(p + 1); + p++; + } else if (*(p + 1) == 't' && *(p + 2) == 'a' && *(p + 3) == 'b') { + *q++ = '\t'; + p++; + } + } + p++; + } else if (*p == '{') { + level++; + p++; + } else if (*p == '}') { + level--; + p++; + } else if (level == 0) { + if ((*p == ' ' || *p == '\r') && (*(p + 1) != '\\')) { + p++; + + if (*p == '\n' && + (*(p + 1) == '{' || *(p + 1) == '}' || *(p + 1) == '\\')) { + p++; + } else { + /* We found some text */ + while (*p != '\0' && *p != '\\' && *p != '{' && *p != '}') { + *q++ = *p; + p++; + } + } + } else { + p++; + } + } else { + p++; + } + } + + return dest; +} + +/* Handle getdetails response and set the new user record into the event */ +static void +_got_user_for_event(NMUser * user, NMERR_T ret_val, + gpointer resp_data, gpointer user_data) +{ + NMUserRecord *user_record; + NMEvent *event; + nm_event_cb cb; + + if (user == NULL) + return; + + user_record = resp_data; + event = user_data; + + if (ret_val == NM_OK) { + if (event && user_record) { + + /* Add the user record to the event structure + * and make the callback. + */ + nm_event_set_user_record(event, user_record); + if ((cb = nm_user_get_event_callback(user))) { + cb(user, event); + } + } + + } else { + /* Cleanup resp_data */ + + } + + /* Clean up */ + if (event) + nm_release_event(event); + +} + +/* Handle getdetails response, set the new user record into the event + * and add the user record as a participant in the conference + */ +static void +_got_user_for_conference(NMUser * user, NMERR_T ret_val, + gpointer resp_data, gpointer user_data) +{ + NMUserRecord *user_record = resp_data; + NMEvent *event = user_data; + NMConference *conference; + nm_event_cb cb; + + if (user == NULL) + return; + + if (event && user_record) { + + conference = nm_event_get_conference(event); + if (conference) { + + /* Add source of event as recip of the conference */ + nm_conference_add_participant(conference, user_record); + + /* Add the user record to the event structure + * and make the callback. + */ + nm_event_set_user_record(event, user_record); + if ((cb = nm_user_get_event_callback(user))) { + cb(user, event); + } + } + } + + if (event) + nm_release_event(event); +} + +/* Read the receive message event, set up the event object, and + * get details for the event source if we don't have them yet. + */ +static NMERR_T +handle_receive_message(NMUser * user, NMEvent * event, gboolean autoreply) +{ + NMConference *conference; + NMUserRecord *user_record; + NMConn *conn; + NMERR_T rc = NM_OK; + guint32 size = 0, flags = 0; + char *msg = NULL; + char *nortf = NULL; + char *guid = NULL; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + /* Read the conference flags */ + if (rc == NM_OK) { + rc = nm_read_all(conn, (char *) &flags, sizeof(flags)); + } + + /* Read the message text */ + if (rc == NM_OK) { + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + + msg = g_new0(char, size + 1); + rc = nm_read_all(conn, msg, size); + + gaim_debug(GAIM_DEBUG_INFO, "novell", "Message is %s\n", msg); + + /* Auto replies are not in RTF format! */ + if (!autoreply) { + + nortf = _strip_rtf((const char *) msg, size); + + gaim_debug(GAIM_DEBUG_INFO, "novell", + "Message without RTF is %s\n", nortf); + + /* Store the event data */ + nm_event_set_text(event, nortf); + + } else { + + /* Store the event data */ + nm_event_set_text(event, msg); + } + } + } + + /* Check to see if we already know about the conference */ + conference = nm_conference_list_find(user, guid); + if (conference) { + + nm_conference_set_flags(conference, flags); + nm_event_set_conference(event, conference); + + /* Add a reference to the user record in our event object */ + user_record = nm_find_user_record(user, nm_event_get_source(event)); + if (user_record) { + nm_event_set_user_record(event, user_record); + } + + } else { + + /* This is a new conference, so create one and add it to our list */ + conference = nm_create_conference(guid); + nm_conference_set_flags(conference, flags); + + /* Add a reference to the conference in the event */ + nm_event_set_conference(event, conference); + + /* Add new conference to the conference list */ + nm_conference_list_add(user, conference); + + /* Check to see if we have details for the event source yet */ + user_record = nm_find_user_record(user, nm_event_get_source(event)); + if (user_record) { + + /* We do so add the user record as a recipient of the conference */ + nm_conference_add_participant(conference, user_record); + + /* Add a reference to the user record in our event object */ + nm_event_set_user_record(event, user_record); + + } else { + + /* Need to go to the server to get details for the user */ + rc = nm_send_get_details(user, nm_event_get_source(event), + _got_user_for_conference, event); + if (rc == NM_OK) + rc = -1; /* Not done processing the event yet! */ + } + + nm_release_conference(conference); + } + + if (msg) + g_free(msg); + + if (nortf) + g_free(nortf); + + if (guid) + g_free(guid); + + return rc; +} + +/* Read the invite event, set up the event object, and + * get details for the event source if we don't have them yet. + */ +static NMERR_T +handle_conference_invite(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint32 size = 0; + char *guid = NULL; + char *msg = NULL; + NMConn *conn; + NMUserRecord *user_record; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + /* Read the the message */ + if (rc == NM_OK) { + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + msg = g_new0(char, size + 1); + rc = nm_read_all(conn, msg, size); + } + } + + /* Store the event data */ + if (rc == NM_OK) { + NMConference *conference; + + nm_event_set_text(event, msg); + + conference = nm_conference_list_find(user, guid); + if (conference == NULL) { + conference = nm_create_conference(guid); + + /* Add new conference to the list and the event */ + nm_conference_list_add(user, conference); + nm_event_set_conference(event, conference); + + /* Check to see if we have details for the event source yet */ + user_record = nm_find_user_record(user, nm_event_get_source(event)); + if (user_record) { + + /* Add a reference to the user record in our event object */ + nm_event_set_user_record(event, user_record); + + } else { + + /* Need to go to the server to get details for the user */ + rc = nm_send_get_details(user, nm_event_get_source(event), + _got_user_for_event, event); + if (rc == NM_OK) + rc = -1; /* Not done processing the event yet! */ + } + + nm_release_conference(conference); + + } + } + + if (msg) + g_free(msg); + + if (guid) + g_free(guid); + + return rc; +} + +/* Read the invite notify event, set up the event object, and + * get details for the event source if we don't have them yet. + */ +static NMERR_T +handle_conference_invite_notify(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint32 size = 0; + char *guid = NULL; + NMConn *conn; + NMConference *conference; + NMUserRecord *user_record; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + conference = nm_conference_list_find(user, guid); + if (conference) { + nm_event_set_conference(event, conference); + + /* Check to see if we have details for the event source yet */ + user_record = nm_find_user_record(user, nm_event_get_source(event)); + if (user_record) { + + /* Add a reference to the user record in our event object */ + nm_event_set_user_record(event, user_record); + + } else { + + /* Need to go to the server to get details for the user */ + rc = nm_send_get_details(user, nm_event_get_source(event), + _got_user_for_event, event); + if (rc == NM_OK) + rc = -1; /* Not done processing the event yet! */ + } + + } else { + rc = NMERR_CONFERENCE_NOT_FOUND; + } + + + if (guid) + g_free(guid); + + return rc; +} + +/* Read the conference reject event and set up the event object */ +static NMERR_T +handle_conference_reject(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint32 size = 0; + char *guid = NULL; + NMConn *conn; + NMConference *conference; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + if (rc == NM_OK) { + conference = nm_conference_list_find(user, guid); + if (conference) { + nm_event_set_conference(event, conference); + } else { + rc = NMERR_CONFERENCE_NOT_FOUND; + } + } + + if (guid) + g_free(guid); + + return rc; +} + +/* Read the conference left event, set up the event object, and + * remove the conference from the list if there are no more + * participants + */ +static NMERR_T +handle_conference_left(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint32 size = 0, flags = 0; + char *guid = NULL; + NMConference *conference; + NMConn *conn; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + /* Read the conference flags */ + if (rc == NM_OK) { + rc = nm_read_all(conn, (char *) &flags, sizeof(flags)); + } + + if (rc == NM_OK) { + conference = nm_conference_list_find(user, guid); + if (conference) { + nm_event_set_conference(event, conference); + nm_conference_set_flags(conference, flags); + + nm_conference_remove_participant(conference, nm_event_get_source(event)); + if (nm_conference_get_participant_count(conference) == 0) { + nm_conference_list_remove(user, conference); + } + + } else { + rc = NMERR_CONFERENCE_NOT_FOUND; + } + } + + if (guid) + g_free(guid); + + return rc; +} + +/* Read the conference closed, set up the event object, and + * remove the conference from the list + */ +static NMERR_T +handle_conference_closed(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint32 size = 0; + char *guid = NULL; + NMConference *conference; + NMConn *conn; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + if (rc == NM_OK) { + conference = nm_conference_list_find(user, guid); + if (conference) { + nm_event_set_conference(event, conference); + nm_conference_list_remove(user, conference); + } else { + rc = NMERR_CONFERENCE_NOT_FOUND; + } + } + + if (guid) + g_free(guid); + + return rc; +} + +/* Read the conference joined event, set up the event object, and + * get details for the event source if we don't have them yet. + */ +static NMERR_T +handle_conference_joined(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint32 size = 0, flags = 0; + char *guid = NULL; + NMConn *conn; + NMConference *conference; + NMUserRecord *user_record; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + /* Read the conference flags */ + if (rc == NM_OK) { + rc = nm_read_all(conn, (char *) &flags, sizeof(flags)); + } + + if (rc == NM_OK) { + conference = nm_conference_list_find(user, guid); + if (conference) { + nm_conference_set_flags(conference, flags); + + nm_event_set_conference(event, conference); + + /* Add the new user to the participants list */ + user_record = nm_find_user_record(user, nm_event_get_source(event)); + if (user_record) { + nm_conference_add_participant(conference, user_record); + } else { + + /* Need to go to the server to get details for the user */ + rc = nm_send_get_details(user, nm_event_get_source(event), + _got_user_for_conference, event); + if (rc == NM_OK) + rc = -1; /* Not done processing the event yet! */ + } + + } else { + rc = NMERR_CONFERENCE_NOT_FOUND; + } + } + + if (guid) + g_free(guid); + + return rc; +} + +/* Read the typing event and set up the event object */ +static NMERR_T +handle_typing(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint32 size = 0; + char *guid = NULL; + NMConference *conference; + NMConn *conn; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + if (rc == NM_OK) { + conference = nm_conference_list_find(user, guid); + if (conference) { + nm_event_set_conference(event, conference); + } else { + rc = NMERR_CONFERENCE_NOT_FOUND; + } + } + + if (guid) + g_free(guid); + + return rc; +} + +/* Read the event, set up the event object, and update + * the status in the user record (for the event source) + */ +static NMERR_T +handle_status_change(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint16 status; + guint32 size; + char *text = NULL; + NMUserRecord *user_record; + NMConn *conn; + + conn = nm_user_get_conn(user); + + /* Read new status */ + rc = nm_read_all(conn, (char *) &status, sizeof(status)); + if (rc == NM_OK) { + + /* Read the status text */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + if (size > 0) { + text = g_new0(char, size + 1); + rc = nm_read_all(conn, text, size); + } + } + } + + if (rc == NM_OK) { + nm_event_set_text(event, text); + + /* Get a reference to the user record and store the new status */ + user_record = nm_find_user_record(user, nm_event_get_source(event)); + if (user_record) { + nm_event_set_user_record(event, user_record); + nm_user_record_set_status(user_record, status, text); + } + } + + if (text) + g_free(text); + + return rc; +} + +/* Read the undeliverable event */ +static NMERR_T +handle_undeliverable_status(NMUser * user, NMEvent * event) +{ + NMERR_T rc = NM_OK; + guint32 size = 0; + char *guid = NULL; + NMConn *conn; + + conn = nm_user_get_conn(user); + + /* Read the conference guid */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + guid = g_new0(char, size + 1); + rc = nm_read_all(conn, guid, size); + } + + if (guid) + g_free(guid); + + return rc; +} + +/******************************************************************************* + * Event API -- see header file for comments + ******************************************************************************/ + +NMEvent * +nm_create_event(int type, const char *source, guint32 gmt) +{ + NMEvent *event = g_new0(NMEvent, 1); + + event->type = type; + event->gmt = gmt; + + if (source) + event->source = g_strdup(source); + + event->ref_count = 1; + + return event; +} + +void +nm_release_event(NMEvent * event) +{ + if (event == NULL) { + return; + } + + if (--(event->ref_count) == 0) { + + if (event->source) + g_free(event->source); + + if (event->conference) + nm_release_conference(event->conference); + + if (event->user_record) + nm_release_user_record(event->user_record); + + if (event->text) + g_free(event->text); + + g_free(event); + } +} + + +NMConference * +nm_event_get_conference(NMEvent * event) +{ + if (event) + return event->conference; + else + return NULL; +} + +void +nm_event_set_conference(NMEvent * event, NMConference * conference) +{ + if (event && conference) { + nm_conference_add_ref(conference); + event->conference = conference; + } +} + +NMUserRecord * +nm_event_get_user_record(NMEvent * event) +{ + if (event) + return event->user_record; + else + return NULL; +} + +void +nm_event_set_user_record(NMEvent * event, NMUserRecord * user_record) +{ + if (event && user_record) { + nm_user_record_add_ref(user_record); + event->user_record = user_record; + } +} + +const char * +nm_event_get_text(NMEvent * event) +{ + if (event) + return event->text; + else + return NULL; +} + +void +nm_event_set_text(NMEvent * event, const char *text) +{ + if (event) { + if (text) + event->text = g_strdup(text); + else + event->text = NULL; + } +} + +const char * +nm_event_get_source(NMEvent * event) +{ + if (event) + return event->source; + else + return NULL; +} + +int +nm_event_get_type(NMEvent * event) +{ + if (event) + return event->type; + else + return -1; +} + +guint32 +nm_event_get_gmt(NMEvent * event) +{ + if (event) + return event->gmt; + else + return (guint32)-1; +} + +NMERR_T +nm_process_event(NMUser * user, int type) +{ + NMERR_T rc = NM_OK; + guint32 size = 0; + NMEvent *event = NULL; + char *source = NULL; + nm_event_cb cb; + NMConn *conn; + + if (user == NULL) + return NMERR_BAD_PARM; + + if (type < NMEVT_START || type > NMEVT_STOP) + return NMERR_PROTOCOL; + + conn = nm_user_get_conn(user); + + /* Read the event source */ + rc = nm_read_all(conn, (char *) &size, sizeof(size)); + if (rc == NM_OK) { + if (size > 0) { + source = g_new0(char, size); + + rc = nm_read_all(conn, source, size); + } + } + + /* Read the event data */ + if (rc == NM_OK) { + event = nm_create_event(type, source, time(0)); + + if (event) { + + switch (type) { + case NMEVT_STATUS_CHANGE: + rc = handle_status_change(user, event); + break; + + case NMEVT_RECEIVE_MESSAGE: + rc = handle_receive_message(user, event, FALSE); + break; + + case NMEVT_RECEIVE_AUTOREPLY: + rc = handle_receive_message(user, event, TRUE); + break; + + case NMEVT_USER_TYPING: + case NMEVT_USER_NOT_TYPING: + rc = handle_typing(user, event); + break; + + case NMEVT_CONFERENCE_LEFT: + rc = handle_conference_left(user, event); + break; + + case NMEVT_CONFERENCE_CLOSED: + rc = handle_conference_closed(user, event); + break; + + case NMEVT_CONFERENCE_JOINED: + rc = handle_conference_joined(user, event); + break; + + case NMEVT_CONFERENCE_INVITE: + rc = handle_conference_invite(user, event); + break; + + case NMEVT_CONFERENCE_REJECT: + rc = handle_conference_reject(user, event); + break; + + case NMEVT_CONFERENCE_INVITE_NOTIFY: + rc = handle_conference_invite_notify(user, event); + break; + + case NMEVT_UNDELIVERABLE_STATUS: + rc = handle_undeliverable_status(user, event); + break; + + case NMEVT_INVALID_RECIPIENT: + /* Nothing else to read, just callback */ + break; + + case NMEVT_USER_DISCONNECT: + /* Nothing else to read, just callback */ + break; + + case NMEVT_SERVER_DISCONNECT: + /* Nothing else to read, just callback */ + break; + + case NMEVT_RECEIVE_FILE: + case NMEVT_CONTACT_ADD: + /* Safely ignored for now */ + break; + + default: + gaim_debug(GAIM_DEBUG_INFO, "novell", + "Unknown event %d received.\n", type); + rc = NMERR_PROTOCOL; + break; + } + } + } + + if (rc == (NMERR_T)-1) { + /* -1 means that we are not ready to callback yet. */ + rc = NM_OK; + } else if (rc == NM_OK && (cb = nm_user_get_event_callback(user))) { + + cb(user, event); + + if (event) + nm_release_event(event); + } else { + if (event) + nm_release_event(event); + } + + /* Cleanup */ + if (source) + g_free(source); + + return rc; +}