void msn_sbconn_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part) { MsnMessage *msg; const char *passport; char *data; size_t size; msg = msn_message_new_msnslp(); passport = purple_normalize(slplink->session->account, slplink->remote_user); msn_message_set_header(msg, "P2P-Dest", passport); msg->part = msn_slpmsgpart_ref(part); data = msn_slpmsgpart_serialize(part, &size); msn_message_set_bin_data(msg, data, size); g_free(data); if (slplink->swboard == NULL) { slplink->swboard = msn_session_get_swboard(slplink->session, slplink->remote_user, MSN_SB_FLAG_FT); g_return_if_fail(slplink->swboard != NULL); /* If swboard is destroyed we will be too */ slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); } msn_switchboard_send_msg(slplink->swboard, msg, TRUE); msn_message_unref(msg); }
void msn_message_destroy(MsnMessage *msg) { g_return_if_fail(msg != NULL); if (msg->ref_count > 0) { msn_message_unref(msg); return; } #ifdef MSN_DEBUG_MSG purple_debug_info("msn", "message destroy (%p)\n", msg); #endif if (msg->remote_user != NULL) g_free(msg->remote_user); if (msg->body != NULL) g_free(msg->body); if (msg->content_type != NULL) g_free(msg->content_type); if (msg->charset != NULL) g_free(msg->charset); g_hash_table_destroy(msg->attr_table); g_list_free(msg->attr_list); g_free(msg); }
/** Called when we receive a nak of a special message. */ static void msg_nak(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnMessage *msg; msg = cmd->trans->data; msn_message_unref(msg); }
/** Called when we receive an ack of a special message. */ static void msg_ack(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnMessage *msg; msg = cmd->trans->data; if (msg->ack_cb != NULL) msg->ack_cb(msg->ack_data); msn_message_unref(msg); }
/* We have received the message nak. */ static void msg_nak(MsnMessage *msg, void *data) { MsnSlpMessage *slpmsg; slpmsg = data; msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); msn_message_unref(msg); }
static void send_clientcaps(MsnSwitchBoard *swboard) { MsnMessage *msg; msg = msn_message_new(MSN_MSG_CAPS); msn_message_set_content_type(msg, "text/x-clientcaps"); msn_message_set_flag(msg, 'U'); msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO)); msn_switchboard_send_msg(swboard, msg, TRUE); msn_message_unref(msg); }
static void ack_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSwitchBoard *swboard; MsnMessage *msg; msg = cmd->trans->data; if (msg->ack_cb != NULL) msg->ack_cb(msg, msg->ack_data); swboard = cmdproc->data; swboard->ack_list = g_list_remove(swboard->ack_list, msg); msn_message_unref(msg); }
void msn_slp_session_destroy(MsnSlpSession *session) { g_return_if_fail(session != NULL); if (session->orig_body != NULL) g_free(session->orig_body); if (session->outgoing_msg != NULL) msn_message_unref(session->outgoing_msg); if (session->call_id != NULL) g_free(session->call_id); g_free(session); }
static void process_queue(MsnSwitchBoard *swboard) { MsnMessage *msg; g_return_if_fail(swboard != NULL); purple_debug_info("msn", "Processing queue\n"); while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) { purple_debug_info("msn", "Sending message\n"); release_msg(swboard, msg); msn_message_unref(msg); } }
static void msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len) { MsnMessage *msg; msg = msn_message_new_from_cmd(cmdproc->session, cmd); msn_message_parse_payload(msg, payload, len, MSG_LINE_DEM,MSG_BODY_DEM); if (purple_debug_is_verbose()) msn_message_show_readable(msg, "SB RECV", FALSE); g_free (msg->remote_user); msg->remote_user = g_strdup(cmd->params[0]); msn_cmdproc_process_msg(cmdproc, msg); msn_message_unref(msg); }
/* We have received the message ack */ static void msg_ack(MsnMessage *msg, void *data) { MsnSlpMessage *slpmsg; long long real_size; slpmsg = data; real_size = (slpmsg->flags == 0x2) ? 0 : slpmsg->size; slpmsg->offset += msg->msnslp_header.length; slpmsg->msgs = g_list_remove(slpmsg->msgs, msg); if (slpmsg->offset < real_size) { if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED) { slpmsg->slpcall->xfer_msg = slpmsg; msn_message_ref(msg); purple_xfer_prpl_ready(slpmsg->slpcall->xfer); } else msn_slplink_send_msgpart(slpmsg->slplink, slpmsg); } else { /* The whole message has been sent */ if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000020 || slpmsg->flags == 0x1000030) { if (slpmsg->slpcall != NULL) { if (slpmsg->slpcall->cb) slpmsg->slpcall->cb(slpmsg->slpcall, NULL, 0); } } } msn_message_unref(msg); }
void msn_transaction_destroy(MsnTransaction *trans) { g_return_if_fail(trans != NULL); g_free(trans->command); g_free(trans->params); g_free(trans->payload); if (trans->data_free) trans->data_free(trans->data); #if 0 if (trans->pendent_cmd != NULL) msn_message_unref(trans->pendent_msg); #endif #if 0 MsnTransaction *elem; if (trans->queue != NULL) { while ((elem = g_queue_pop_head(trans->queue)) != NULL) msn_transaction_destroy(elem); g_queue_free(trans->queue); } #endif if (trans->callbacks != NULL && trans->has_custom_callbacks) g_hash_table_destroy(trans->callbacks); if (trans->timer) purple_timeout_remove(trans->timer); g_free(trans); }
void msn_switchboard_destroy(MsnSwitchBoard *swboard) { MsnSession *session; MsnMessage *msg; GList *l; if (purple_debug_is_verbose()) purple_debug_info("msn", "switchboard destroy: swboard(%p)\n", swboard); g_return_if_fail(swboard != NULL); if (swboard->destroying) return; swboard->destroying = TRUE; if (swboard->reconn_timeout_h > 0) purple_timeout_remove(swboard->reconn_timeout_h); /* If it linked us is because its looking for trouble */ while (swboard->slplinks != NULL) msn_slplink_destroy(swboard->slplinks->data); /* Destroy the message queue */ while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL) { if (swboard->error != MSN_SB_ERROR_NONE) { /* The messages could not be sent due to a switchboard error */ msg_error_helper(swboard->cmdproc, msg, MSN_MSG_ERROR_SB); } msn_message_unref(msg); } g_queue_free(swboard->msg_queue); /* msg_error_helper will both remove the msg from ack_list and unref it, so we don't need to do either here */ while ((l = swboard->ack_list) != NULL) msg_error_helper(swboard->cmdproc, l->data, MSN_MSG_ERROR_SB); g_free(swboard->im_user); g_free(swboard->auth_key); g_free(swboard->session_id); for (; swboard->users; swboard->users = g_list_delete_link(swboard->users, swboard->users)) g_free(swboard->users->data); session = swboard->session; session->switches = g_list_remove(session->switches, swboard); for (l = session->slplinks; l; l = l->next) { MsnSlpLink *slplink = l->data; if (slplink->swboard == swboard) slplink->swboard = NULL; } #if 0 /* This should never happen or we are in trouble. */ if (swboard->servconn != NULL) msn_servconn_destroy(swboard->servconn); #endif swboard->cmdproc->data = NULL; msn_servconn_set_disconnect_cb(swboard->servconn, NULL); msn_servconn_destroy(swboard->servconn); g_free(swboard); }
static void msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error) { MsnSwitchBoard *swboard; g_return_if_fail(cmdproc != NULL); g_return_if_fail(msg != NULL); if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL)) msg->nak_cb(msg, msg->ack_data); swboard = cmdproc->data; /* This is not good, and should be fixed somewhere else. */ g_return_if_fail(swboard != NULL); if (msg->type == MSN_MSG_TEXT) { const char *format, *str_reason; char *body_str, *body_enc, *pre, *post; #if 0 if (swboard->conv == NULL) { if (msg->ack_ref) msn_message_unref(msg); return; } #endif if (error == MSN_MSG_ERROR_TIMEOUT) { str_reason = _("Message may have not been sent " "because a timeout occurred:"); } else if (error == MSN_MSG_ERROR_SB) { switch (swboard->error) { case MSN_SB_ERROR_OFFLINE: str_reason = _("Message could not be sent, " "not allowed while invisible:"); break; case MSN_SB_ERROR_USER_OFFLINE: str_reason = _("Message could not be sent " "because the user is offline:"); break; case MSN_SB_ERROR_CONNECTION: str_reason = _("Message could not be sent " "because a connection error occurred:"); break; case MSN_SB_ERROR_TOO_FAST: str_reason = _("Message could not be sent " "because we are sending too quickly:"); break; default: str_reason = _("Message could not be sent " "because an error with " "the switchboard occurred:"); break; } } else { str_reason = _("Message may have not been sent " "because an unknown error occurred:"); } body_str = msn_message_to_string(msg); body_enc = g_markup_escape_text(body_str, -1); g_free(body_str); format = msn_message_get_attr(msg, "X-MMS-IM-Format"); msn_parse_format(format, &pre, &post); body_str = g_strdup_printf("%s%s%s", pre ? pre : "", body_enc ? body_enc : "", post ? post : ""); g_free(body_enc); g_free(pre); g_free(post); msn_switchboard_report_user(swboard, GAIM_MESSAGE_ERROR, str_reason); msn_switchboard_report_user(swboard, GAIM_MESSAGE_RAW, body_str); g_free(body_str); } /* If a timeout occures we will want the msg around just in case we * receive the ACK after the timeout. */ if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT) { swboard->ack_list = g_list_remove(swboard->ack_list, msg); msn_message_unref(msg); } }
static void msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error) { MsnSwitchBoard *swboard; g_return_if_fail(cmdproc != NULL); g_return_if_fail(msg != NULL); if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL)) msg->nak_cb(msg, msg->ack_data); swboard = cmdproc->data; /* This is not good, and should be fixed somewhere else. */ g_return_if_fail(swboard != NULL); if (msg->type == MSN_MSG_TEXT) { const char *format, *str_reason; char *body_str, *body_enc, *pre, *post; #if 0 if (swboard->conv == NULL) { if (msg->ack_ref) msn_message_unref(msg); return; } #endif if (error == MSN_MSG_ERROR_TIMEOUT) { str_reason = _("Message may have not been sent " "because a timeout occurred:"); } else if (error == MSN_MSG_ERROR_SB) { MsnSession *session = swboard->session; if (!session->destroying && msg->retries && swboard->im_user && (swboard->error == MSN_SB_ERROR_CONNECTION || swboard->error == MSN_SB_ERROR_UNKNOWN)) { MsnSwitchBoard *new_sw = msn_session_find_swboard(session, swboard->im_user); if (new_sw == NULL || new_sw->reconn_timeout_h == 0) { new_sw = msn_switchboard_new(session); new_sw->im_user = g_strdup(swboard->im_user); new_sw->reconn_timeout_h = purple_timeout_add_seconds(3, msg_resend_cb, new_sw); new_sw->flag |= MSN_SB_FLAG_IM; } body_str = msn_message_to_string(msg); body_enc = g_markup_escape_text(body_str, -1); g_free(body_str); purple_debug_info("msn", "queuing unsent message to %s: %s\n", swboard->im_user, body_enc); g_free(body_enc); msn_send_im_message(session, msg); msg->retries--; return; } switch (swboard->error) { case MSN_SB_ERROR_OFFLINE: str_reason = _("Message could not be sent, " "not allowed while invisible:"); break; case MSN_SB_ERROR_USER_OFFLINE: str_reason = _("Message could not be sent " "because the user is offline:"); break; case MSN_SB_ERROR_CONNECTION: str_reason = _("Message could not be sent " "because a connection error occurred:"); break; case MSN_SB_ERROR_TOO_FAST: str_reason = _("Message could not be sent " "because we are sending too quickly:"); break; case MSN_SB_ERROR_AUTHFAILED: str_reason = _("Message could not be sent " "because we were unable to establish a " "session with the server. This is " "likely a server problem, try again in " "a few minutes:"); break; default: str_reason = _("Message could not be sent " "because an error with " "the switchboard occurred:"); break; } } else { str_reason = _("Message may have not been sent " "because an unknown error occurred:"); } body_str = msn_message_to_string(msg); body_enc = g_markup_escape_text(body_str, -1); g_free(body_str); format = msn_message_get_attr(msg, "X-MMS-IM-Format"); msn_parse_format(format, &pre, &post); body_str = g_strdup_printf("%s%s%s", pre ? pre : "", body_enc ? body_enc : "", post ? post : ""); g_free(body_enc); g_free(pre); g_free(post); msn_switchboard_report_user(swboard, PURPLE_MESSAGE_ERROR, str_reason); msn_switchboard_report_user(swboard, PURPLE_MESSAGE_RAW, body_str); g_free(body_str); } /* If a timeout occures we will want the msg around just in case we * receive the ACK after the timeout. */ if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT) { swboard->ack_list = g_list_remove(swboard->ack_list, msg); msn_message_unref(msg); } }
/*Post the Offline Instant Message to User Conversation*/ static void msn_oim_report_to_user(MsnOimRecvData *rdata, const char *msg_str) { MsnMessage *message; const char *date; const char *from; const char *boundary; char *decode_msg = NULL, *clean_msg = NULL; gsize body_len; char **tokens; char *passport = NULL; time_t stamp; const char *charset = NULL; message = msn_message_new(MSN_MSG_UNKNOWN); msn_message_parse_payload(message, msg_str, strlen(msg_str), MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM); purple_debug_info("msn", "oim body:{%s}\n", message->body); boundary = msn_message_get_header_value(message, "boundary"); if (boundary != NULL) { char *bounds; char **part; bounds = g_strdup_printf("--%s" MSG_OIM_LINE_DEM, boundary); tokens = g_strsplit(message->body, bounds, 0); /* tokens+1 to skip the "This is a multipart message..." text */ for (part = tokens+1; *part != NULL; part++) { MsnMessage *multipart; const char *type; multipart = msn_message_new(MSN_MSG_UNKNOWN); msn_message_parse_payload(multipart, *part, strlen(*part), MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM); type = msn_message_get_content_type(multipart); if (type && !strcmp(type, "text/plain")) { decode_msg = (char *)purple_base64_decode(multipart->body, &body_len); charset = msn_message_get_charset(multipart); msn_message_unref(multipart); break; } msn_message_unref(multipart); } g_strfreev(tokens); g_free(bounds); if (decode_msg == NULL) { purple_debug_error("msn", "Couldn't find text/plain OIM message.\n"); msn_message_unref(message); return; } } else { decode_msg = (char *)purple_base64_decode(message->body, &body_len); charset = msn_message_get_charset(message); } if (charset && !((g_ascii_strncasecmp(charset, "UTF-8", 5) == 0) || (g_ascii_strncasecmp(charset, "UTF8", 4) == 0))) { clean_msg = g_convert(decode_msg, body_len, "UTF-8", charset, NULL, NULL, NULL); if (!clean_msg) { char *clean = purple_utf8_salvage(decode_msg); purple_debug_error("msn", "Failed to convert charset from %s to UTF-8 for OIM message: %s\n", charset, clean); clean_msg = g_strdup_printf(_("%s (There was an error receiving this message. " "Converting the encoding from %s to UTF-8 failed.)"), clean, charset); g_free(clean); } g_free(decode_msg); } else if (!g_utf8_validate(decode_msg, body_len, NULL)) { char *clean = purple_utf8_salvage(decode_msg); purple_debug_error("msn", "Received an OIM message that is not UTF-8," " and no encoding specified: %s\n", clean); if (charset) { clean_msg = g_strdup_printf(_("%s (There was an error receiving this message." " The charset was %s, but it was not valid UTF-8.)"), clean, charset); } else { clean_msg = g_strdup_printf(_("%s (There was an error receiving this message." " The charset was missing, but it was not valid UTF-8.)"), clean); } g_free(clean); g_free(decode_msg); } else { clean_msg = decode_msg; } from = msn_message_get_header_value(message, "X-OIM-originatingSource"); /* Match number to user's mobile number, FROM is a phone number if the other side pages you using your phone number */ if (from && !strncmp(from, "tel:+", 5)) { MsnUser *user = msn_userlist_find_user_with_mobile_phone( rdata->oim->session->userlist, from + 4); if (user && user->passport) passport = g_strdup(user->passport); } if (passport == NULL) { char *start, *end; from = msn_message_get_header_value(message, "From"); tokens = g_strsplit(from, " ", 2); if (tokens[1] != NULL) from = (const char *)tokens[1]; start = strchr(from, '<'); if (start != NULL) { start++; end = strchr(from, '>'); if (end != NULL) passport = g_strndup(start, end - start); } if (passport == NULL) passport = g_strdup(_("Unknown")); g_strfreev(tokens); } date = msn_message_get_header_value(message, "Date"); stamp = msn_oim_parse_timestamp(date); purple_debug_info("msn", "oim Date:{%s},passport{%s}\n", date, passport); purple_serv_got_im(purple_account_get_connection(rdata->oim->session->account), passport, clean_msg, 0, stamp); /*Now get the oim message ID from the oim_list. * and append to read list to prepare for deleting the Offline Message when sign out */ msn_oim_post_delete_msg(rdata); g_free(passport); g_free(clean_msg); msn_message_unref(message); }
void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { GHashTable *body; const gchar *command; const gchar *cookie; gboolean accepted = FALSE; g_return_if_fail(cmdproc != NULL); g_return_if_fail(msg != NULL); body = msn_message_get_hashtable_from_body(msg); if (body == NULL) { purple_debug_warning("msn", "Unable to parse invite msg body.\n"); return; } /* * GUID is NOT always present but Invitation-Command and Invitation-Cookie * are mandatory. */ command = g_hash_table_lookup(body, "Invitation-Command"); cookie = g_hash_table_lookup(body, "Invitation-Cookie"); if (command == NULL || cookie == NULL) { purple_debug_warning("msn", "Invalid invitation message: either Invitation-Command " "or Invitation-Cookie is missing or invalid.\n" ); return; } else if (!strcmp(command, "INVITE")) { const gchar *guid = g_hash_table_lookup(body, "Application-GUID"); if (guid == NULL) { purple_debug_warning("msn", "Invite msg missing Application-GUID.\n"); accepted = TRUE; } else if (!strcmp(guid, MSN_FT_GUID)) { } else if (!strcmp(guid, "{02D3C01F-BF30-4825-A83A-DE7AF41648AA}")) { purple_debug_info("msn", "Computer call\n"); if (cmdproc->session) { PurpleIMConversation *im = NULL; gchar *from = msg->remote_user; gchar *buf = NULL; if (from) im = purple_conversations_find_im_with_account( from, cmdproc->session->account); if (im) buf = g_strdup_printf( _("%s sent you a voice chat " "invite, which is not yet " "supported."), from); if (buf) { purple_conversation_write(PURPLE_CONVERSATION(im), NULL, buf, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NOTIFY, time(NULL)); g_free(buf); } } } else { const gchar *application = g_hash_table_lookup(body, "Application-Name"); purple_debug_warning("msn", "Unhandled invite msg with GUID %s: %s.\n", guid, application ? application : "(null)"); } if (!accepted) { MsnSwitchBoard *swboard = cmdproc->data; char *text; MsnMessage *cancel; cancel = msn_message_new(MSN_MSG_TEXT); msn_message_set_content_type(cancel, "text/x-msmsgsinvite"); msn_message_set_charset(cancel, "UTF-8"); msn_message_set_flag(cancel, 'U'); text = g_strdup_printf("Invitation-Command: CANCEL\r\n" "Invitation-Cookie: %s\r\n" "Cancel-Code: REJECT_NOT_INSTALLED\r\n", cookie); msn_message_set_bin_data(cancel, text, strlen(text)); g_free(text); msn_switchboard_send_msg(swboard, cancel, TRUE); msn_message_unref(cancel); } } else if (!strcmp(command, "CANCEL")) { const gchar *code = g_hash_table_lookup(body, "Cancel-Code"); purple_debug_info("msn", "MSMSGS invitation cancelled: %s.\n", code ? code : "no reason given"); } else { /* * Some other already established invitation session. * Can be retrieved by Invitation-Cookie. */ } g_hash_table_destroy(body); }