static guint sipe_ocs2005_availability_from_status(struct sipe_core_private *sipe_private) { const gchar *status = sipe_private->status; if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_INVISIBLE)) || sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_OFFLINE))) return(SIPE_OCS2005_AVAILABILITY_OFFLINE); else return(SIPE_OCS2005_AVAILABILITY_ONLINE); }
void sipe_group_create(struct sipe_core_private *sipe_private, struct sipe_ucs_transaction *trans, const gchar *name, const gchar *who) { /* "trans" is always set for UCS code paths, otherwise NULL */ if (trans) { sipe_ucs_group_create(sipe_private, trans, name, who); } else { struct transaction_payload *payload = g_new0(struct transaction_payload, 1); struct group_user_context *ctx = g_new0(struct group_user_context, 1); const gchar *soap_name = sipe_strequal(name, _("Other Contacts")) ? "~" : name; gchar *request; ctx->group_name = g_strdup(name); ctx->user_name = g_strdup(who); payload->destroy = sipe_group_context_destroy; payload->data = ctx; /* soap_name can contain restricted characters */ request = g_markup_printf_escaped("<m:name>%s</m:name>" "<m:externalURI />", soap_name); sip_soap_request_cb(sipe_private, "addGroup", request, process_add_group_response, payload); g_free(request); } }
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); }
static void assert_stringify(const sipe_xml *xml, int expected, ...) { va_list args; gchar *string = sipe_xml_stringify(xml); va_start(args, expected); while (expected-- > 0) { const gchar *alternative = va_arg(args, const gchar *); if (sipe_strequal(string, alternative)) { succeeded++; break; } else { printf("XML stringify alternative FAILED: '%s' (trying next...)\n", alternative ? alternative : "(nil)"); } } va_end(args); if (expected < 0) { printf("[%s]\nXML stringify all alternatives FAILED: '%s'\n", teststring, string ? string : "(nil)"); failed++; } g_free(string); }
/** 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; }
char * sipe_ews_get_oof_note(struct sipe_calendar *cal) { time_t now = time(NULL); if (!cal || !cal->oof_state) return NULL; if (sipe_strequal(cal->oof_state, "Enabled") || (sipe_strequal(cal->oof_state, "Scheduled") && now >= cal->oof_start && now <= cal->oof_end)) { return cal->oof_note; } else { return NULL; } }
const sipe_xml *sipe_xml_twin(const sipe_xml *node) { sipe_xml *sibling; if (!node) return NULL; for (sibling = node->sibling; sibling; sibling = sibling->sibling) { if (sipe_strequal(node->name, sibling->name)) return sibling; } return NULL; }
static void assert_data(const sipe_xml *xml, const gchar *s) { gchar *data = sipe_xml_data(xml); if (sipe_strequal(s, data)) { succeeded++; } else { printf("[%s]\nXML data FAILED: '%s' expected: '%s'\n", teststring, data ? data : "(nil)", s ? s : "(nil)"); failed++; } g_free(data); }
static void assert_name(const sipe_xml *xml, const gchar *s) { const gchar *name = sipe_xml_name(xml); if (sipe_strequal(name, s)) { succeeded++; } else { printf("[%s]\nXML name FAILED: '%s' expected: '%s'\n", teststring, name ? name : "(nil)", s ? s : "(nil)"); failed++; } }
static gboolean sipe_process_incoming_x_msmsgsinvite(struct sipe_core_private *sipe_private, struct sip_dialog *dialog, GSList *parsed_body) { gboolean found = FALSE; if (parsed_body) { const gchar *invitation_command = sipe_utils_nameval_find(parsed_body, "Invitation-Command"); if (sipe_strequal(invitation_command, "INVITE")) { sipe_ft_incoming_transfer(sipe_private, dialog, parsed_body); found = TRUE; } else if (sipe_strequal(invitation_command, "CANCEL")) { sipe_ft_incoming_cancel(dialog, parsed_body); found = TRUE; } else if (sipe_strequal(invitation_command, "ACCEPT")) { sipe_ft_incoming_accept(dialog, parsed_body); found = TRUE; } } return found; }
/** 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; }
static void assert_attribute(const sipe_xml *xml, const gchar *key, const gchar *value) { const gchar *attr = sipe_xml_attribute(xml, key); if (sipe_strequal(value, attr)) { succeeded++; } else { printf("[%s]\nXML attr FAILED: '%s': '%s' expected: '%s'\n", teststring, key ? key : "(nil)", attr ? attr : "(nil)", value ? value : "(nil)"); failed++; } }
static int sipe_cal_get_wday(char *wday_name) { int i; if (!wday_name) return -1; for (i = 0; i < 7; i++) { if (sipe_strequal(wday_names[i], wday_name)) { return i; } } return -1; }
gboolean sipe_core_ft_incoming_stop(struct sipe_file_transfer *ft) { static const guchar BYE[] = "BYE 16777989\r\n"; const gsize BUFFER_SIZE = 50; const gsize MAC_OFFSET = 4; struct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE; gchar buffer[BUFFER_SIZE]; gsize mac_len; gchar *mac; gchar *mac1; if (!sipe_backend_ft_write(SIPE_FILE_TRANSFER_PUBLIC, BYE, sizeof(BYE) - 1)) { raise_ft_socket_write_error_and_cancel(ft_private); return FALSE; } if (!read_line(ft_private, (guchar *) buffer, BUFFER_SIZE)) { raise_ft_socket_read_error_and_cancel(ft_private); return FALSE; } mac_len = strlen(buffer); if (mac_len < (MAC_OFFSET)) { raise_ft_error_and_cancel(ft_private, _("Received MAC is corrupted")); return FALSE; } /* Check MAC */ mac = g_strndup(buffer + MAC_OFFSET, mac_len - MAC_OFFSET); mac1 = sipe_hmac_finalize(ft_private->hmac_context); if (!sipe_strequal(mac, mac1)) { g_free(mac1); g_free(mac); raise_ft_error_and_cancel(ft_private, _("Received file is corrupted")); return(FALSE); } g_free(mac1); g_free(mac); return(TRUE); }
struct sipe_group* sipe_group_find_by_name(struct sipe_core_private *sipe_private, const gchar * name) { struct sipe_group *group; GSList *entry; if (!sipe_private || !name) return NULL; entry = sipe_private->groups->list; while (entry) { group = entry->data; if (sipe_strequal(group->name, name)) { return group; } entry = entry->next; } return NULL; }
void sipe_conf_cancel_unaccepted(struct sipe_core_private *sipe_private, struct sipmsg *msg) { const gchar *callid1 = msg ? sipmsg_find_header(msg, "Call-ID") : NULL; GSList *it = sipe_private->sessions_to_accept; while (it) { struct conf_accept_ctx *ctx = it->data; const gchar *callid2 = NULL; if (msg && ctx->msg) callid2 = sipmsg_find_header(ctx->msg, "Call-ID"); if (sipe_strequal(callid1, callid2)) { GSList *tmp; if (ctx->msg) sip_transport_response(sipe_private, ctx->msg, 487, "Request Terminated", NULL); if (msg) sip_transport_response(sipe_private, msg, 200, "OK", NULL); sipe_user_close_ask(ctx->ask_ctx); conf_accept_ctx_free(ctx); tmp = it; it = it->next; sipe_private->sessions_to_accept = g_slist_delete_link(sipe_private->sessions_to_accept, tmp); if (callid1) break; } else it = it->next; } }
gboolean sipe_backend_status_changed(struct sipe_core_public *sipe_public, guint activity, const gchar *message) { struct sipe_backend_private *purple_private = sipe_public->backend_private; PurpleStatus *status = purple_account_get_active_status(purple_private->account); const gchar *status_id = sipe_purple_activity_to_token(activity); gboolean changed = TRUE; if (g_str_equal(status_id, purple_status_get_id(status)) && sipe_strequal(message, purple_status_get_attr_string(status, SIPE_PURPLE_STATUS_ATTR_ID_MESSAGE))) { changed = FALSE; } if (purple_savedstatus_is_idleaway()) { changed = FALSE; } return(changed); }
const sipe_xml *sipe_xml_child(const sipe_xml *parent, const gchar *name) { gchar **names; const sipe_xml *child = NULL; if (!parent || !name) return NULL; /* 0: child name */ /* 1: trailing path (optional) */ names = g_strsplit(name, "/", 2); for (child = parent->first; child; child = child->sibling) { if (sipe_strequal(names[0], child->name)) break; } /* recurse into path */ if (child && names[1]) child = sipe_xml_child(child, names[1]); g_strfreev(names); return child; }
static guint sipe_ocs2005_activity_from_status(struct sipe_core_private *sipe_private) { const gchar *status = sipe_private->status; if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_AWAY))) { return(SIPE_OCS2005_ACTIVITY_AWAY); /*} else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_LUNCH))) { return(SIPE_OCS2005_ACTIVITY_LUNCH); */ } else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_BRB))) { return(SIPE_OCS2005_ACTIVITY_BRB); } else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_AVAILABLE))) { return(SIPE_OCS2005_ACTIVITY_AVAILABLE); /*} else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_ON_PHONE))) { return(SIPE_OCS2005_ACTIVITY_ON_PHONE); */ } else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_BUSY)) || sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_DND))) { return(SIPE_OCS2005_ACTIVITY_BUSY); } else if (sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_INVISIBLE)) || sipe_strequal(status, sipe_status_activity_to_token(SIPE_ACTIVITY_OFFLINE))) { return(SIPE_OCS2005_ACTIVITY_AWAY); } else { return(SIPE_OCS2005_ACTIVITY_AVAILABLE); } }
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) {
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); }
static gboolean sipe_is_user_available(struct sipe_core_private *sipe_private) { return(sipe_strequal(sipe_private->status, sipe_status_activity_to_token(SIPE_ACTIVITY_AVAILABLE))); }
void sipe_ocs2005_apply_calendar_status(struct sipe_core_private *sipe_private, struct sipe_buddy *sbuddy, const char *status_id) { time_t cal_avail_since; int cal_status = sipe_cal_get_status(sbuddy, time(NULL), &cal_avail_since); int avail; gchar *self_uri; if (!sbuddy) return; if (cal_status < SIPE_CAL_NO_DATA) { SIPE_DEBUG_INFO("sipe_apply_calendar_status: cal_status : %d for %s", cal_status, sbuddy->name); SIPE_DEBUG_INFO("sipe_apply_calendar_status: cal_avail_since : %s", asctime(localtime(&cal_avail_since))); } /* scheduled Cal update call */ if (!status_id) { status_id = sbuddy->last_non_cal_status_id; g_free(sbuddy->activity); sbuddy->activity = g_strdup(sbuddy->last_non_cal_activity); } if (!status_id) { SIPE_DEBUG_INFO("sipe_apply_calendar_status: status_id is NULL for %s, exiting.", sbuddy->name ? sbuddy->name : "" ); return; } /* adjust to calendar status */ if (cal_status != SIPE_CAL_NO_DATA) { SIPE_DEBUG_INFO("sipe_apply_calendar_status: user_avail_since: %s", asctime(localtime(&sbuddy->user_avail_since))); if ((cal_status == SIPE_CAL_BUSY) && (cal_avail_since > sbuddy->user_avail_since) && sipe_ocs2007_status_is_busy(status_id)) { status_id = sipe_status_activity_to_token(SIPE_ACTIVITY_BUSY); g_free(sbuddy->activity); sbuddy->activity = g_strdup(sipe_core_activity_description(SIPE_ACTIVITY_IN_MEETING)); } avail = sipe_ocs2007_availability_from_status(status_id, NULL); SIPE_DEBUG_INFO("sipe_apply_calendar_status: activity_since : %s", asctime(localtime(&sbuddy->activity_since))); if (cal_avail_since > sbuddy->activity_since) { if ((cal_status == SIPE_CAL_OOF) && sipe_ocs2007_availability_is_away(avail)) { g_free(sbuddy->activity); sbuddy->activity = g_strdup(sipe_core_activity_description(SIPE_ACTIVITY_OOF)); } } } /* then set status_id actually */ SIPE_DEBUG_INFO("sipe_apply_calendar_status: to %s for %s", status_id, sbuddy->name ? sbuddy->name : "" ); sipe_backend_buddy_set_status(SIPE_CORE_PUBLIC, sbuddy->name, sipe_status_token_to_activity(status_id)); /* set our account state to the one in roaming (including calendar info) */ self_uri = sip_uri_self(sipe_private); if (SIPE_CORE_PRIVATE_FLAG_IS(INITIAL_PUBLISH) && sipe_strcase_equal(sbuddy->name, self_uri)) { if (sipe_strequal(status_id, sipe_status_activity_to_token(SIPE_ACTIVITY_OFFLINE))) { /* do not let offline status switch us off */ status_id = sipe_status_activity_to_token(SIPE_ACTIVITY_INVISIBLE); } sipe_status_and_note(sipe_private, status_id); } g_free(self_uri); }
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 sipe_core_ft_outgoing_start(struct sipe_file_transfer *ft, gsize total_size) { static const guchar VER[] = "VER MSN_SECURE_FTP\r\n"; const gsize BUFFER_SIZE = 50; struct sipe_file_transfer_private *ft_private = SIPE_FILE_TRANSFER_PRIVATE; guchar buf[BUFFER_SIZE]; gchar **parts; unsigned auth_cookie_received; gboolean users_match; if (!read_line(ft_private, buf, BUFFER_SIZE)) { raise_ft_socket_read_error_and_cancel(ft_private); return; } if (!sipe_strequal((gchar *)buf, (gchar *)VER)) { raise_ft_error_and_cancel(ft_private, _("File transfer initialization failed.")); SIPE_DEBUG_INFO("File transfer VER string incorrect, received: %s expected: %s", buf, VER); return; } if (!write_exact(ft_private, VER, sizeof(VER) - 1)) { raise_ft_socket_write_error_and_cancel(ft_private); return; } if (!read_line(ft_private, buf, BUFFER_SIZE)) { raise_ft_socket_read_error_and_cancel(ft_private); return; } parts = g_strsplit((gchar *)buf, " ", 3); auth_cookie_received = g_ascii_strtoull(parts[2], NULL, 10); /* dialog->with has 'sip:' prefix, skip these four characters */ users_match = sipe_strcase_equal(parts[1], (ft_private->dialog->with + 4)); g_strfreev(parts); SIPE_DEBUG_INFO("File transfer authentication: %s Expected: USR %s %u", buf, ft_private->dialog->with + 4, ft_private->auth_cookie); if (!users_match || (ft_private->auth_cookie != auth_cookie_received)) { raise_ft_error_and_cancel(ft_private, _("File transfer authentication failed.")); return; } g_sprintf((gchar *)buf, "FIL %" G_GSIZE_FORMAT "\r\n", total_size); if (!write_exact(ft_private, buf, strlen((gchar *)buf))) { raise_ft_socket_write_error_and_cancel(ft_private); return; } /* TFR */ if (!read_line(ft_private ,buf, BUFFER_SIZE)) { raise_ft_socket_read_error_and_cancel(ft_private); return; } ft_private->bytes_remaining_chunk = 0; ft_private->cipher_context = sipe_cipher_context_init(ft_private->encryption_key); ft_private->hmac_context = sipe_hmac_context_init(ft_private->hash_key); }
/** 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; }
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); }