static gboolean process_add_group_response(struct sipe_core_private *sipe_private, struct sipmsg *msg, struct transaction *trans) { if (msg->response == 200) { struct sipe_group *group; struct group_user_context *ctx = trans->payload->data; sipe_xml *xml; const sipe_xml *node; char *group_id; xml = sipe_xml_parse(msg->body, msg->bodylen); if (!xml) { return FALSE; } node = sipe_xml_child(xml, "Body/addGroup/groupID"); if (!node) { sipe_xml_free(xml); return FALSE; } group_id = sipe_xml_data(node); if (!group_id) { sipe_xml_free(xml); return FALSE; } group = sipe_group_add(sipe_private, ctx->group_name, NULL, NULL, g_ascii_strtoull(group_id, NULL, 10)); g_free(group_id); if (group) { struct sipe_buddy *buddy = sipe_buddy_find_by_uri(sipe_private, ctx->user_name); if (buddy) { sipe_buddy_insert_group(buddy, group); sipe_group_update_buddy(sipe_private, buddy); } } sipe_xml_free(xml); return TRUE; } return FALSE; }
void process_incoming_invite_conf(struct sipe_core_private *sipe_private, struct sipmsg *msg) { sipe_xml *xn_conferencing = sipe_xml_parse(msg->body, msg->bodylen); const sipe_xml *xn_focus_uri = sipe_xml_child(xn_conferencing, "focus-uri"); const sipe_xml *xn_audio = sipe_xml_child(xn_conferencing, "audio"); gchar *focus_uri = sipe_xml_data(xn_focus_uri); gboolean audio = sipe_strequal(sipe_xml_attribute(xn_audio, "available"), "true"); sipe_xml_free(xn_conferencing); SIPE_DEBUG_INFO("We have received invitation to Conference. Focus URI=%s", focus_uri); if (audio) { sip_transport_response(sipe_private, msg, 180, "Ringing", NULL); ask_accept_voice_conference(sipe_private, focus_uri, msg, (SipeUserAskCb) conf_accept_cb, (SipeUserAskCb) conf_decline_cb); } else { accept_incoming_invite_conf(sipe_private, focus_uri, FALSE, msg); } g_free(focus_uri); }
/** Create conference callback */ static gboolean process_conf_add_response(struct sipe_core_private *sipe_private, struct sipmsg *msg, struct transaction *trans) { if (msg->response >= 400) { SIPE_DEBUG_INFO_NOFORMAT("process_conf_add_response: SERVICE response is not 200. Failed to create conference."); /* @TODO notify user of failure to create conference */ return FALSE; } if (msg->response == 200) { sipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen); if (sipe_strequal("success", sipe_xml_attribute(xn_response, "code"))) { gchar *who = trans->payload->data; const sipe_xml *xn_conference_info = sipe_xml_child(xn_response, "addConference/conference-info"); struct sip_session *session = sipe_conf_create(sipe_private, NULL, sipe_xml_attribute(xn_conference_info, "entity")); SIPE_DEBUG_INFO("process_conf_add_response: session->focus_uri=%s", session->chat_session->id); session->pending_invite_queue = sipe_utils_slist_insert_unique_sorted(session->pending_invite_queue, g_strdup(who), (GCompareFunc)strcmp, g_free); } sipe_xml_free(xn_response); } return TRUE; }
void sipe_xml_free(sipe_xml *node) { sipe_xml *child; if (!node) return; /* we don't support partial tree deletion */ if (node->parent != NULL) { SIPE_DEBUG_ERROR_NOFORMAT("sipe_xml_free: partial delete attempt! Expect crash or memory leaks..."); } /* free children */ child = node->first; while (child) { sipe_xml *tmp = child->sibling; child->parent = NULL; /* detach from tree, see above */ sipe_xml_free(child); child = tmp; } /* free node */ g_free(node->name); if (node->data) g_string_free(node->data, TRUE); if (node->attributes) g_hash_table_destroy(node->attributes); g_free(node); }
/** Invite us to the focus callback */ static gboolean process_invite_conf_focus_response(struct sipe_core_private *sipe_private, struct sipmsg *msg, SIPE_UNUSED_PARAMETER struct transaction *trans) { struct sip_session *session = NULL; char *focus_uri = parse_from(sipmsg_find_header(msg, "To")); session = sipe_session_find_conference(sipe_private, focus_uri); if (!session) { SIPE_DEBUG_INFO("process_invite_conf_focus_response: unable to find conf session with focus=%s", focus_uri); g_free(focus_uri); return FALSE; } if (!session->focus_dialog) { SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: session's focus_dialog is NULL"); g_free(focus_uri); return FALSE; } sipe_dialog_parse(session->focus_dialog, msg, TRUE); if (msg->response >= 200) { /* send ACK to focus */ session->focus_dialog->cseq = 0; sip_transport_ack(sipe_private, session->focus_dialog); session->focus_dialog->outgoing_invite = NULL; session->focus_dialog->is_established = TRUE; } if (msg->response >= 400) { SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: INVITE response is not 200. Failed to join focus."); /* @TODO notify user of failure to join focus */ sipe_session_remove(sipe_private, session); g_free(focus_uri); return FALSE; } else if (msg->response == 200) { sipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen); const gchar *code = sipe_xml_attribute(xn_response, "code"); if (sipe_strequal(code, "success")) { /* subscribe to focus */ sipe_subscribe_conference(sipe_private, session, FALSE); } sipe_xml_free(xn_response); } g_free(focus_uri); return TRUE; }
void sipe_process_imdn(struct sipe_core_private *sipe_private, struct sipmsg *msg) { gchar *with = parse_from(sipmsg_find_header(msg, "From")); const gchar *callid = sipmsg_find_header(msg, "Call-ID"); static struct sip_session *session; sipe_xml *xn_imdn; const sipe_xml *node; gchar *message_id; gchar *message; session = sipe_session_find_chat_or_im(sipe_private, callid, with); if (!session) { SIPE_DEBUG_INFO("sipe_process_imdn: unable to find conf session with callid=%s", callid); g_free(with); return; } xn_imdn = sipe_xml_parse(msg->body, msg->bodylen); message_id = sipe_xml_data(sipe_xml_child(xn_imdn, "message-id")); message = g_hash_table_lookup(session->conf_unconfirmed_messages, message_id); /* recipient */ for (node = sipe_xml_child(xn_imdn, "recipient"); node; node = sipe_xml_twin(node)) { gchar *tmp = parse_from(sipe_xml_attribute(node, "uri")); gchar *uri = parse_from(tmp); gchar *status = sipe_xml_data(sipe_xml_child(node, "status")); guint error = status ? g_ascii_strtoull(status, NULL, 10) : 0; /* default to error if missing or conversion failed */ if ((error == 0) || (error >= 300)) sipe_user_present_message_undelivered(sipe_private, session, error, -1, uri, message); g_free(status); g_free(tmp); g_free(uri); } sipe_xml_free(xn_imdn); g_hash_table_remove(session->conf_unconfirmed_messages, message_id); SIPE_DEBUG_INFO("sipe_process_imdn: removed message %s from conf_unconfirmed_messages(count=%d)", message_id, g_hash_table_size(session->conf_unconfirmed_messages)); g_free(message_id); g_free(with); }
sipe_xml *sipe_xml_parse(const gchar *string, gsize length) { sipe_xml *result = NULL; if (string && length) { struct _parser_data *pd = g_new0(struct _parser_data, 1); if (xmlSAXUserParseMemory(&parser, pd, string, length)) pd->error = TRUE; if (pd->error) { sipe_xml_free(pd->root); } else { result = pd->root; } g_free(pd); } return result; }
int main(SIPE_UNUSED_PARAMETER int argc, SIPE_UNUSED_PARAMETER char **argv) { sipe_xml *xml; const sipe_xml *child1, *child2; #if 0 /* * No idea why the memory leak checks work on some platforms * but fail on others :-( Disable for now... */ g_mem_set_vtable(&memory_leak_check); #else (void) memory_leak_check; #endif /* empty XML */ xml = assert_parse(NULL, FALSE); assert_stringify(xml, 1, NULL); sipe_xml_free(xml); xml = assert_parse("", FALSE); sipe_xml_free(xml); xml = assert_parse("<?xml version=\"1.0\" ?>", FALSE); sipe_xml_free(xml); /* one node */ xml = assert_parse("<test></test>", TRUE); assert_name(xml, "test"); assert_data(xml, NULL); assert_stringify(xml, 1, "<test/>"); sipe_xml_free(xml); xml = assert_parse("<test/>", TRUE); assert_name(xml, "test"); assert_data(xml, NULL); assert_stringify(xml, 1, teststring); sipe_xml_free(xml); xml = assert_parse("<test>a</test>", TRUE); assert_name(xml, "test"); assert_data(xml, "a"); assert_stringify(xml, 1, teststring); sipe_xml_free(xml); xml = assert_parse("<test>a\nb</test>", TRUE); assert_name(xml, "test"); assert_data(xml, "a\nb"); assert_stringify(xml, 1, teststring); sipe_xml_free(xml); /* child node */ xml = assert_parse("<test>a<child>b</child></test>", TRUE); assert_name(xml, "test"); assert_data(xml, "a"); child1 = assert_child(xml, NULL, FALSE); child1 = assert_child(xml, "child", TRUE); assert_name(child1, "child"); assert_data(child1, "b"); child1 = assert_child(xml, "shouldnotmatch", FALSE); assert_data(child1, NULL); assert_stringify(xml, 1, teststring); sipe_xml_free(xml); xml = assert_parse("<test>a<child/></test>", TRUE); assert_name(xml, "test"); assert_data(xml, "a"); child1 = assert_child(xml, "child", TRUE); assert_name(child1, "child"); assert_data(child1, NULL); child1 = assert_child(xml, "shouldnotmatch", FALSE); assert_data(child1, NULL); assert_stringify(xml, 1, teststring); sipe_xml_free(xml); xml = assert_parse("<test>a<child>b<inner>c</inner></child></test>", TRUE); assert_name(xml, "test"); assert_data(xml, "a"); child1 = assert_child(xml, "child", TRUE); assert_name(child1, "child"); assert_data(child1, "b"); child1 = assert_child(child1, "inner", TRUE); assert_name(child1, "inner"); assert_data(child1, "c"); child1 = assert_child(xml, "child/inner", TRUE); assert_name(child1, "inner"); assert_data(child1, "c"); assert_stringify(xml, 1, teststring); sipe_xml_free(xml); xml = assert_parse("<test>a<child>b<inner>c<innerinner>d</innerinner></inner></child></test>", TRUE); assert_name(xml, "test"); assert_data(xml, "a"); child1 = assert_child(xml, "child", TRUE); assert_name(child1, "child"); assert_data(child1, "b"); child2 = assert_child(child1, "inner/innerinner", TRUE); assert_name(child2, "innerinner"); assert_data(child2, "d"); child1 = assert_child(child1, "inner", TRUE); assert_name(child1, "inner"); assert_data(child1, "c"); child1 = assert_child(child1, "innerinner", TRUE); assert_name(child1, "innerinner"); assert_data(child1, "d"); child1 = assert_child(xml, "child/inner", TRUE); assert_name(child1, "inner"); assert_data(child1, "c"); child1 = assert_child(xml, "child/inner/innerinner", TRUE); assert_name(child1, "innerinner"); assert_data(child1, "d"); assert_stringify(xml, 1, teststring); sipe_xml_free(xml); /* attributes */ xml = assert_parse("<test a=\"\">a</test>", TRUE); assert_name(xml, "test"); assert_data(xml, "a"); assert_attribute(xml, NULL, NULL); assert_attribute(xml, "a", ""); assert_attribute(xml, "b", NULL); assert_stringify(xml, 1, teststring); sipe_xml_free(xml); xml = assert_parse("<test a=\"1\" b=\"abc\">a</test>", TRUE); assert_name(xml, "test"); assert_data(xml, "a"); assert_attribute(xml, "a", "1"); assert_int_attribute(xml, "a", 1, 0); assert_attribute(xml, "b", "abc"); assert_attribute(xml, "c", NULL); assert_int_attribute(xml, "d", 100, 200); /* the attribute order depends on glib hashing :-( */ assert_stringify(xml, 2, teststring, "<test b=\"abc\" a=\"1\">a</test>"); sipe_xml_free(xml); /* attributes with namespace */ xml = assert_parse("<m:row m:uri=\"sip:\" m:displayName=\"X\" m:title=\"Y\" m:office=\"Z\" m:phone=\"0\" m:company=\"A\" m:city=\"B\" m:state=\"C\" m:country=\"D\" m:email=\"E\" />", TRUE); assert_name(xml, "row"); assert_data(xml, NULL); assert_attribute(xml, "uri", "sip:"); assert_attribute(xml, "displayName", "X"); assert_attribute(xml, "title", "Y"); assert_attribute(xml, "office", "Z"); assert_attribute(xml, "phone", "0"); assert_attribute(xml, "company", "A"); assert_attribute(xml, "city", "B"); assert_attribute(xml, "state", "C"); assert_attribute(xml, "country", "D"); assert_attribute(xml, "email", "E"); sipe_xml_free(xml); xml = assert_parse("<state xsi:type=\"aggregateState\" lastActive=\"date\" xmlns:xsi=\"http://one\" xmlns=\"http://two\"><availability>15500</availability></state>", TRUE); assert_name(xml, "state"); assert_data(xml, NULL); assert_attribute(xml, "type", "aggregateState"); assert_attribute(xml, "lastActive", "date"); assert_attribute(xml, "xsi", "http://one"); assert_attribute(xml, "xmlns", "http://two"); child1 = assert_child(xml, "availability", TRUE); assert_name(child1, "availability"); assert_data(child1, "15500"); sipe_xml_free(xml); /* broken XML */ xml = assert_parse("t", FALSE); sipe_xml_free(xml); xml = assert_parse("<>", FALSE); sipe_xml_free(xml); xml = assert_parse("<></>", FALSE); sipe_xml_free(xml); xml = assert_parse("<test>", FALSE); sipe_xml_free(xml); xml = assert_parse("<a a=\"1\" a=\"2\"></a>", FALSE); sipe_xml_free(xml); if (allocated) { printf("MEMORY LEAK: %" G_GSIZE_FORMAT " still allocated\n", allocated); failed++; } else { printf("MEMORY LEAK CHECK OK\n"); succeeded++; } printf("Result: %d PASSED %d FAILED\n", succeeded, failed); return(failed); }
void sipe_process_conference(struct sipe_core_private *sipe_private, struct sipmsg *msg) { sipe_xml *xn_conference_info; const sipe_xml *node; const sipe_xml *xn_subject; const gchar *focus_uri; struct sip_session *session; gboolean just_joined = FALSE; #ifdef HAVE_VV gboolean audio_was_added = FALSE; #endif if (msg->response != 0 && msg->response != 200) return; if (msg->bodylen == 0 || msg->body == NULL || !sipe_strequal(sipmsg_find_header(msg, "Event"), "conference")) return; xn_conference_info = sipe_xml_parse(msg->body, msg->bodylen); if (!xn_conference_info) return; focus_uri = sipe_xml_attribute(xn_conference_info, "entity"); session = sipe_session_find_conference(sipe_private, focus_uri); if (!session) { SIPE_DEBUG_INFO("sipe_process_conference: unable to find conf session with focus=%s", focus_uri); return; } if (!session->chat_session->backend) { gchar *self = sip_uri_self(sipe_private); /* create chat */ session->chat_session->backend = sipe_backend_chat_create(SIPE_CORE_PUBLIC, session->chat_session, session->chat_session->title, self); just_joined = TRUE; /* @TODO ask for full state (re-subscribe) if it was a partial one - * this is to obtain full list of conference participants. */ g_free(self); } /* subject */ if ((xn_subject = sipe_xml_child(xn_conference_info, "conference-description/subject"))) { g_free(session->subject); session->subject = sipe_xml_data(xn_subject); sipe_backend_chat_topic(session->chat_session->backend, session->subject); SIPE_DEBUG_INFO("sipe_process_conference: subject=%s", session->subject ? session->subject : ""); } /* IM MCU URI */ if (!session->im_mcu_uri) { for (node = sipe_xml_child(xn_conference_info, "conference-description/conf-uris/entry"); node; node = sipe_xml_twin(node)) { gchar *purpose = sipe_xml_data(sipe_xml_child(node, "purpose")); if (sipe_strequal("chat", purpose)) { g_free(purpose); session->im_mcu_uri = sipe_xml_data(sipe_xml_child(node, "uri")); SIPE_DEBUG_INFO("sipe_process_conference: im_mcu_uri=%s", session->im_mcu_uri); break; } g_free(purpose); } } /* users */ for (node = sipe_xml_child(xn_conference_info, "users/user"); node; node = sipe_xml_twin(node)) { const gchar *user_uri = sipe_xml_attribute(node, "entity"); const gchar *state = sipe_xml_attribute(node, "state"); gchar *role = sipe_xml_data(sipe_xml_child(node, "roles/entry")); gboolean is_operator = sipe_strequal(role, "presenter"); gboolean is_in_im_mcu = FALSE; gchar *self = sip_uri_self(sipe_private); if (sipe_strequal("deleted", state)) { if (sipe_backend_chat_find(session->chat_session->backend, user_uri)) { sipe_backend_chat_remove(session->chat_session->backend, user_uri); } } else { /* endpoints */ const sipe_xml *endpoint; for (endpoint = sipe_xml_child(node, "endpoint"); endpoint; endpoint = sipe_xml_twin(endpoint)) { const gchar *session_type; gchar *status = sipe_xml_data(sipe_xml_child(endpoint, "status")); gboolean connected = sipe_strequal("connected", status); g_free(status); if (!connected) continue; session_type = sipe_xml_attribute(endpoint, "session-type"); if (sipe_strequal("chat", session_type)) { is_in_im_mcu = TRUE; if (!sipe_backend_chat_find(session->chat_session->backend, user_uri)) { sipe_backend_chat_add(session->chat_session->backend, user_uri, !just_joined && g_ascii_strcasecmp(user_uri, self)); } if (is_operator) { sipe_backend_chat_operator(session->chat_session->backend, user_uri); } } else if (sipe_strequal("audio-video", session_type)) { #ifdef HAVE_VV if (!session->is_call) audio_was_added = TRUE; #endif } } if (!is_in_im_mcu) { if (sipe_backend_chat_find(session->chat_session->backend, user_uri)) { sipe_backend_chat_remove(session->chat_session->backend, user_uri); } } } g_free(role); g_free(self); } #ifdef HAVE_VV if (audio_was_added) { session->is_call = TRUE; ask_accept_voice_conference(sipe_private, focus_uri, NULL, (SipeUserAskCb) call_accept_cb, (SipeUserAskCb) call_decline_cb); } #endif /* entity-view, locked */ for (node = sipe_xml_child(xn_conference_info, "conference-view/entity-view"); node; node = sipe_xml_twin(node)) { const sipe_xml *xn_type = sipe_xml_child(node, "entity-state/media/entry/type"); gchar *tmp = NULL; if (xn_type && sipe_strequal("chat", (tmp = sipe_xml_data(xn_type)))) { const sipe_xml *xn_locked = sipe_xml_child(node, "entity-state/locked"); if (xn_locked) { gchar *locked = sipe_xml_data(xn_locked); gboolean prev_locked = session->locked; session->locked = sipe_strequal(locked, "true"); if (prev_locked && !session->locked) { sipe_user_present_info(sipe_private, session, _("This conference is no longer locked. Additional participants can now join.")); } if (!prev_locked && session->locked) { sipe_user_present_info(sipe_private, session, _("This conference is locked. Nobody else can join the conference while it is locked.")); } SIPE_DEBUG_INFO("sipe_process_conference: session->locked=%s", session->locked ? "TRUE" : "FALSE"); g_free(locked); } } g_free(tmp); } sipe_xml_free(xn_conference_info); if (session->im_mcu_uri) { struct sip_dialog *dialog = sipe_dialog_find(session, session->im_mcu_uri); if (!dialog) { dialog = sipe_dialog_add(session); dialog->callid = g_strdup(session->callid); dialog->with = g_strdup(session->im_mcu_uri); /* send INVITE to IM MCU */ sipe_im_invite(sipe_private, session, dialog->with, NULL, NULL, NULL, FALSE); } } sipe_process_pending_invite_queue(sipe_private, session); }
/** Invite us to the focus callback */ static gboolean process_invite_conf_focus_response(struct sipe_core_private *sipe_private, struct sipmsg *msg, SIPE_UNUSED_PARAMETER struct transaction *trans) { struct sip_session *session = NULL; char *focus_uri = parse_from(sipmsg_find_header(msg, "To")); session = sipe_session_find_conference(sipe_private, focus_uri); if (!session) { SIPE_DEBUG_INFO("process_invite_conf_focus_response: unable to find conf session with focus=%s", focus_uri); g_free(focus_uri); return FALSE; } if (!session->focus_dialog) { SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: session's focus_dialog is NULL"); g_free(focus_uri); return FALSE; } sipe_dialog_parse(session->focus_dialog, msg, TRUE); if (msg->response >= 200) { /* send ACK to focus */ session->focus_dialog->cseq = 0; sip_transport_ack(sipe_private, session->focus_dialog); session->focus_dialog->outgoing_invite = NULL; session->focus_dialog->is_established = TRUE; } if (msg->response >= 400) { gchar *reason = sipmsg_get_ms_diagnostics_reason(msg); SIPE_DEBUG_INFO_NOFORMAT("process_invite_conf_focus_response: INVITE response is not 200. Failed to join focus."); sipe_backend_notify_error(SIPE_CORE_PUBLIC, _("Failed to join the conference"), reason ? reason : _("no reason given")); g_free(reason); sipe_session_remove(sipe_private, session); g_free(focus_uri); return FALSE; } else if (msg->response == 200) { sipe_xml *xn_response = sipe_xml_parse(msg->body, msg->bodylen); const gchar *code = sipe_xml_attribute(xn_response, "code"); if (sipe_strequal(code, "success")) { /* subscribe to focus */ sipe_subscribe_conference(sipe_private, session->chat_session->id, FALSE); #ifdef HAVE_VV if (session->is_call) sipe_core_media_connect_conference(SIPE_CORE_PUBLIC, session->chat_session); #endif } sipe_xml_free(xn_response); } g_free(focus_uri); return TRUE; }
static void sipe_ews_process_avail_response(int return_code, const char *body, SIPE_UNUSED_PARAMETER const char *content_type, HttpConn *conn, void *data) { struct sipe_calendar *cal = data; SIPE_DEBUG_INFO_NOFORMAT("sipe_ews_process_avail_response: cb started."); if(!sipe_strequal(cal->as_url, cal->oof_url)) { /* whether reuse conn */ http_conn_set_close(conn); cal->http_conn = NULL; } if (return_code == 200 && body) { const sipe_xml *node; const sipe_xml *resp; /** ref: [MS-OXWAVLS] */ sipe_xml *xml = sipe_xml_parse(body, strlen(body)); /* Envelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/ResponseMessage@ResponseClass="Success" Envelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/MergedFreeBusy Envelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/CalendarEventArray/CalendarEvent Envelope/Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse/FreeBusyView/WorkingHours */ resp = sipe_xml_child(xml, "Body/GetUserAvailabilityResponse/FreeBusyResponseArray/FreeBusyResponse"); if (!resp) return; /* rather soap:Fault */ if (!sipe_strequal(sipe_xml_attribute(sipe_xml_child(resp, "ResponseMessage"), "ResponseClass"), "Success")) { return; /* Error response */ } /* MergedFreeBusy */ g_free(cal->free_busy); cal->free_busy = sipe_xml_data(sipe_xml_child(resp, "FreeBusyView/MergedFreeBusy")); /* WorkingHours */ node = sipe_xml_child(resp, "FreeBusyView/WorkingHours"); g_free(cal->working_hours_xml_str); cal->working_hours_xml_str = sipe_xml_stringify(node); SIPE_DEBUG_INFO("sipe_ews_process_avail_response: cal->working_hours_xml_str:\n%s", cal->working_hours_xml_str ? cal->working_hours_xml_str : ""); sipe_cal_events_free(cal->cal_events); cal->cal_events = NULL; /* CalendarEvents */ for (node = sipe_xml_child(resp, "FreeBusyView/CalendarEventArray/CalendarEvent"); node; node = sipe_xml_twin(node)) { char *tmp; /* <CalendarEvent> <StartTime>2009-12-07T13:30:00</StartTime> <EndTime>2009-12-07T14:30:00</EndTime> <BusyType>Busy</BusyType> <CalendarEventDetails> <ID>0000000...</ID> <Subject>Lunch</Subject> <Location>Cafe</Location> <IsMeeting>false</IsMeeting> <IsRecurring>true</IsRecurring> <IsException>false</IsException> <IsReminderSet>true</IsReminderSet> <IsPrivate>false</IsPrivate> </CalendarEventDetails> </CalendarEvent> */ struct sipe_cal_event *cal_event = g_new0(struct sipe_cal_event, 1); cal->cal_events = g_slist_append(cal->cal_events, cal_event); tmp = sipe_xml_data(sipe_xml_child(node, "StartTime")); cal_event->start_time = sipe_utils_str_to_time(tmp); g_free(tmp); tmp = sipe_xml_data(sipe_xml_child(node, "EndTime")); cal_event->end_time = sipe_utils_str_to_time(tmp); g_free(tmp); tmp = sipe_xml_data(sipe_xml_child(node, "BusyType")); if (sipe_strequal("Free", tmp)) { cal_event->cal_status = SIPE_CAL_FREE; } else if (sipe_strequal("Tentative", tmp)) { cal_event->cal_status = SIPE_CAL_TENTATIVE; } else if (sipe_strequal("Busy", tmp)) { cal_event->cal_status = SIPE_CAL_BUSY; } else if (sipe_strequal("OOF", tmp)) { cal_event->cal_status = SIPE_CAL_OOF; } else { cal_event->cal_status = SIPE_CAL_NO_DATA; } g_free(tmp); cal_event->subject = sipe_xml_data(sipe_xml_child(node, "CalendarEventDetails/Subject")); cal_event->location = sipe_xml_data(sipe_xml_child(node, "CalendarEventDetails/Location")); tmp = sipe_xml_data(sipe_xml_child(node, "CalendarEventDetails/IsMeeting")); cal_event->is_meeting = tmp ? sipe_strequal(tmp, "true") : TRUE; g_free(tmp); } sipe_xml_free(xml); cal->state = SIPE_EWS_STATE_AVAILABILITY_SUCCESS; sipe_ews_run_state_machine(cal); } else { if (return_code < 0) {
static void sipe_domino_process_calendar_response(int return_code, const char *body, const char *content_type, HttpConn *conn, void *data) { struct sipe_calendar *cal = data; SIPE_DEBUG_INFO_NOFORMAT("sipe_domino_process_calendar_response: cb started."); http_conn_set_close(conn); cal->http_conn = NULL; if (content_type && !g_str_has_prefix(content_type, "text/xml")) { cal->is_domino_disabled = TRUE; SIPE_DEBUG_INFO_NOFORMAT("sipe_domino_process_calendar_response: not XML, disabling."); return; } if (return_code == 200 && body) { const sipe_xml *node, *node2, *node3; sipe_xml *xml; SIPE_DEBUG_INFO("sipe_domino_process_calendar_response: SUCCESS, ret=%d", return_code); xml = sipe_xml_parse(body, strlen(body)); sipe_cal_events_free(cal->cal_events); cal->cal_events = NULL; /* viewentry */ for (node = sipe_xml_child(xml, "viewentry"); node; node = sipe_xml_twin(node)) { struct sipe_cal_event *cal_event = g_new0(struct sipe_cal_event, 1); cal->cal_events = g_slist_append(cal->cal_events, cal_event); cal_event->cal_status = SIPE_CAL_BUSY; cal_event->is_meeting = TRUE; /* SIPE_DEBUG_INFO("viewentry unid=%s", sipe_xml_attribute(node, "unid")); */ /* entrydata */ for (node2 = sipe_xml_child(node, "entrydata"); node2; node2 = sipe_xml_twin(node2)) { const char *name = sipe_xml_attribute(node2, "name"); SIPE_DEBUG_INFO("\tentrydata name=%s", name); if (sipe_strequal(name, VIEWENTITY_START0_TIME) || sipe_strequal(name, VIEWENTITY_START_TIME) || sipe_strequal(name, VIEWENTITY_END_TIME)) { char *tmp = sipe_xml_data(sipe_xml_child(node2, "datetime")); time_t time_val = sipe_utils_str_to_time(tmp); if (sipe_strequal(name, VIEWENTITY_START_TIME)) { cal_event->start_time = time_val; } else if (sipe_strequal(name, VIEWENTITY_END_TIME)) { cal_event->end_time = time_val; } SIPE_DEBUG_INFO("\t\tdatetime=%s", asctime(gmtime(&time_val))); g_free(tmp); } else if (sipe_strequal(name, VIEWENTITY_TEXT_LIST)) { int i = 0; /* test */ for (node3 = sipe_xml_child(node2, "textlist/text"); node3; node3 = sipe_xml_twin(node3)) { char *tmp = sipe_xml_data(node3); if (!tmp) continue; SIPE_DEBUG_INFO("\t\ttext=%s", tmp); if (i == 0) { cal_event->subject = g_strdup(tmp); SIPE_DEBUG_INFO("\t\t*Subj.=%s", tmp); } else { /* plain English, don't localize! */ if (!g_ascii_strncasecmp(tmp, "Location:", 9)) { if (strlen(tmp) > 9) { cal_event->location = g_strdup(g_strstrip(tmp+9)); SIPE_DEBUG_INFO("\t\t*Loc.=%s", cal_event->location); } /* Translators: (!) should be as in localized Lotus Notes to be able to extract meeting location */ } else if (g_str_has_prefix(tmp, _("Location:"))) { guint len = strlen(_("Location:")); if (strlen(tmp) > len) { cal_event->location = g_strdup(g_strstrip(tmp+len)); SIPE_DEBUG_INFO("\t\t*Loc.=%s", cal_event->location); } } } i++; g_free(tmp); } } } } sipe_xml_free(xml); /* creates FreeBusy from cal->cal_events */ g_free(cal->free_busy); cal->free_busy = sipe_domino_get_free_busy(cal->fb_start, cal->cal_events); /* update SIP server */ cal->is_updated = TRUE; if (cal->sip->ocs2007) { /* sipe.h */ publish_calendar_status_self(cal->sip->private, NULL); } else {
void process_incoming_message(struct sipe_core_private *sipe_private, struct sipmsg *msg) { gchar *from; const gchar *contenttype; gboolean found = FALSE; from = parse_from(sipmsg_find_header(msg, "From")); if (!from) return; SIPE_DEBUG_INFO("got message from %s: %s", from, msg->body); contenttype = sipmsg_find_header(msg, "Content-Type"); if (g_str_has_prefix(contenttype, "text/plain") || g_str_has_prefix(contenttype, "text/html") || g_str_has_prefix(contenttype, "multipart/related") || g_str_has_prefix(contenttype, "multipart/alternative")) { const gchar *callid = sipmsg_find_header(msg, "Call-ID"); gchar *html = get_html_message(contenttype, msg->body); struct sip_session *session = sipe_session_find_chat_or_im(sipe_private, callid, from); if (session && session->chat_session) { if (session->chat_session->type == SIPE_CHAT_TYPE_CONFERENCE) { /* a conference */ gchar *tmp = parse_from(sipmsg_find_header(msg, "Ms-Sender")); gchar *sender = parse_from(tmp); g_free(tmp); sipe_backend_chat_message(SIPE_CORE_PUBLIC, session->chat_session->backend, sender, 0, html); g_free(sender); } else { /* a multiparty chat */ sipe_backend_chat_message(SIPE_CORE_PUBLIC, session->chat_session->backend, from, 0, html); } } else { sipe_backend_im_message(SIPE_CORE_PUBLIC, from, html); } g_free(html); sip_transport_response(sipe_private, msg, 200, "OK", NULL); found = TRUE; } else if (g_str_has_prefix(contenttype, "application/im-iscomposing+xml")) { sipe_xml *isc = sipe_xml_parse(msg->body, msg->bodylen); const sipe_xml *state; gchar *statedata; if (!isc) { SIPE_DEBUG_INFO_NOFORMAT("process_incoming_message: can not parse iscomposing"); g_free(from); return; } state = sipe_xml_child(isc, "state"); if (!state) { SIPE_DEBUG_INFO_NOFORMAT("process_incoming_message: no state found"); sipe_xml_free(isc); g_free(from); return; } statedata = sipe_xml_data(state); if (statedata) { if (strstr(statedata, "active")) { sipe_backend_user_feedback_typing(SIPE_CORE_PUBLIC, from); } else { sipe_backend_user_feedback_typing_stop(SIPE_CORE_PUBLIC, from); } g_free(statedata); } sipe_xml_free(isc); sip_transport_response(sipe_private, msg, 200, "OK", NULL); found = TRUE; } else if (g_str_has_prefix(contenttype, "text/x-msmsgsinvite")) { const gchar *callid = sipmsg_find_header(msg, "Call-ID"); struct sip_session *session = sipe_session_find_chat_or_im(sipe_private, callid, from); if (session) { struct sip_dialog *dialog = sipe_dialog_find(session, from); GSList *body = sipe_ft_parse_msg_body(msg->body); found = sipe_process_incoming_x_msmsgsinvite(sipe_private, dialog, body); sipe_utils_nameval_free(body); if (found) { sip_transport_response(sipe_private, msg, 200, "OK", NULL); } } else { sip_transport_response(sipe_private, msg, 481, "Call Leg/Transaction Does Not Exist", NULL); found = TRUE; } } if (!found) { const gchar *callid = sipmsg_find_header(msg, "Call-ID"); struct sip_session *session = sipe_session_find_chat_or_im(sipe_private, callid, from); if (session) { gchar *errmsg = g_strdup_printf(_("Received a message with unrecognized contents from %s"), from); sipe_user_present_error(sipe_private, session, errmsg); g_free(errmsg); } SIPE_DEBUG_INFO("got unknown mime-type '%s'", contenttype); sip_transport_response(sipe_private, msg, 415, "Unsupported media type", NULL); } g_free(from); }
void process_incoming_info(struct sipe_core_private *sipe_private, struct sipmsg *msg) { const gchar *contenttype = sipmsg_find_header(msg, "Content-Type"); const gchar *callid = sipmsg_find_header(msg, "Call-ID"); gchar *from; struct sip_session *session; SIPE_DEBUG_INFO_NOFORMAT("process_incoming_info"); /* Call Control protocol */ if (g_str_has_prefix(contenttype, "application/csta+xml")) { process_incoming_info_csta(sipe_private, msg); return; } else if (g_str_has_prefix(contenttype, "application/xml+conversationinfo")) { process_incoming_info_conversation(sipe_private, msg); return; } from = parse_from(sipmsg_find_header(msg, "From")); session = sipe_session_find_chat_or_im(sipe_private, callid, from); if (!session) { g_free(from); return; } /* Group Chat uses text/plain */ if (session->is_groupchat) { process_incoming_info_groupchat(sipe_private, msg, session); g_free(from); return; } if (g_str_has_prefix(contenttype, "application/x-ms-mim")) { sipe_xml *xn_action = sipe_xml_parse(msg->body, msg->bodylen); const sipe_xml *xn_request_rm = sipe_xml_child(xn_action, "RequestRM"); const sipe_xml *xn_set_rm = sipe_xml_child(xn_action, "SetRM"); sipmsg_add_header(msg, "Content-Type", "application/x-ms-mim"); if (xn_request_rm) { //const char *rm = sipe_xml_attribute(xn_request_rm, "uri"); int bid = sipe_xml_int_attribute(xn_request_rm, "bid", 0); gchar *body = g_strdup_printf( "<?xml version=\"1.0\"?>\r\n" "<action xmlns=\"http://schemas.microsoft.com/sip/multiparty/\">" "<RequestRMResponse uri=\"sip:%s\" allow=\"%s\"/></action>\r\n", sipe_private->username, session->bid < bid ? "true" : "false"); sip_transport_response(sipe_private, msg, 200, "OK", body); g_free(body); } else if (xn_set_rm) { gchar *body; sipe_chat_set_roster_manager(session, sipe_xml_attribute(xn_set_rm, "uri")); body = g_strdup_printf( "<?xml version=\"1.0\"?>\r\n" "<action xmlns=\"http://schemas.microsoft.com/sip/multiparty/\">" "<SetRMResponse uri=\"sip:%s\"/></action>\r\n", sipe_private->username); sip_transport_response(sipe_private, msg, 200, "OK", body); g_free(body); } sipe_xml_free(xn_action); } else { /* looks like purple lacks typing notification for chat */ if (!session->chat_session) { sipe_xml *xn_keyboard_activity = sipe_xml_parse(msg->body, msg->bodylen); const char *status = sipe_xml_attribute(sipe_xml_child(xn_keyboard_activity, "status"), "status"); if (sipe_strequal(status, "type")) { sipe_backend_user_feedback_typing(SIPE_CORE_PUBLIC, from); } else if (sipe_strequal(status, "idle")) { sipe_backend_user_feedback_typing_stop(SIPE_CORE_PUBLIC, from); } sipe_xml_free(xn_keyboard_activity); } sip_transport_response(sipe_private, msg, 200, "OK", NULL); } g_free(from); }