Permalink
Browse files

Skypeweb : Add support for receiving server-backed files

... and give warning about P2P files being unsupported
  • Loading branch information...
EionRobb committed Dec 31, 2015
1 parent 8c64874 commit 416fee02b3d785acd3c70f98c0733338c85330ed
Showing with 222 additions and 1 deletion.
  1. +9 −0 skypeweb/libskypeweb.h
  2. +182 −1 skypeweb/skypeweb_contacts.c
  3. +1 −0 skypeweb/skypeweb_contacts.h
  4. +30 −0 skypeweb/skypeweb_messages.c
View
@@ -173,6 +173,15 @@
#define purple_hash_append purple_cipher_context_append
#define purple_hash_digest(hash, data, len) purple_cipher_context_digest(hash, len, data, NULL)
#define purple_hash_destroy purple_cipher_context_destroy
+ #define purple_xfer_set_protocol_data(xfer, proto_data) ((xfer)->data = (proto_data))
+ #define purple_xfer_get_protocol_data(xfer) ((xfer)->data)
+static inline gboolean
+purple_xfer_write_file(PurpleXfer *xfer, const guchar *buffer, gsize size) {
+ PurpleXferUiOps *ui_ops = purple_xfer_get_ui_ops(xfer);
+ purple_xfer_set_bytes_sent(xfer, purple_xfer_get_bytes_sent(xfer) +
+ (ui_ops && ui_ops->ui_write ? ui_ops->ui_write(xfer, buffer, size) : fwrite(buffer, 1, size, xfer->dest_fp)));
+ return TRUE;
+}
#define PURPLE_CMD_FLAG_PROTOCOL_ONLY PURPLE_CMD_FLAG_PRPL_ONLY
#define PURPLE_CMD_P_PLUGIN PURPLE_CMD_P_PRPL
@@ -221,7 +221,7 @@ skypeweb_got_vm_download_info(SkypeWebAccount *sa, JsonNode *node, gpointer user
purple_xfer_set_size(xfer, fileSize);
purple_xfer_set_filename(xfer, filename);
json_object_ref(file);
- xfer->data = file;
+ purple_xfer_set_protocol_data(xfer, file);
purple_xfer_set_init_fnc(xfer, skypeweb_init_vm_download);
purple_xfer_set_cancel_recv_fnc(xfer, skypeweb_cancel_vm_download);
purple_xfer_add(xfer);
@@ -273,6 +273,187 @@ skypeweb_download_video_message(SkypeWebAccount *sa, const gchar *sid, PurpleCon
}
+static void
+skypeweb_cancel_file_download(PurpleXfer *xfer)
+{
+ SkypeWebFileTransfer *swft;
+
+ swft = purple_xfer_get_protocol_data(xfer);
+
+ json_object_unref(swft->info);
+ g_free(swft->url);
+ g_free(swft->from);
+ g_free(swft);
+
+ purple_xfer_set_protocol_data(xfer, NULL);
+}
+
+static void
+skypeweb_got_file(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
+{
+ SkypeWebFileTransfer *swft = user_data;
+ PurpleXfer *xfer = swft->xfer;
+ SkypeWebAccount *sa = swft->sa;
+
+ sa->url_datas = g_slist_remove(sa->url_datas, url_data);
+
+ if (error_message) {
+ purple_xfer_error(purple_xfer_get_type(xfer), sa->account, swft->from, error_message);
+ purple_xfer_cancel_local(xfer);
+ } else {
+ purple_xfer_write_file(xfer, (guchar *)url_text, len);
+ purple_xfer_set_bytes_sent(xfer, len);
+ purple_xfer_set_completed(xfer, TRUE);
+ }
+
+ //cleanup
+ skypeweb_cancel_file_download(xfer);
+}
+
+static void
+skypeweb_init_file_download(PurpleXfer *xfer)
+{
+ SkypeWebFileTransfer *swft;
+ const gchar *view_location;
+ gint64 content_full_length;
+ PurpleHttpURL *httpurl;
+ gchar *headers;
+
+ swft = purple_xfer_get_protocol_data(xfer);
+
+ view_location = json_object_get_string_member(swft->info, "view_location");
+ content_full_length = json_object_get_int_member(swft->info, "content_full_length");
+
+ purple_xfer_start(xfer, -1, NULL, 0);
+
+ httpurl = purple_http_url_parse(view_location);
+ headers = g_strdup_printf("GET /%s HTTP/1.0\r\n"
+ "Connection: close\r\n"
+ "Cookie: skypetoken_asm=%s\r\n"
+ "Host: %s\r\n"
+ "\r\n\r\n",
+ purple_http_url_get_path(httpurl),
+ swft->sa->skype_token,
+ purple_http_url_get_host(httpurl));
+
+ skypeweb_fetch_url_request(swft->sa, view_location, TRUE, NULL, FALSE, headers, FALSE, content_full_length, skypeweb_got_file, swft);
+
+ g_free(headers);
+ purple_http_url_free(httpurl);
+}
+
+static void
+skypeweb_got_file_info(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
+{
+ JsonObject *obj;
+ PurpleXfer *xfer;
+ SkypeWebFileTransfer *swft = user_data;
+ SkypeWebAccount *sa = swft->sa;
+ JsonParser *parser;
+ JsonNode *node;
+
+ parser = json_parser_new();
+ if (!json_parser_load_from_data(parser, url_text, len, NULL)) {
+ g_free(swft->url);
+ g_free(swft->from);
+ g_free(swft);
+ g_object_unref(parser);
+ return;
+ }
+
+ node = json_parser_get_root(parser);
+ if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) {
+ g_free(swft->url);
+ g_free(swft->from);
+ g_free(swft);
+ g_object_unref(parser);
+ return;
+ }
+ obj = json_node_get_object(node);
+
+ /*
+ {
+ "content_length": 40708,
+ "content_full_length": 40708,
+ "view_length": 40708,
+ "content_state": "ready",
+ "view_state": "ready",
+ "view_location": "uri/views/original",
+ "status_location": "uri/views/original/status",
+ "scan": {
+ "status": "passed"
+ },
+ "original_filename": "filename"
+ } */
+ purple_debug_info("skypeweb", "File info: %s\n", url_text);
+
+ if (!json_object_has_member(obj, "content_state") || !g_str_equal(json_object_get_string_member(obj, "content_state"), "ready")) {
+ skypeweb_present_uri_as_filetransfer(sa, json_object_get_string_member(obj, "status_location"), swft->from);
+ g_free(swft->url);
+ g_free(swft->from);
+ g_free(swft);
+ g_object_unref(parser);
+ return;
+ }
+
+ json_object_ref(obj);
+ swft->info = obj;
+
+ xfer = purple_xfer_new(sa->account, PURPLE_XFER_RECEIVE, swft->from);
+ purple_xfer_set_size(xfer, json_object_get_int_member(obj, "content_full_length"));
+ purple_xfer_set_filename(xfer, json_object_get_string_member(obj, "original_filename"));
+ purple_xfer_set_init_fnc(xfer, skypeweb_init_file_download);
+ purple_xfer_set_cancel_recv_fnc(xfer, skypeweb_cancel_file_download);
+
+ swft->xfer = xfer;
+ purple_xfer_set_protocol_data(xfer, swft);
+
+ purple_xfer_request(xfer);
+
+ g_object_unref(parser);
+}
+
+void
+skypeweb_present_uri_as_filetransfer(SkypeWebAccount *sa, const gchar *uri, const gchar *from)
+{
+ PurpleHttpURL *httpurl;
+ const gchar *host;
+ gchar *path;
+ SkypeWebFileTransfer *swft;
+ gchar *headers;
+
+
+ httpurl = purple_http_url_parse(uri);
+ host = purple_http_url_get_host(httpurl);
+
+ if (g_str_has_suffix(uri, "/views/original/status")) {
+ path = g_strconcat(purple_http_url_get_path(httpurl), NULL);
+ } else {
+ path = g_strconcat(purple_http_url_get_path(httpurl), "/views/original/status", NULL);
+ }
+
+ headers = g_strdup_printf("GET /%s HTTP/1.0\r\n"
+ "Connection: close\r\n"
+ "Cookie: skypetoken_asm=%s\r\n"
+ "Host: %s\r\n"
+ "\r\n\r\n",
+ path,
+ sa->skype_token,
+ host);
+
+ swft = g_new0(SkypeWebFileTransfer, 1);
+ swft->sa = sa;
+ swft->url = g_strdup(uri);
+ swft->from = g_strdup(from);
+
+ skypeweb_fetch_url_request(sa, uri, TRUE, NULL, FALSE, headers, FALSE, -1, skypeweb_got_file_info, swft);
+
+ g_free(path);
+ g_free(headers);
+ purple_http_url_free(httpurl);
+}
+
+
static void
skypeweb_got_self_details(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
{
@@ -24,6 +24,7 @@
void skypeweb_get_icon(PurpleBuddy *buddy);
void skypeweb_download_uri_to_conv(SkypeWebAccount *sa, const gchar *uri, PurpleConversation *conv);
void skypeweb_download_video_message(SkypeWebAccount *sa, const gchar *sid, PurpleConversation *conv);
+void skypeweb_present_uri_as_filetransfer(SkypeWebAccount *sa, const gchar *uri, const gchar *from);
void skypeweb_search_users(PurplePluginAction *action);
@@ -303,6 +303,13 @@ process_message_resource(SkypeWebAccount *sa, JsonObject *resource)
g_free(role);
}
+ purple_xmlnode_free(blob);
+ } else if (g_str_equal(messagetype, "RichText/UriObject")) {
+ PurpleXmlNode *blob = purple_xmlnode_from_str(content, -1);
+ const gchar *uri = purple_xmlnode_get_attrib(blob, "url_thumbnail");
+ PurpleIMConversation *imconv;
+
+ skypeweb_download_uri_to_conv(sa, uri, conv);
purple_xmlnode_free(blob);
} else {
purple_debug_warning("skypeweb", "Unhandled thread message resource messagetype '%s'\n", messagetype);
@@ -337,6 +344,7 @@ process_message_resource(SkypeWebAccount *sa, JsonObject *resource)
skypeemoteoffset = atoi(json_object_get_string_member(resource, "skypeemoteoffset"));
//TODO if (skypeeditedid && *skypeeditedid) { ... }
+ //TODO if (!content)
if (g_str_equal(messagetype, "Text")) {
gchar *temp = skypeweb_meify(content, skypeemoteoffset);
@@ -381,6 +389,18 @@ process_message_resource(SkypeWebAccount *sa, JsonObject *resource)
skypeweb_download_uri_to_conv(sa, uri, conv);
}
purple_xmlnode_free(blob);
+ } else if (g_str_equal(messagetype, "RichText/Media_GenericFile")) {
+ PurpleXmlNode *blob = purple_xmlnode_from_str(content, -1);
+ const gchar *uri = purple_xmlnode_get_attrib(blob, "uri");
+ PurpleIMConversation *imconv;
+
+ if (!skypeweb_is_user_self(sa, from)) {
+
+ skypeweb_present_uri_as_filetransfer(sa, uri, from);
+
+ from = convbuddyname;
+ }
+ purple_xmlnode_free(blob);
} else if (g_str_equal(messagetype, "Event/SkypeVideoMessage")) {
PurpleXmlNode *blob = purple_xmlnode_from_str(content, -1);
const gchar *sid = purple_xmlnode_get_attrib(blob, "sid");
@@ -453,6 +473,8 @@ process_message_resource(SkypeWebAccount *sa, JsonObject *resource)
purple_serv_got_im(sa->pc, from, message, PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_SYSTEM, composetimestamp);
}
purple_xmlnode_free(partlist);
+ } else if (g_str_equal(messagetype, "RichText/Files")) {
+ purple_serv_got_im(sa->pc, convbuddyname, _("The user sent files in an unsupported way"), PURPLE_MESSAGE_RECV | PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_ERROR, composetimestamp);
} else {
purple_debug_warning("skypeweb", "Unhandled message resource messagetype '%s'\n", messagetype);
}
@@ -1387,3 +1409,11 @@ skypeweb_chat_set_topic(PurpleConnection *pc, int id, const char *topic)
json_object_unref(obj);
}
+void
+skypeweb_get_thread_url(SkypeWebAccount *sa, const gchar *thread)
+{
+ //POST https://api.scheduler.skype.com/threads
+ //{"baseDomain":"https://join.skype.com/launch/","threadId":"%s"}
+
+ // {"Id":"MeMxigEAAAAxOTo5NDZkMjExMGQ4YmU0ZjQzODc3NjMxNDQ3ZTgxYWNmNkB0aHJlYWQuc2t5cGU","Blob":null,"JoinUrl":"https://join.skype.com/ALXsHZ2RFQnk","ThreadId":"19:946d2110d8be4f43877631447e81acf6@thread.skype"}
+}

0 comments on commit 416fee0

Please sign in to comment.