static void got_emoticon(MsnSlpCall *slpcall, const guchar *data, gsize size) { PurpleConversation *conv; PurpleConnection *gc; const char *who; gc = slpcall->slplink->session->account->gc; who = slpcall->slplink->remote_user; if ((conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY, who, gc->account))) { /* FIXME: it would be better if we wrote the data as we received it instead of all at once, calling write multiple times and close once at the very end */ purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size); purple_conv_custom_smiley_close(conv, slpcall->data_info); } pecan_debug ("got smiley: %s", slpcall->data_info); }
/** @todo add extensive tests for this */ static void parse_impl (PecanNode *base_conn, gchar *buf, gsize bytes_read) { PecanCmdServer *cmd_conn; gchar *cur, *end, *old_rx_buf; gint cur_len; pecan_log ("begin"); pecan_debug ("conn=%p,name=%s", base_conn, base_conn->name); cmd_conn = CMD_PECAN_NODE (base_conn); buf[bytes_read] = '\0'; cmd_conn->rx_buf = g_realloc (cmd_conn->rx_buf, bytes_read + cmd_conn->rx_len + 1); memcpy (cmd_conn->rx_buf + cmd_conn->rx_len, buf, bytes_read + 1); cmd_conn->rx_len += bytes_read; end = old_rx_buf = cmd_conn->rx_buf; cmd_conn->rx_buf = NULL; do { cur = end; if (cmd_conn->payload_len) { if (cmd_conn->payload_len > cmd_conn->rx_len) /* The payload is still not complete. */ break; cur_len = cmd_conn->payload_len; end += cur_len; } else { end = strstr(cur, "\r\n"); if (end == NULL) /* The command is still not complete. */ break; *end = '\0'; end += 2; cur_len = end - cur; } cmd_conn->rx_len -= cur_len; if (cmd_conn->cmdproc) { if (cmd_conn->payload_len) { msn_cmdproc_process_payload (cmd_conn->cmdproc, cur, cur_len); cmd_conn->payload_len = 0; } else { msn_cmdproc_process_cmd_text (cmd_conn->cmdproc, cur); cmd_conn->payload_len = cmd_conn->cmdproc->last_cmd->payload_len; } } } while (cmd_conn->rx_len > 0); if (cmd_conn->rx_len > 0) cmd_conn->rx_buf = g_memdup (cur, cmd_conn->rx_len); else cmd_conn->rx_buf = NULL; g_free (old_rx_buf); pecan_log ("end"); }
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); } } }