* Copyright (c) 2004 Novell, Inc. All Rights Reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA #include "nmuserrecord.h" #define MAX_UINT32 0xFFFFFFFF /* The DN of the event source */ /* Timestamp of the event */ /* Conference to associate with the event */ NMConference *conference; /* User record to associate with the event */ NMUserRecord *user_record; /* Text associated with the event */ /* Reference count for event structure */ /* Handle getdetails response and set the new user record into the event */ _got_user_for_event(NMUser * user, NMERR_T ret_val, gpointer resp_data, gpointer user_data) NMUserRecord *user_record; if (event && user_record) { /* Add the user record to the event structure nm_event_set_user_record(event, user_record); if ((cb = nm_user_get_event_callback(user))) { /* Handle getdetails response, set the new user record into the event * and add the user record as a participant in the conference _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; if (event && user_record) { conference = nm_event_get_conference(event); /* Add source of event as recip of the conference */ nm_conference_add_participant(conference, user_record); /* Add the user record to the event structure nm_event_set_user_record(event, user_record); if ((cb = nm_user_get_event_callback(user))) { /* Read the receive message event, set up the event object, and * get details for the event source if we don't have them yet. handle_receive_message(NMUser * user, NMEvent * event, gboolean autoreply) NMConference *conference; NMUserRecord *user_record; guint32 size = 0, flags = 0; conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); /* Read the conference flags */ rc = nm_read_uint32(conn, &flags); /* Read the message text */ rc = nm_read_uint32(conn, &size); if (size > 100000) return NMERR_PROTOCOL; msg = g_new0(char, size + 1); rc = nm_read_all(conn, msg, size); purple_debug(PURPLE_DEBUG_INFO, "novell", "Message is %s\n", msg); /* Auto replies are not in RTF format! */ nortf = nm_rtf_strip_formatting(ctx, msg); purple_debug(PURPLE_DEBUG_INFO, "novell", "Message without RTF is %s\n", nortf); /* Store the event data */ nm_event_set_text(event, nortf); /* 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); 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)); nm_event_set_user_record(event, user_record); /* 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)); /* 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); /* 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); rc = -1; /* Not done processing the event yet! */ nm_release_conference(conference); /* Read the invite event, set up the event object, and * get details for the event source if we don't have them yet. handle_conference_invite(NMUser * user, NMEvent * event) NMUserRecord *user_record; conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); /* Read the the message */ rc = nm_read_uint32(conn, &size); if (size > 100000) return NMERR_PROTOCOL; msg = g_new0(char, size + 1); rc = nm_read_all(conn, msg, size); /* Store the event data */ 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)); /* Add a reference to the user record in our event object */ nm_event_set_user_record(event, user_record); /* 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); rc = -1; /* Not done processing the event yet! */ nm_release_conference(conference); /* Read the invite notify event, set up the event object, and * get details for the event source if we don't have them yet. handle_conference_invite_notify(NMUser * user, NMEvent * event) NMConference *conference; NMUserRecord *user_record; conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); conference = nm_conference_list_find(user, guid); 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)); /* Add a reference to the user record in our event object */ nm_event_set_user_record(event, user_record); /* 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); rc = -1; /* Not done processing the event yet! */ rc = NMERR_CONFERENCE_NOT_FOUND; /* Read the conference reject event and set up the event object */ handle_conference_reject(NMUser * user, NMEvent * event) NMConference *conference; conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); conference = nm_conference_list_find(user, guid); nm_event_set_conference(event, conference); rc = NMERR_CONFERENCE_NOT_FOUND; /* Read the conference left event, set up the event object, and * remove the conference from the list if there are no more handle_conference_left(NMUser * user, NMEvent * event) guint32 size = 0, flags = 0; NMConference *conference; conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); /* Read the conference flags */ rc = nm_read_uint32(conn, &flags); conference = nm_conference_list_find(user, guid); 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); rc = NMERR_CONFERENCE_NOT_FOUND; /* Read the conference closed, set up the event object, and * remove the conference from the list handle_conference_closed(NMUser * user, NMEvent * event) NMConference *conference; conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); conference = nm_conference_list_find(user, guid); nm_event_set_conference(event, conference); nm_conference_list_remove(user, conference); rc = NMERR_CONFERENCE_NOT_FOUND; /* Read the conference joined event, set up the event object, and * get details for the event source if we don't have them yet. handle_conference_joined(NMUser * user, NMEvent * event) guint32 size = 0, flags = 0; NMConference *conference; NMUserRecord *user_record; conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); /* Read the conference flags */ rc = nm_read_uint32(conn, &flags); conference = nm_conference_list_find(user, guid); 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)); nm_conference_remove_participant(conference, nm_user_record_get_dn(user_record)); nm_conference_add_participant(conference, user_record); /* 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); rc = -1; /* Not done processing the event yet! */ rc = NMERR_CONFERENCE_NOT_FOUND; /* Read the typing event and set up the event object */ handle_typing(NMUser * user, NMEvent * event) NMConference *conference; conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); conference = nm_conference_list_find(user, guid); nm_event_set_conference(event, conference); rc = NMERR_CONFERENCE_NOT_FOUND; /* Read the event, set up the event object, and update * the status in the user record (for the event source) handle_status_change(NMUser * user, NMEvent * event) NMUserRecord *user_record; conn = nm_user_get_conn(user); rc = nm_read_uint16(conn, &status); /* Read the status text */ rc = nm_read_uint32(conn, &size); if (size > 10000) return NMERR_PROTOCOL; text = g_new0(char, size + 1); rc = nm_read_all(conn, text, size); 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)); nm_event_set_user_record(event, user_record); nm_user_record_set_status(user_record, status, text); /* Read the undeliverable event */ handle_undeliverable_status(NMUser * user, NMEvent * event) conn = nm_user_get_conn(user); /* Read the conference guid */ rc = nm_read_uint32(conn, &size); if (size > 1000) return NMERR_PROTOCOL; guid = g_new0(char, size + 1); rc = nm_read_all(conn, guid, size); /******************************************************************************* * Event API -- see header file for comments ******************************************************************************/ nm_create_event(int type, const char *source, guint32 gmt) NMEvent *event = g_new0(NMEvent, 1); event->source = g_strdup(source); nm_release_event(NMEvent * event) if (--(event->ref_count) == 0) { nm_release_conference(event->conference); nm_release_user_record(event->user_record); nm_event_get_conference(NMEvent * event) return event->conference; nm_event_set_conference(NMEvent * event, NMConference * conference) if (event && conference) { nm_conference_add_ref(conference); event->conference = conference; nm_event_get_user_record(NMEvent * event) return event->user_record; 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; nm_event_get_text(NMEvent * event) nm_event_set_text(NMEvent * event, const char *text) event->text = g_strdup(text); nm_event_get_source(NMEvent * event) nm_event_get_type(NMEvent * event) nm_event_get_gmt(NMEvent * event) nm_process_event(NMUser * user, int type) if (type < NMEVT_START || type > NMEVT_STOP) conn = nm_user_get_conn(user); /* Read the event source */ rc = nm_read_uint32(conn, &size); /* Size is larger than our 1MB sanity check. Ignore it. */ source = g_new0(char, size); rc = nm_read_all(conn, source, size); /* Read the event data */ event = nm_create_event(type, source, time(0)); case NMEVT_STATUS_CHANGE: rc = handle_status_change(user, event); case NMEVT_RECEIVE_MESSAGE: rc = handle_receive_message(user, event, FALSE); case NMEVT_RECEIVE_AUTOREPLY: rc = handle_receive_message(user, event, TRUE); case NMEVT_USER_NOT_TYPING: rc = handle_typing(user, event); case NMEVT_CONFERENCE_LEFT: rc = handle_conference_left(user, event); case NMEVT_CONFERENCE_CLOSED: rc = handle_conference_closed(user, event); case NMEVT_CONFERENCE_JOINED: rc = handle_conference_joined(user, event); case NMEVT_CONFERENCE_INVITE: rc = handle_conference_invite(user, event); case NMEVT_CONFERENCE_REJECT: rc = handle_conference_reject(user, event); case NMEVT_CONFERENCE_INVITE_NOTIFY: rc = handle_conference_invite_notify(user, event); case NMEVT_UNDELIVERABLE_STATUS: rc = handle_undeliverable_status(user, event); case NMEVT_INVALID_RECIPIENT: /* Nothing else to read, just callback */ case NMEVT_USER_DISCONNECT: /* Nothing else to read, just callback */ case NMEVT_SERVER_DISCONNECT: /* Nothing else to read, just callback */ /* Safely ignored for now */ purple_debug(PURPLE_DEBUG_INFO, "novell", "Unknown event %d received.\n", type); /* -1 means that we are not ready to callback yet. */ } else if (rc == NM_OK && (cb = nm_user_get_event_callback(user))) {