static void group_error_helper(MsnSession *session, const char *msg, const gchar *group_guid, int error) { PurpleAccount *account; PurpleConnection *gc; char *reason = NULL; char *title = NULL; account = session->account; gc = purple_account_get_connection(account); if (error == 224) { const char *group_name; group_name = pecan_contactlist_find_group_name(session->contactlist, group_guid); reason = pecan_strdup_printf(_("%s is not a valid group."), group_name); } else { reason = g_strdup(_("Unknown error.")); } title = pecan_strdup_printf(_("%s on %s (%s)"), msg, purple_account_get_username(account), purple_account_get_protocol_name(account)); purple_notify_error(gc, NULL, title, reason); g_free(title); g_free(reason); }
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 adc_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error) { MsnSession *session; PurpleAccount *account; PurpleConnection *gc; const char *list, *passport; const char *reason; char *msg = NULL; char **params; session = cmdproc->session; account = session->account; gc = purple_account_get_connection(account); params = g_strsplit(trans->params, " ", 0); list = params[0]; passport = params[1]; if (!strcmp(list, "FL")) msg = pecan_strdup_printf(_("Unable to add user on %s (%s)"), purple_account_get_username(account), purple_account_get_protocol_name(account)); else if (!strcmp(list, "BL")) msg = pecan_strdup_printf(_("Unable to block user on %s (%s)"), purple_account_get_username(account), purple_account_get_protocol_name(account)); else if (!strcmp(list, "AL")) msg = pecan_strdup_printf(_("Unable to permit user on %s (%s)"), purple_account_get_username(account), purple_account_get_protocol_name(account)); reason = pecan_error_to_string (error); if (msg != NULL) { purple_notify_error(gc, NULL, msg, reason); g_free(msg); } if (!strcmp(list, "FL")) { PurpleBuddy *buddy; buddy = purple_find_buddy(account, passport); if (buddy != NULL) purple_blist_remove_buddy(buddy); } g_strfreev(params); }
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); }
gchar * msn_object_to_string(const MsnObject *obj) { gchar *str; const gchar *sha1c; g_return_val_if_fail(obj != NULL, NULL); sha1c = msn_object_get_sha1c(obj); str = pecan_strdup_printf("<msnobj Creator=\"%s\" Size=\"%d\" Type=\"%d\" " "Location=\"%s\" Friendly=\"%s\" SHA1D=\"%s\"" "%s%s%s/>", msn_object_get_creator(obj), msn_object_get_size(obj), msn_object_get_type(obj), msn_object_get_location(obj), msn_object_get_friendly(obj), msn_object_get_sha1d(obj), sha1c ? " SHA1C=\"" : "", sha1c ? sha1c : "", sha1c ? "\"" : ""); return str; }
void send_bye(MsnSlpCall *slpcall, const char *type) { MsnSlpLink *slplink; MsnSlpMessage *slpmsg; char *header; slplink = slpcall->slplink; g_return_if_fail(slplink != NULL); header = pecan_strdup_printf("BYE MSNMSGR:%s MSNSLP/1.0", slplink->local_user); slpmsg = msn_slpmsg_sip_new(slpcall, 0, header, "A0D624A6-6C0C-4283-A9E0-BC97B4B46D32", type, "\r\n"); g_free(header); #ifdef PECAN_DEBUG_SLP slpmsg->info = "SLP BYE"; slpmsg->text_body = TRUE; #endif msn_slplink_queue_slpmsg(slplink, slpmsg); }
void msn_xfer_cancel(PurpleXfer *xfer) { MsnSlpCall *slpcall; char *content; g_return_if_fail(xfer != NULL); g_return_if_fail(xfer->data != NULL); slpcall = xfer->data; if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) { if (slpcall->started) { msn_slp_call_close(slpcall); } else { content = pecan_strdup_printf("SessionID: %lu\r\n\r\n", slpcall->session_id); send_decline(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody", content); g_free(content); msn_slplink_unleash(slpcall->slplink); msn_slp_call_destroy(slpcall); } } }
MsnSlpMessage * msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq, const char *header, const char *branch, const char *content_type, const char *content) { MsnSlpLink *slplink; MsnSlpMessage *slpmsg; gchar *body; gsize body_len; gsize content_len; g_return_val_if_fail(slpcall != NULL, NULL); g_return_val_if_fail(header != NULL, NULL); slplink = slpcall->slplink; /* Let's remember that "content" should end with a 0x00 */ content_len = (content != NULL) ? strlen(content) + 1 : 0; body = pecan_strdup_printf( "%s\r\n" "To: <msnmsgr:%s>\r\n" "From: <msnmsgr:%s>\r\n" "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n" "CSeq: %d\r\n" "Call-ID: {%s}\r\n" "Max-Forwards: 0\r\n" "Content-Type: %s\r\n" "Content-Length: %" G_GSIZE_FORMAT "\r\n" "\r\n", header, slplink->remote_user, slplink->local_user, branch, cseq, slpcall->id, content_type, content_len); body_len = strlen(body); if (content_len > 0) { body_len += content_len; body = g_realloc(body, body_len); g_strlcat(body, content, body_len); } slpmsg = msn_slpmsg_new(slplink); msn_slpmsg_set_body(slpmsg, (gpointer) body, body_len); slpmsg->sip = TRUE; slpmsg->slpcall = slpcall; g_free(body); return slpmsg; }
static void msn_xfer_init(PurpleXfer *xfer) { MsnSlpCall *slpcall; /* MsnSlpLink *slplink; */ char *content; pecan_info ("xfer_init"); slpcall = xfer->data; /* Send Ok */ content = pecan_strdup_printf("SessionID: %lu\r\n\r\n", slpcall->session_id); send_ok(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody", content); g_free(content); msn_slplink_unleash(slpcall->slplink); }
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 url_cmd (MsnCmdProc *cmdproc, MsnCommand *cmd) { MsnSession *session; PurpleConnection *connection; const gchar *rru; const gchar *url; gchar creds[64]; glong tmp_timestamp; session = cmdproc->session; connection = purple_account_get_connection (session->account); rru = cmd->params[1]; url = cmd->params[2]; session->passport_info.mail_url_timestamp = time (NULL); tmp_timestamp = session->passport_info.mail_url_timestamp - session->passport_info.sl; { PurpleCipher *cipher; PurpleCipherContext *context; guchar digest[16]; gchar *buf; buf = pecan_strdup_printf ("%s%ld%s", session->passport_info.mspauth ? session->passport_info.mspauth : "BOGUS", tmp_timestamp, purple_connection_get_password (connection)); cipher = purple_ciphers_find_cipher ("md5"); context = purple_cipher_context_new (cipher, NULL); purple_cipher_context_append (context, (const guchar *) buf, strlen (buf)); purple_cipher_context_digest (context, sizeof (digest), digest, NULL); purple_cipher_context_destroy (context); g_free (buf); memset (creds, 0, sizeof (creds)); { gchar buf2[3]; gint i; for (i = 0; i < 16; i++) { g_snprintf (buf2, sizeof (buf2), "%02x", digest[i]); strcat (creds, buf2); } } } g_free (session->passport_info.mail_url); session->passport_info.mail_url = g_strdup_printf ("%s&auth=%s&creds=%s&sl=%ld&username=%s&mode=ttl&sid=%s&id=2&rru=%ssvc_mail&js=yes", url, session->passport_info.mspauth, creds, tmp_timestamp, msn_session_get_username (session), session->passport_info.sid, rru); /* The user wants to check his email */ if (cmd->trans && cmd->trans->data) { purple_notify_uri (connection, session->passport_info.mail_url); return; } if (purple_account_get_check_mail (session->account)) { static gboolean is_initial = TRUE; if (!is_initial) return; if (session->inbox_unread_count > 0) { const gchar *passport; const gchar *main_url; passport = msn_session_get_username (session); main_url = session->passport_info.mail_url; purple_notify_emails (connection, session->inbox_unread_count, FALSE, NULL, NULL, &passport, &main_url, NULL, NULL); } is_initial = FALSE; } }
void login_connect_cb(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond) { MsnNexus *nexus; MsnSession *session; char *username, *password; char *request_str, *head, *tail; char *buffer = NULL; guint32 ctint; nexus = data; g_return_if_fail(nexus != NULL); session = nexus->session; g_return_if_fail(session != NULL); msn_session_set_login_step(session, PECAN_LOGIN_STEP_GET_COOKIE); username = g_strdup(purple_url_encode(msn_session_get_username(session))); password = g_strdup(purple_url_encode(msn_session_get_password(session))); ctint = strtoul((char *)g_hash_table_lookup(nexus->challenge_data, "ct"), NULL, 10) + 200; head = pecan_strdup_printf( "GET %s HTTP/1.1\r\n" "Authorization: Passport1.4 OrgVerb=GET,OrgURL=%s,sign-in=%s", nexus->login_path, (char *)g_hash_table_lookup(nexus->challenge_data, "ru"), username); tail = pecan_strdup_printf( "lc=%s,id=%s,tw=%s,fs=%s,ru=%s,ct=%" G_GUINT32_FORMAT ",kpp=%s,kv=%s,ver=%s,tpf=%s\r\n" "User-Agent: MSMSGS\r\n" "Host: %s\r\n" "Connection: Keep-Alive\r\n" "Cache-Control: no-cache\r\n", nexus_challenge_data_lookup(nexus->challenge_data, "lc"), nexus_challenge_data_lookup(nexus->challenge_data, "id"), nexus_challenge_data_lookup(nexus->challenge_data, "tw"), nexus_challenge_data_lookup(nexus->challenge_data, "fs"), nexus_challenge_data_lookup(nexus->challenge_data, "ru"), ctint, nexus_challenge_data_lookup(nexus->challenge_data, "kpp"), nexus_challenge_data_lookup(nexus->challenge_data, "kv"), nexus_challenge_data_lookup(nexus->challenge_data, "ver"), nexus_challenge_data_lookup(nexus->challenge_data, "tpf"), nexus->login_host); buffer = pecan_strdup_printf("%s,pwd=XXXXXXXX,%s\r\n", head, tail); request_str = pecan_strdup_printf("%s,pwd=%s,%s\r\n", head, password, tail); pecan_log ("sending: [%s]", buffer); g_free(buffer); g_free(head); g_free(tail); g_free(username); g_free(password); nexus->write_buf = request_str; nexus->written_len = 0; nexus->read_len = 0; nexus->written_cb = nexus_login_written_cb; nexus->input_handler = purple_input_add(gsc->fd, PURPLE_INPUT_WRITE, nexus_write_cb, nexus); nexus_write_cb(nexus, gsc->fd, PURPLE_INPUT_WRITE); return; }
static void got_ok(MsnSlpCall *slpcall, const char *type, const char *content) { g_return_if_fail(slpcall != NULL); g_return_if_fail(type != NULL); pecan_log ("type=%s", type); if (!strcmp(type, "application/x-msnmsgr-sessionreqbody")) { #ifdef MSN_DIRECTCONN if (slpcall->slplink->session->use_directconn && slpcall->type == MSN_SLPCALL_DC) { /* First let's try a DirectConnection. */ MsnSlpLink *slplink; MsnSlpMessage *slpmsg; char *header; gchar *new_content; char *branch; slplink = slpcall->slplink; branch = msn_rand_guid(); new_content = pecan_strdup_printf( "Bridges: TRUDPv1 TCPv1\r\n" "NetID: 0\r\n" "Conn-Type: Direct-Connect\r\n" "UPnPNat: false\r\n" "ICF: false\r\n" ); header = pecan_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0", slplink->remote_user); slpmsg = msn_slpmsg_sip_new(slpcall, 0, header, branch, "application/x-msnmsgr-transreqbody", new_content); #ifdef PECAN_DEBUG_SLP slpmsg->info = "SLP INVITE"; slpmsg->text_body = TRUE; #endif msn_slplink_send_slpmsg(slplink, slpmsg); g_free(header); g_free(new_content); g_free(branch); } else { msn_slp_call_session_init(slpcall); } #else msn_slp_call_session_init(slpcall); #endif /* MSN_DIRECTCONN */ } else if (!strcmp(type, "application/x-msnmsgr-transreqbody")) { /* Do we get this? */ pecan_info ("OK with transreqbody"); } #ifdef MSN_DIRECTCONN else if (!strcmp(type, "application/x-msnmsgr-transrespbody")) { char *ip_addrs; char *temp; char *nonce; int port; { char *listening; listening = get_token(content, "Listening: ", "\r\n"); if (strcmp (listening, "false") == 0) { /** @todo I'm not sure if this is OK. */ msn_slp_call_session_init(slpcall); g_free (listening); return; } g_free (listening); } nonce = get_token(content, "Nonce: {", "}\r\n"); ip_addrs = get_token(content, "IPv4Internal-Addrs: ", "\r\n"); temp = get_token(content, "IPv4Internal-Port: ", "\r\n"); if (temp != NULL) port = atoi(temp); else port = -1; g_free(temp); if (ip_addrs == NULL) return; if (port > 0) got_transresp(slpcall, nonce, ip_addrs, port); g_free(nonce); g_free(ip_addrs); } #endif /* MSN_DIRECTCONN */ }
static void got_invite(MsnSlpCall *slpcall, const char *branch, const char *type, const char *content) { MsnSlpLink *slplink; slplink = slpcall->slplink; pecan_log ("type=%s", type); if (!strcmp(type, "application/x-msnmsgr-sessionreqbody")) { char *euf_guid, *context; char *temp; euf_guid = get_token(content, "EUF-GUID: {", "}\r\n"); temp = get_token(content, "SessionID: ", "\r\n"); if (temp != NULL) slpcall->session_id = atoi(temp); g_free(temp); temp = get_token(content, "AppID: ", "\r\n"); if (temp != NULL) slpcall->app_id = atoi(temp); g_free(temp); context = get_token(content, "Context: ", "\r\n"); if (context != NULL) got_sessionreq(slpcall, branch, euf_guid, context); g_free(context); g_free(euf_guid); } else if (!strcmp(type, "application/x-msnmsgr-transreqbody")) { /* A direct connection? */ const gchar *listening; gchar *new_content, *nonce; if (FALSE) { #if 0 MsnDirectConn *directconn; /* const char *ip_addr; */ char *ip_port; int port; /* ip_addr = purple_prefs_get_string("/purple/ft/public_ip"); */ ip_port = "5190"; listening = "true"; nonce = msn_rand_guid(); directconn = msn_directconn_new(slplink); /* msn_directconn_parse_nonce(directconn, nonce); */ directconn->nonce = g_strdup(nonce); msn_directconn_listen(directconn); port = directconn->port; new_content = pecan_strdup_printf( "Bridge: TCPv1\r\n" "Listening: %s\r\n" "Nonce: {%s}\r\n" "Ipv4Internal-Addrs: 192.168.0.82\r\n" "Ipv4Internal-Port: %d\r\n" "\r\n", listening, nonce, port); #endif } else { listening = "false"; nonce = g_strdup("00000000-0000-0000-0000-000000000000"); new_content = pecan_strdup_printf( "Bridge: TCPv1\r\n" "Listening: %s\r\n" "Nonce: {%s}\r\n" "\r\n", listening, nonce); } send_ok(slpcall, branch, "application/x-msnmsgr-transrespbody", new_content); g_free(new_content); g_free(nonce); } #ifdef MSN_DIRECTCONN else if (!strcmp(type, "application/x-msnmsgr-transrespbody")) { char *ip_addrs; char *temp; char *nonce; int port; nonce = get_token(content, "Nonce: {", "}\r\n"); ip_addrs = get_token(content, "IPv4Internal-Addrs: ", "\r\n"); temp = get_token(content, "IPv4Internal-Port: ", "\r\n"); if (temp != NULL) port = atoi(temp); else port = -1; g_free(temp); if (ip_addrs == NULL) return; if (port > 0) got_transresp(slpcall, nonce, ip_addrs, port); g_free(nonce); g_free(ip_addrs); } #endif /* MSN_DIRECTCONN */ }
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); } } }