static void close_cb (PecanNode *conn, MsnNotification *notification) { char *tmp; { const char *reason = NULL; if (conn->error) { reason = conn->error->message; pecan_error ("connection error: (NS):reason=[%s]", reason); tmp = pecan_strdup_printf (_("Error on notification server:\n%s"), reason); g_clear_error (&conn->error); } else { pecan_error ("connection error: (NS)"); tmp = pecan_strdup_printf (_("Error on notification server:\nUnknown")); } } pecan_node_close (PECAN_NODE (notification->conn)); notification->closed = TRUE; msn_session_set_error (notification->session, MSN_ERROR_SERVCONN, tmp); g_free (tmp); }
static void xfr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { char *host; int port; if (strcmp(cmd->params[1], "SB") && strcmp(cmd->params[1], "NS")) { /* Maybe we can have a generic bad command error. */ pecan_error ("bad XFR command: params=[%s]", cmd->params[1]); return; } msn_parse_socket(cmd->params[2], &host, &port); if (!strcmp(cmd->params[1], "SB")) { pecan_error ("this shouldn't be handled here"); } else if (!strcmp(cmd->params[1], "NS")) { MsnSession *session; session = cmdproc->session; msn_session_set_login_step(session, PECAN_LOGIN_STEP_TRANSFER); msn_notification_connect(session->notification, host, port); } g_free(host); }
static void rea_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; const char *who; const char *alias; session = cmdproc->session; who = cmd->params[2]; alias = purple_url_decode(cmd->params[3]); if (strcmp(who, purple_account_get_username (session->account)) == 0) { /* This is for us. */ PurpleConnection *gc; gc = session->account->gc; purple_connection_set_display_name(gc, alias); } else { /* This is for a buddy. */ PecanContact *user; user = pecan_contactlist_find_contact(session->contactlist, who); if (user) { pecan_contact_set_store_name(user, alias); } else { pecan_error ("unknown user: who=[%s]", who); return; } } }
MsnObject * msn_object_new_from_string(const gchar *str) { MsnObject *obj; gchar *tag, *c; g_return_val_if_fail(str != NULL, NULL); if (strncmp(str, "<msnobj ", 8)) return NULL; obj = msn_object_new(); GET_STRING_TAG(creator, "Creator"); GET_INT_TAG(size, "Size"); GET_INT_TAG(type, "Type"); GET_STRING_TAG(location, "Location"); GET_STRING_TAG(friendly, "Friendly"); GET_STRING_TAG(sha1d, "SHA1D"); GET_STRING_TAG(sha1c, "SHA1C"); /* If we are missing any of the required elements then discard the object */ /* SHA1C is not always sent anymore */ if (obj->creator == NULL || obj->size == 0 || obj->type == 0 || obj->location == NULL || obj->friendly == NULL || obj->sha1d == NULL /*|| obj->sha1c == NULL*/) { pecan_error ("discarding: str=[%s]", str); msn_object_destroy(obj); obj = NULL; } return obj; }
static void error_handler (MsnCmdProc *cmdproc, MsnTransaction *trans, gint error) { MsnNotification *notification; gchar *reason; notification = cmdproc->data; g_return_if_fail (notification); reason = pecan_error_to_string (error); pecan_error ("connection error: (NS):reason=[%s]", reason); switch (error) { case 913: case 208: /* non-fatal */ break; default: { char *tmp; tmp = pecan_strdup_printf (_("Error on notification server:\n%s"), reason); msn_session_set_error (notification->session, MSN_ERROR_SERVCONN, tmp); g_free (tmp); } } g_free (reason); }
void msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { MsnSession *session; MsnSlpLink *slplink; session = cmdproc->session; slplink = msn_session_get_slplink(session, msg->remote_user); if (slplink->swboard == NULL) { /* We will need this in order to change its flags. */ slplink->swboard = (MsnSwitchBoard *)cmdproc->data; /* If swboard is NULL, something has probably gone wrong earlier on * I didn't want to do this, but MSN 7 is somehow causing us to crash * here, I couldn't reproduce it to debug more, and people are * reporting bugs. Hopefully this doesn't cause more crashes. Stu. */ if (slplink->swboard != NULL) slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink); else pecan_error ("msn_p2p_msg, swboard is NULL, ouch!"); } msn_slplink_process_msg(slplink, msg); }
static void email_msg(MsnCmdProc *cmdproc, MsnMessage *msg) { MsnSession *session; PurpleConnection *gc; GHashTable *table; char *from, *subject, *tmp; session = cmdproc->session; gc = session->account->gc; if (!purple_account_get_check_mail (session->account)) return; if (strcmp(msg->remote_user, "Hotmail")) { pecan_warning ("unofficial message"); return; } if (!session->passport_info.mail_url) { pecan_error ("no url"); return; } table = msn_message_get_hashtable_from_body(msg); from = subject = NULL; tmp = g_hash_table_lookup(table, "From"); if (tmp != NULL) from = purple_mime_decode_field(tmp); tmp = g_hash_table_lookup(table, "Subject"); if (tmp != NULL) subject = purple_mime_decode_field(tmp); /** @todo go to the extact email */ purple_notify_email(gc, (subject != NULL ? subject : ""), (from != NULL ? from : ""), msn_session_get_username (session), session->passport_info.mail_url, NULL, NULL); g_free(from); g_free(subject); g_hash_table_destroy(table); }
static void debug_msg_to_file(MsnMessage *msg, gboolean send) { char *tmp; char *dir; char *pload; FILE *tf; int c; gsize pload_size; dir = send ? "send" : "recv"; c = send ? m_sc++ : m_rc++; tmp = pecan_strdup_printf("%s/msntest/%s/%03d", g_get_home_dir(), dir, c); tf = g_fopen(tmp, "wb"); if (tf == NULL) { pecan_error ("could not open debug file"); return; } pload = msn_message_gen_payload(msg, &pload_size); fwrite(pload, 1, pload_size, tf); fclose(tf); g_free(tmp); }
static void nln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; PurpleAccount *account; PurpleConnection *gc; PecanContact *user; #if defined(PECAN_CVR) MsnObject *msnobj; #endif /* defined(PECAN_CVR) */ unsigned long clientid; const char *state, *passport; gchar *friendly; session = cmdproc->session; account = session->account; gc = purple_account_get_connection(account); state = cmd->params[0]; passport = cmd->params[1]; friendly = pecan_url_decode(cmd->params[2]); user = pecan_contactlist_find_contact(session->contactlist, passport); if (!user) { pecan_error ("unknown user: passport=[%s]", passport); return; } pecan_contact_set_friendly_name(user, friendly); #if defined(PECAN_CVR) if (session->use_userdisplay) { if (cmd->param_count == 5) { gchar *tmp; tmp = pecan_url_decode(cmd->params[4]); msnobj = msn_object_new_from_string(tmp); pecan_contact_set_object(user, msnobj); g_free (tmp); } else { pecan_contact_set_object(user, NULL); } } #endif /* defined(PECAN_CVR) */ clientid = strtoul (cmd->params[3], NULL, 10); user->mobile = (clientid & MSN_CLIENT_CAP_MSNMOBILE); pecan_contact_set_state(user, state); pecan_contact_update(user); /* store the friendly name on the server. */ if (!session->server_alias) msn_cmdproc_send (cmdproc, "SBP", "%s %s %s", pecan_contact_get_guid (user), "MFN", cmd->params[2]); g_free (friendly); }
void msn_slplink_process_msg(MsnSlpLink *slplink, MsnMessage *msg) { MsnSlpMessage *slpmsg; const char *data; gsize offset; gsize len; #ifdef PECAN_DEBUG_SLP msn_slpmsg_show(msg); #endif #ifdef PECAN_DEBUG_SLP_FILES debug_msg_to_file(msg, FALSE); #endif if (msg->msnslp_header.total_size < msg->msnslp_header.length) { pecan_error ("This can't be good"); g_return_if_reached(); } slpmsg = NULL; data = msn_message_get_bin_data(msg, &len); /* OVERHEAD! if (msg->msnslp_header.length < msg->msnslp_header.total_size) */ offset = msg->msnslp_header.offset; if (offset == 0) { slpmsg = msn_slpmsg_new(slplink); slpmsg->id = msg->msnslp_header.id; slpmsg->session_id = msg->msnslp_header.session_id; slpmsg->size = msg->msnslp_header.total_size; slpmsg->flags = msg->msnslp_header.flags; if (slpmsg->session_id) { if (slpmsg->slpcall == NULL) slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, slpmsg->session_id); if (slpmsg->slpcall != NULL) { if (slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { PurpleXfer *xfer; xfer = slpmsg->slpcall->xfer; if (xfer != NULL) { purple_xfer_start(slpmsg->slpcall->xfer, 0, NULL, 0); slpmsg->fp = ((PurpleXfer *)slpmsg->slpcall->xfer)->dest_fp; xfer->dest_fp = NULL; /* Disable double fclose() */ } } } } if (!slpmsg->fp && slpmsg->size) { slpmsg->buffer = g_try_malloc(slpmsg->size); if (slpmsg->buffer == NULL) { pecan_error ("failed to allocate buffer for slpmsg"); return; } } } else { slpmsg = msn_slplink_message_find(slplink, msg->msnslp_header.session_id, msg->msnslp_header.id); } if (slpmsg == NULL) { /* Probably the transfer was canceled */ pecan_error ("couldn't find slpmsg"); return; } if (slpmsg->fp) { /* fseek(slpmsg->fp, offset, SEEK_SET); */ len = fwrite(data, 1, len, slpmsg->fp); } else if (slpmsg->size) { if ((offset + len) > slpmsg->size) { pecan_error ("oversized slpmsg"); g_return_if_reached(); } else memcpy(slpmsg->buffer + offset, data, len); } if ((slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) && (slpmsg->slpcall != NULL)) { slpmsg->slpcall->progress = TRUE; if (slpmsg->slpcall->progress_cb != NULL) { slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size, len, offset); } } #if 0 if (slpmsg->buffer == NULL) return; #endif if (msg->msnslp_header.offset + msg->msnslp_header.length >= msg->msnslp_header.total_size) { /* All the pieces of the slpmsg have been received */ MsnSlpCall *slpcall = NULL; slpcall = msn_slp_process_msg(slplink, slpmsg); #ifdef MSN_DIRECTCONN if (slpmsg->flags == 0x100) { MsnDirectConn *directconn; directconn = slplink->directconn; directconn->ack_recv = TRUE; if (!directconn->ack_sent) { pecan_warning ("bad ACK"); msn_directconn_send_handshake(directconn); } } else if (slpmsg->flags == 0x0 || slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { /* Release all the messages and send the ACK */ msn_slplink_send_ack(slplink, msg); msn_slplink_unleash(slplink); } #else if (slpmsg->flags == 0x0 || slpmsg->flags == 0x20 || slpmsg->flags == 0x1000030) { /* Release all the messages and send the ACK */ msn_slplink_send_ack(slplink, msg); msn_slplink_unleash(slplink); } #endif /* MSN_DIRECTCONN */ msn_slpmsg_destroy(slpmsg); if (slpcall != NULL && slpcall->wasted) msn_slp_call_destroy(slpcall); } }
MsnSlpCall * msn_slp_sip_recv(MsnSlpLink *slplink, const char *body) { MsnSlpCall *slpcall; if (body == NULL) { pecan_warning ("received bogus message"); return NULL; } if (!strncmp(body, "INVITE", strlen("INVITE"))) { char *branch; char *content; char *content_type; slpcall = msn_slp_call_new(slplink); /* From: <msnmsgr:[email protected]> */ #if 0 slpcall->remote_user = get_token(body, "From: <msnmsgr:", ">\r\n"); #endif branch = get_token(body, ";branch={", "}"); slpcall->id = get_token(body, "Call-ID: {", "}"); #if 0 long content_len = -1; temp = get_token(body, "Content-Length: ", "\r\n"); if (temp != NULL) content_len = atoi(temp); g_free(temp); #endif content_type = get_token(body, "Content-Type: ", "\r\n"); content = get_token(body, "\r\n\r\n", NULL); got_invite(slpcall, branch, content_type, content); g_free(branch); g_free(content_type); g_free(content); } else if (!strncmp(body, "MSNSLP/1.0 ", strlen("MSNSLP/1.0 "))) { char *content; char *content_type; /* Make sure this is "OK" */ const char *status = body + strlen("MSNSLP/1.0 "); char *call_id; call_id = get_token(body, "Call-ID: {", "}"); slpcall = msn_slplink_find_slp_call(slplink, call_id); g_free(call_id); g_return_val_if_fail(slpcall != NULL, NULL); if (strncmp(status, "200 OK", 6)) { /* It's not valid. Kill this off. */ char temp[32]; const char *c; /* Eww */ if ((c = strchr(status, '\r')) || (c = strchr(status, '\n')) || (c = strchr(status, '\0'))) { size_t offset = c - status; if (offset >= sizeof(temp)) offset = sizeof(temp) - 1; strncpy(temp, status, offset); temp[offset] = '\0'; } pecan_error ("received non-OK result: %s", temp); slpcall->wasted = TRUE; /* msn_slp_call_destroy(slpcall); */ return slpcall; } content_type = get_token(body, "Content-Type: ", "\r\n"); content = get_token(body, "\r\n\r\n", NULL); got_ok(slpcall, content_type, content); g_free(content_type); g_free(content); } else if (!strncmp(body, "BYE", strlen("BYE"))) { char *call_id; call_id = get_token(body, "Call-ID: {", "}"); slpcall = msn_slplink_find_slp_call(slplink, call_id); g_free(call_id); if (slpcall != NULL) slpcall->wasted = TRUE; /* msn_slp_call_destroy(slpcall); */ } else slpcall = NULL; return slpcall; }
static void got_sessionreq(MsnSlpCall *slpcall, const char *branch, const char *euf_guid, const char *context) { pecan_debug ("euf_guid=[%s]", euf_guid); if (!strcmp(euf_guid, "A4268EEC-FEC5-49E5-95C3-F126696BDBF6")) { /* Emoticon or UserDisplay */ char *content; gsize len; MsnSlpSession *slpsession; MsnSlpLink *slplink; MsnSlpMessage *slpmsg; MsnObject *obj; char *msnobj_data; PecanBuffer *image; int type; /* Send Ok */ content = pecan_strdup_printf("SessionID: %lu\r\n\r\n", slpcall->session_id); send_ok(slpcall, branch, "application/x-msnmsgr-sessionreqbody", content); g_free(content); slplink = slpcall->slplink; msnobj_data = (char *)purple_base64_decode(context, &len); obj = msn_object_new_from_string(msnobj_data); type = msn_object_get_type(obj); g_free(msnobj_data); if (type == MSN_OBJECT_USERTILE) { /* image is owned by a local object, not obj */ image = msn_object_get_image(obj); } #if PURPLE_VERSION_CHECK(2,5,0) else if (type == MSN_OBJECT_EMOTICON) { PurpleStoredImage *img; char *path; path = g_build_filename(purple_smileys_get_storing_dir(), msn_object_get_location(obj), NULL); img = purple_imgstore_new_from_file(path); image = pecan_buffer_new_memdup ((const gpointer) purple_imgstore_get_data (img), purple_imgstore_get_size (img)); purple_imgstore_unref(img); g_free(path); } #endif /* PURPLE_VERSION_CHECK(2,5,0) */ else { pecan_error ("Wrong object?"); msn_object_destroy(obj); g_return_if_reached(); } if (!image) { pecan_error ("Wrong object"); msn_object_destroy (obj); g_return_if_reached (); } msn_object_destroy(obj); { gchar *tmp; tmp = msn_object_to_string (obj); pecan_info ("object requested: %s", tmp); g_free (tmp); } slpsession = msn_slplink_find_slp_session(slplink, slpcall->session_id); /* DATA PREP */ slpmsg = msn_slpmsg_new(slplink); slpmsg->slpcall = slpcall; slpmsg->slpsession = slpsession; slpmsg->session_id = slpsession->id; msn_slpmsg_set_body(slpmsg, NULL, 4); #ifdef PECAN_DEBUG_SLP slpmsg->info = "SLP DATA PREP"; #endif msn_slplink_queue_slpmsg(slplink, slpmsg); /* DATA */ slpmsg = msn_slpmsg_new(slplink); slpmsg->slpcall = slpcall; slpmsg->slpsession = slpsession; slpmsg->flags = 0x20; #ifdef PECAN_DEBUG_SLP slpmsg->info = "SLP DATA"; #endif msn_slpmsg_set_image (slpmsg, image); msn_slplink_queue_slpmsg(slplink, slpmsg); } else if (!strcmp(euf_guid, "5D3E02AB-6190-11D3-BBBB-00C04F795683")) { /* File Transfer */ PurpleAccount *account; PurpleXfer *xfer; char *bin; gsize bin_len; guint32 file_size; char *file_name; gunichar2 *uni_name; account = slpcall->slplink->session->account; slpcall->cb = msn_xfer_completed_cb; slpcall->end_cb = msn_xfer_end_cb; slpcall->progress_cb = msn_xfer_progress_cb; slpcall->branch = g_strdup(branch); slpcall->pending = TRUE; xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, slpcall->slplink->remote_user); if (xfer) { bin = (char *)purple_base64_decode(context, &bin_len); file_size = GUINT32_FROM_LE(*(gsize *)(bin + 8)); uni_name = (gunichar2 *)(bin + 20); while(*uni_name != 0 && ((char *)uni_name - (bin + 20)) < MAX_FILE_NAME_LEN) { *uni_name = GUINT16_FROM_LE(*uni_name); uni_name++; } file_name = g_utf16_to_utf8((const gunichar2 *)(bin + 20), -1, NULL, NULL, NULL); g_free(bin); purple_xfer_set_filename(xfer, file_name); purple_xfer_set_size(xfer, file_size); purple_xfer_set_init_fnc(xfer, msn_xfer_init); purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel); purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel); slpcall->xfer = xfer; purple_xfer_ref(slpcall->xfer); xfer->data = slpcall; purple_xfer_request(xfer); } } }