diff options
Diffstat (limited to 'skypeweb/skypeweb_contacts.c')
-rw-r--r-- | skypeweb/skypeweb_contacts.c | 3178 |
1 files changed, 1589 insertions, 1589 deletions
diff --git a/skypeweb/skypeweb_contacts.c b/skypeweb/skypeweb_contacts.c index aab23e4..ecaab9e 100644 --- a/skypeweb/skypeweb_contacts.c +++ b/skypeweb/skypeweb_contacts.c @@ -1,682 +1,682 @@ -/*
- * SkypeWeb Plugin for libpurple/Pidgin
- * Copyright (c) 2014-2020 Eion Robb
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "skypeweb_contacts.h"
-#include "skypeweb_connection.h"
-#include "skypeweb_messages.h"
-#include "skypeweb_util.h"
-
-#include "http.h"
-#include "xfer.h"
-#include "image-store.h"
-
-static void purple_conversation_write_img_message(
- PurpleConversation *conv, const char* who, const gchar *msg,
- PurpleMessageFlags flags, time_t ts) {
- PurpleMessage *pmsg;
-
- if (flags & PURPLE_MESSAGE_SEND) {
- pmsg = purple_message_new_outgoing(who, msg, flags);
- purple_message_set_time(pmsg, ts);
- } else {
- pmsg = purple_message_new_incoming(who, msg, flags, ts);
- }
-
- purple_conversation_write_message(conv, pmsg);
- purple_message_destroy(pmsg);
-}
-
-// Check that the conversation hasn't been closed
-static gboolean
-purple_conversation_is_valid(PurpleConversation *conv)
-{
- GList *convs = purple_conversations_get_all();
-
- return (g_list_find(convs, conv) != NULL);
-}
-
-
-typedef struct {
- PurpleXfer *xfer;
- JsonObject *info;
- gchar *from;
- gchar *url;
- gchar *id;
- SkypeWebAccount *sa;
-} SkypeWebFileTransfer;
-
-static guint active_icon_downloads = 0;
-
-static void
-skypeweb_get_icon_cb(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data)
-{
- PurpleHttpRequest *request = purple_http_conn_get_request(http_conn);
- PurpleBuddy *buddy = user_data;
- const gchar *url = purple_http_request_get_url(request);
- const gchar *data;
- gsize len;
-
- active_icon_downloads--;
-
- if (!buddy || !purple_http_response_is_successful(response)) {
- return;
- }
-
- data = purple_http_response_get_data(response, &len);
-
- if (!len || !*data) {
- return;
- }
-
- purple_buddy_icons_set_for_user(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), g_memdup(data, len), len, url);
-
-}
-
-static void
-skypeweb_get_icon_now(PurpleBuddy *buddy)
-{
- SkypeWebBuddy *sbuddy;
- SkypeWebAccount *sa;
- gchar *url;
-
- purple_debug_info("skypeweb", "getting new buddy icon for %s\n", purple_buddy_get_name(buddy));
-
- sbuddy = purple_buddy_get_protocol_data(buddy);
-
- if (!sbuddy || !sbuddy->sa || !sbuddy->sa->pc)
- return;
-
- if (sbuddy->avatar_url && sbuddy->avatar_url[0]) {
- url = g_strdup(sbuddy->avatar_url);
- } else {
- url = g_strdup_printf("https://avatar.skype.com/v1/avatars/%s/public?returnDefaultImage=false", purple_url_encode(purple_buddy_get_name(buddy)));
- }
-
- sa = sbuddy->sa;
-
- purple_http_get(sa->pc, skypeweb_get_icon_cb, buddy, url);
- g_free(url);
-
- active_icon_downloads++;
-}
-
-static gboolean
-skypeweb_get_icon_queuepop(gpointer data)
-{
- PurpleBuddy *buddy = data;
-
- // Only allow 4 simultaneous downloads
- if (active_icon_downloads > 4)
- return TRUE;
-
- skypeweb_get_icon_now(buddy);
- return FALSE;
-}
-
-void
-skypeweb_get_icon(PurpleBuddy *buddy)
-{
- if (!buddy) return;
-
- g_timeout_add(100, skypeweb_get_icon_queuepop, (gpointer)buddy);
-}
-
-typedef struct SkypeImgMsgContext_ {
- PurpleConversation *conv;
- time_t composetimestamp;
+/* + * SkypeWeb Plugin for libpurple/Pidgin + * Copyright (c) 2014-2020 Eion Robb + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "skypeweb_contacts.h" +#include "skypeweb_connection.h" +#include "skypeweb_messages.h" +#include "skypeweb_util.h" + +#include "http.h" +#include "xfer.h" +#include "image-store.h" + +static void purple_conversation_write_img_message( + PurpleConversation *conv, const char* who, const gchar *msg, + PurpleMessageFlags flags, time_t ts) { + PurpleMessage *pmsg; + + if (flags & PURPLE_MESSAGE_SEND) { + pmsg = purple_message_new_outgoing(who, msg, flags); + purple_message_set_time(pmsg, ts); + } else { + pmsg = purple_message_new_incoming(who, msg, flags, ts); + } + + purple_conversation_write_message(conv, pmsg); + purple_message_destroy(pmsg); +} + +// Check that the conversation hasn't been closed +static gboolean +purple_conversation_is_valid(PurpleConversation *conv) +{ + GList *convs = purple_conversations_get_all(); + + return (g_list_find(convs, conv) != NULL); +} + + +typedef struct { + PurpleXfer *xfer; + JsonObject *info; + gchar *from; + gchar *url; + gchar *id; + SkypeWebAccount *sa; +} SkypeWebFileTransfer; + +static guint active_icon_downloads = 0; + +static void +skypeweb_get_icon_cb(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data) +{ + PurpleHttpRequest *request = purple_http_conn_get_request(http_conn); + PurpleBuddy *buddy = user_data; + const gchar *url = purple_http_request_get_url(request); + const gchar *data; + gsize len; + + active_icon_downloads--; + + if (!buddy || !purple_http_response_is_successful(response)) { + return; + } + + data = purple_http_response_get_data(response, &len); + + if (!len || !*data) { + return; + } + + purple_buddy_icons_set_for_user(purple_buddy_get_account(buddy), purple_buddy_get_name(buddy), g_memdup(data, len), len, url); + +} + +static void +skypeweb_get_icon_now(PurpleBuddy *buddy) +{ + SkypeWebBuddy *sbuddy; + SkypeWebAccount *sa; + gchar *url; + + purple_debug_info("skypeweb", "getting new buddy icon for %s\n", purple_buddy_get_name(buddy)); + + sbuddy = purple_buddy_get_protocol_data(buddy); + + if (!sbuddy || !sbuddy->sa || !sbuddy->sa->pc) + return; + + if (sbuddy->avatar_url && sbuddy->avatar_url[0]) { + url = g_strdup(sbuddy->avatar_url); + } else { + url = g_strdup_printf("https://avatar.skype.com/v1/avatars/%s/public?returnDefaultImage=false", purple_url_encode(purple_buddy_get_name(buddy))); + } + + sa = sbuddy->sa; + + purple_http_get(sa->pc, skypeweb_get_icon_cb, buddy, url); + g_free(url); + + active_icon_downloads++; +} + +static gboolean +skypeweb_get_icon_queuepop(gpointer data) +{ + PurpleBuddy *buddy = data; + + // Only allow 4 simultaneous downloads + if (active_icon_downloads > 4) + return TRUE; + + skypeweb_get_icon_now(buddy); + return FALSE; +} + +void +skypeweb_get_icon(PurpleBuddy *buddy) +{ + if (!buddy) return; + + g_timeout_add(100, skypeweb_get_icon_queuepop, (gpointer)buddy); +} + +typedef struct SkypeImgMsgContext_ { + PurpleConversation *conv; + time_t composetimestamp; gchar* from; -} SkypeImgMsgContext;
-
-static void
-skypeweb_got_imagemessage(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data)
-{
- gint icon_id;
- gchar *msg_tmp;
- const gchar *url_text;
- gsize len;
- PurpleImage *image;
-
- SkypeImgMsgContext *ctx = user_data;
- PurpleConversation *conv = ctx->conv;
- time_t ts = ctx->composetimestamp;
- gchar* ctx_from = ctx->from;
- ctx->from = NULL;
- g_free(ctx);
-
- // Conversation could have been closed before we retrieved the image
- if (!purple_conversation_is_valid(conv)) {
- return;
- }
-
- url_text = purple_http_response_get_data(response, &len);
-
- if (!url_text || !len || url_text[0] == '{' || url_text[0] == '<')
- return;
-
- if (!purple_http_response_is_successful(response))
- return;
-
- image = purple_image_new_from_data(g_memdup(url_text, len), len);
- icon_id = purple_image_store_add(image);
- msg_tmp = g_strdup_printf("<img id='%d'>", icon_id);
- purple_conversation_write_img_message(conv, ctx_from, msg_tmp, PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_IMAGES, ts);
- g_free(msg_tmp);
- g_free(ctx_from);
-}
-
-static const char*
-skypeweb_uri_type_name(SkypeWebURIType uri_type) {
- switch (uri_type) {
- case SKYPEWEB_URI_TYPE_IMAGE:
- return "image";
- case SKYPEWEB_URI_TYPE_VIDEO:
- return "video";
- default:
- return "(unknown)";
- }
-}
-void
-skypeweb_download_uri_to_conv(SkypeWebAccount *sa, const gchar *uri, SkypeWebURIType uri_type, PurpleConversation *conv, time_t ts, const gchar* from)
-{
- gchar *url, *text;
- PurpleHttpRequest *request;
-
- switch (uri_type) {
- case SKYPEWEB_URI_TYPE_IMAGE:
- url = purple_strreplace(uri, "imgt1", "imgpsh_fullsize");
- break;
- case SKYPEWEB_URI_TYPE_VIDEO:
- url = purple_strreplace(uri, "thumbnail", "video");
- break;
- default:
- url = g_strdup(uri);
- break;
- }
- if (purple_strequal(purple_core_get_ui(), "BitlBee")) {
- // Bitlbee doesn't support images, so just plop a url to the image instead
-
- if (PURPLE_IS_IM_CONVERSATION(conv)) {
- purple_serv_got_im(sa->pc, from, url, PURPLE_MESSAGE_RECV, ts);
- } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) {
- gchar *chatname = purple_conversation_get_data(conv, "chatname");
- purple_serv_got_chat_in(sa->pc, g_str_hash(chatname), from, PURPLE_MESSAGE_RECV, url, ts);
- }
- g_free(url);
-
- return;
- }
-
- request = purple_http_request_new(uri);
- purple_http_request_set_keepalive_pool(request, sa->keepalive_pool);
- purple_http_request_header_set_printf(request, "Cookie", "skypetoken_asm=%s", sa->skype_token);
- purple_http_request_header_set(request, "Accept", "image/*");
- SkypeImgMsgContext *ctx = g_new(SkypeImgMsgContext, 1);
- ctx->composetimestamp = ts;
- ctx->conv = conv;
- ctx->from = g_strdup(from);
- purple_http_request(sa->pc, request, skypeweb_got_imagemessage, ctx);
- purple_http_request_unref(request);
-
- text = g_strdup_printf("<a href=\"%s\">Click here to view full %s</a>", url, skypeweb_uri_type_name(uri_type));
- purple_conversation_write_img_message(conv, from, text, 0, ts);
-
- g_free(url);
- g_free(text);
-}
-
-void
-skypeweb_download_moji_to_conv(SkypeWebAccount *sa, const gchar *text, const gchar *url_thumbnail, PurpleConversation *conv, time_t ts, const gchar* from)
-{
- gchar *cdn_url_thumbnail;
- PurpleHttpURL *httpurl;
- PurpleHttpRequest *request;
-
- httpurl = purple_http_url_parse(url_thumbnail);
-
- cdn_url_thumbnail = g_strdup_printf("https://%s/%s", SKYPEWEB_STATIC_CDN_HOST, purple_http_url_get_path(httpurl));
-
- request = purple_http_request_new(cdn_url_thumbnail);
- purple_http_request_set_keepalive_pool(request, sa->keepalive_pool);
- purple_http_request_header_set_printf(request, "Cookie", "vdms-skype-token=%s", sa->vdms_token);
- purple_http_request_header_set(request, "Accept", "image/*");
- SkypeImgMsgContext *ctx = g_new(SkypeImgMsgContext, 1);
- ctx->composetimestamp = ts;
- ctx->conv = conv;
- ctx->from = g_strdup(from);
- purple_http_request(sa->pc, request, skypeweb_got_imagemessage, ctx);
- purple_http_request_unref(request);
-
- purple_conversation_write_img_message(conv, from, text, 0, ts);
-
- g_free(cdn_url_thumbnail);
- purple_http_url_free(httpurl);
-}
-
-static void
-skypeweb_got_vm_file(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data)
-{
- PurpleXfer *xfer = user_data;
- const gchar *data;
- gsize len;
-
- data = purple_http_response_get_data(response, &len);
- purple_xfer_write(xfer, (guchar *)data, len);
-}
-
-static void
-skypeweb_init_vm_download(PurpleXfer *xfer)
-{
- SkypeWebAccount *sa;
- JsonObject *file = purple_xfer_get_protocol_data(xfer);
- gint64 fileSize;
- const gchar *url;
- PurpleHttpRequest *request;
-
- fileSize = json_object_get_int_member(file, "fileSize");
- url = json_object_get_string_member(file, "url");
-
- purple_xfer_set_completed(xfer, FALSE);
- sa = purple_connection_get_protocol_data(purple_account_get_connection(purple_xfer_get_account(xfer)));
-
- request = purple_http_request_new(url);
- purple_http_request_set_keepalive_pool(request, sa->keepalive_pool);
- purple_http_request_set_max_len(request, fileSize);
- purple_http_request(sa->pc, request, skypeweb_got_vm_file, xfer);
- purple_http_request_unref(request);
-
- json_object_unref(file);
-}
-
-static void
-skypeweb_cancel_vm_download(PurpleXfer *xfer)
-{
- JsonObject *file = purple_xfer_get_protocol_data(xfer);
- json_object_unref(file);
-}
-
-static void
-skypeweb_got_vm_download_info(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- PurpleConversation *conv = user_data;
- PurpleXfer *xfer;
- JsonObject *obj, *file;
- JsonArray *files;
- gint64 fileSize;
- const gchar *url, *assetId, *status;
- gchar *filename;
-
- if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT)
- return;
- obj = json_node_get_object(node);
-
- files = json_object_get_array_member(obj, "files");
- file = json_array_get_object_element(files, 0);
- if (file != NULL) {
- status = json_object_get_string_member(file, "status");
- if (status && g_str_equal(status, "ok")) {
- assetId = json_object_get_string_member(obj, "assetId");
- fileSize = json_object_get_int_member(file, "fileSize");
- url = json_object_get_string_member(file, "url");
- (void) url;
-
- filename = g_strconcat(assetId, ".mp4", NULL);
-
- xfer = purple_xfer_new(sa->account, PURPLE_XFER_TYPE_RECEIVE, purple_conversation_get_name(conv));
- purple_xfer_set_size(xfer, fileSize);
- purple_xfer_set_filename(xfer, filename);
- json_object_ref(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);
-
- g_free(filename);
- } else if (status && g_str_equal(status, "running")) {
- //skypeweb_download_video_message(sa, sid??????, conv);
- }
- }
-}
-
-static void
-skypeweb_got_vm_info(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- PurpleConversation *conv = user_data;
- JsonObject *obj, *response, *media_stream;
- const gchar *filename;
-
- if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT)
- return;
- obj = json_node_get_object(node);
-
- response = json_object_get_object_member(obj, "response");
- media_stream = json_object_get_object_member(response, "media_stream");
- filename = json_object_get_string_member(media_stream, "filename");
-
- if (filename != NULL) {
- // Need to keep retrying this url until it comes back with status:ok
- gchar *url = g_strdup_printf("/vod/api-create?assetId=%s&profile=mp4-vm", purple_url_encode(filename));
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, "media.vm.skype.com", url, NULL, skypeweb_got_vm_download_info, conv, TRUE);
- g_free(url);
- }
-
-}
-
-void
-skypeweb_download_video_message(SkypeWebAccount *sa, const gchar *sid, PurpleConversation *conv)
-{
- gchar *url, *username_encoded;
-
- username_encoded = g_strdup(purple_url_encode(sa->username));
- url = g_strdup_printf("/users/%s/video_mails/%s", username_encoded, purple_url_encode(sid));
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_VIDEOMAIL_HOST, url, NULL, skypeweb_got_vm_info, conv, TRUE);
-
- g_free(url);
- g_free(username_encoded);
-
-}
-
-
-static void
-skypeweb_free_xfer(PurpleXfer *xfer)
-{
- SkypeWebFileTransfer *swft;
-
- swft = purple_xfer_get_protocol_data(xfer);
- g_return_if_fail(swft != NULL);
-
- if (swft->info != NULL)
- json_object_unref(swft->info);
- g_free(swft->url);
- g_free(swft->id);
- g_free(swft->from);
- g_free(swft);
-
- purple_xfer_set_protocol_data(xfer, NULL);
-}
-
-static void
-skypeweb_got_file(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data)
-{
- SkypeWebFileTransfer *swft = user_data;
- PurpleXfer *xfer = swft->xfer;
- SkypeWebAccount *sa = swft->sa;
- const gchar *data;
- gsize len;
-
-
- if (!purple_http_response_is_successful(response)) {
- purple_xfer_error(purple_xfer_get_xfer_type(xfer), sa->account, swft->from, purple_http_response_get_error(response));
- purple_xfer_cancel_local(xfer);
- } else {
- data = purple_http_response_get_data(response, &len);
- purple_xfer_write_file(xfer, (guchar *)data, len);
- purple_xfer_set_completed(xfer, TRUE);
- }
-
- //cleanup
- skypeweb_free_xfer(xfer);
- purple_xfer_end(xfer);
-}
-
-static void
-skypeweb_init_file_download(PurpleXfer *xfer)
-{
- SkypeWebAccount *sa;
- SkypeWebFileTransfer *swft;
- const gchar *view_location;
- gint64 content_full_length;
- PurpleHttpRequest *request;
-
- swft = purple_xfer_get_protocol_data(xfer);
- sa = swft->sa;
-
- 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);
-
- request = purple_http_request_new(view_location);
- purple_http_request_set_keepalive_pool(request, sa->keepalive_pool);
- purple_http_request_header_set_printf(request, "Cookie", "skypetoken_asm=%s", sa->skype_token);
- purple_http_request_header_set(request, "Accept", "*/*");
- purple_http_request_set_max_len(request, content_full_length);
- purple_http_request(sa->pc, request, skypeweb_got_file, swft);
- purple_http_request_unref(request);
-}
-
-static void
-skypeweb_got_file_info(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data)
-{
- JsonObject *obj;
- PurpleXfer *xfer;
- SkypeWebFileTransfer *swft = user_data;
- SkypeWebAccount *sa = swft->sa;
- JsonParser *parser;
- JsonNode *node;
- const gchar *data;
- gsize len;
-
- data = purple_http_response_get_data(response, &len);
-
- parser = json_parser_new();
- if (!json_parser_load_from_data(parser, data, 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", data);
-
- if (!json_object_has_member(obj, "content_state") || !purple_strequal(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_TYPE_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_free_xfer);
-
- 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)
-{
- SkypeWebFileTransfer *swft;
- PurpleHttpRequest *request;
-
- swft = g_new0(SkypeWebFileTransfer, 1);
- swft->sa = sa;
- swft->url = g_strdup(uri);
- swft->from = g_strdup(from);
-
- request = purple_http_request_new(uri);
- if (!g_str_has_suffix(uri, "/views/original/status")) {
- purple_http_request_set_url_printf(request, "%s%s", uri, "/views/original/status");
- }
- purple_http_request_set_keepalive_pool(request, sa->keepalive_pool);
- purple_http_request_header_set_printf(request, "Cookie", "skypetoken_asm=%s", sa->skype_token);
- purple_http_request_header_set(request, "Accept", "*/*");
- purple_http_request(sa->pc, request, skypeweb_got_file_info, swft);
- purple_http_request_unref(request);
-}
-
-static void
-got_file_send_progress(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data)
-{
- SkypeWebFileTransfer *swft = user_data;
- PurpleXfer *xfer = swft->xfer;
- SkypeWebAccount *sa = swft->sa;
- JsonParser *parser;
- JsonNode *node;
- JsonObject *obj;
- const gchar *data;
- gsize len;
-
- data = purple_http_response_get_data(response, &len);
-
- //{"content_length":0,"content_full_length":0,"view_length":0,"content_state":"no content","view_state":"none","view_location":"https://nus1-api.asm.skype.com/v1/objects/0-cus-d1-61121cfae8cf601944627a66afdb77ad/views/original","status_location":"https://nus1-api.asm.skype.com/v1/objects/0-cus-d1-61121cfae8cf601944627a66afdb77ad/views/original/status"}
- parser = json_parser_new();
- if (!json_parser_load_from_data(parser, data, len, NULL)) {
- //probably bad
- return;
- }
- node = json_parser_get_root(parser);
- if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) {
- //probably bad
- return;
- }
- obj = json_node_get_object(node);
-
-
- if (json_object_has_member(obj, "status_location")) {
- g_free(swft->url);
- swft->url = g_strdup(json_object_get_string_member(obj, "status_location"));
- }
-
- if (json_object_has_member(obj, "content_state") && purple_strequal(json_object_get_string_member(obj, "content_state"), "ready")) {
- PurpleXmlNode *uriobject = purple_xmlnode_new("URIObject");
- PurpleXmlNode *title = purple_xmlnode_new_child(uriobject, "Title");
- PurpleXmlNode *description = purple_xmlnode_new_child(uriobject, "Description");
- PurpleXmlNode *anchor = purple_xmlnode_new_child(uriobject, "a");
- PurpleXmlNode *originalname = purple_xmlnode_new_child(uriobject, "OriginalName");
- PurpleXmlNode *filesize = purple_xmlnode_new_child(uriobject, "FileSize");
- gchar *message, *temp;
- //We finally did it!
- // May the pesants rejoyce
- purple_xfer_set_completed(xfer, TRUE);
-
- // Don't forget to let the other end know about it
-
- purple_xmlnode_set_attrib(uriobject, "type", "File.1");
- temp = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), NULL);
- purple_xmlnode_set_attrib(uriobject, "uri", temp);
- g_free(temp);
- temp = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), "/views/thumbnail", NULL);
- purple_xmlnode_set_attrib(uriobject, "url_thumbnail", temp);
- g_free(temp);
- purple_xmlnode_insert_data(title, purple_xfer_get_filename(xfer), -1);
- purple_xmlnode_insert_data(description, "Description: ", -1);
- temp = g_strconcat("https://login.skype.com/login/sso?go=webclient.xmm&docid=", purple_url_encode(swft->id), NULL);
- purple_xmlnode_set_attrib(anchor, "href", temp);
- purple_xmlnode_insert_data(anchor, temp, -1);
- g_free(temp);
- purple_xmlnode_set_attrib(originalname, "v", purple_xfer_get_filename(xfer));
- temp = g_strdup_printf("%" G_GSIZE_FORMAT, (gsize) purple_xfer_get_size(xfer));
- purple_xmlnode_set_attrib(filesize, "v", temp);
- g_free(temp);
-
- temp = purple_xmlnode_to_str(uriobject, NULL);
+} SkypeImgMsgContext; + +static void +skypeweb_got_imagemessage(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data) +{ + gint icon_id; + gchar *msg_tmp; + const gchar *url_text; + gsize len; + PurpleImage *image; + + SkypeImgMsgContext *ctx = user_data; + PurpleConversation *conv = ctx->conv; + time_t ts = ctx->composetimestamp; + gchar* ctx_from = ctx->from; + ctx->from = NULL; + g_free(ctx); + + // Conversation could have been closed before we retrieved the image + if (!purple_conversation_is_valid(conv)) { + return; + } + + url_text = purple_http_response_get_data(response, &len); + + if (!url_text || !len || url_text[0] == '{' || url_text[0] == '<') + return; + + if (!purple_http_response_is_successful(response)) + return; + + image = purple_image_new_from_data(g_memdup(url_text, len), len); + icon_id = purple_image_store_add(image); + msg_tmp = g_strdup_printf("<img id='%d'>", icon_id); + purple_conversation_write_img_message(conv, ctx_from, msg_tmp, PURPLE_MESSAGE_NO_LOG | PURPLE_MESSAGE_IMAGES, ts); + g_free(msg_tmp); + g_free(ctx_from); +} + +static const char* +skypeweb_uri_type_name(SkypeWebURIType uri_type) { + switch (uri_type) { + case SKYPEWEB_URI_TYPE_IMAGE: + return "image"; + case SKYPEWEB_URI_TYPE_VIDEO: + return "video"; + default: + return "(unknown)"; + } +} +void +skypeweb_download_uri_to_conv(SkypeWebAccount *sa, const gchar *uri, SkypeWebURIType uri_type, PurpleConversation *conv, time_t ts, const gchar* from) +{ + gchar *url, *text; + PurpleHttpRequest *request; + + switch (uri_type) { + case SKYPEWEB_URI_TYPE_IMAGE: + url = purple_strreplace(uri, "imgt1", "imgpsh_fullsize"); + break; + case SKYPEWEB_URI_TYPE_VIDEO: + url = purple_strreplace(uri, "thumbnail", "video"); + break; + default: + url = g_strdup(uri); + break; + } + if (purple_strequal(purple_core_get_ui(), "BitlBee")) { + // Bitlbee doesn't support images, so just plop a url to the image instead + + if (PURPLE_IS_IM_CONVERSATION(conv)) { + purple_serv_got_im(sa->pc, from, url, PURPLE_MESSAGE_RECV, ts); + } else if (PURPLE_IS_CHAT_CONVERSATION(conv)) { + gchar *chatname = purple_conversation_get_data(conv, "chatname"); + purple_serv_got_chat_in(sa->pc, g_str_hash(chatname), from, PURPLE_MESSAGE_RECV, url, ts); + } + g_free(url); + + return; + } + + request = purple_http_request_new(uri); + purple_http_request_set_keepalive_pool(request, sa->keepalive_pool); + purple_http_request_header_set_printf(request, "Cookie", "skypetoken_asm=%s", sa->skype_token); + purple_http_request_header_set(request, "Accept", "image/*"); + SkypeImgMsgContext *ctx = g_new(SkypeImgMsgContext, 1); + ctx->composetimestamp = ts; + ctx->conv = conv; + ctx->from = g_strdup(from); + purple_http_request(sa->pc, request, skypeweb_got_imagemessage, ctx); + purple_http_request_unref(request); + + text = g_strdup_printf("<a href=\"%s\">Click here to view full %s</a>", url, skypeweb_uri_type_name(uri_type)); + purple_conversation_write_img_message(conv, from, text, 0, ts); + + g_free(url); + g_free(text); +} + +void +skypeweb_download_moji_to_conv(SkypeWebAccount *sa, const gchar *text, const gchar *url_thumbnail, PurpleConversation *conv, time_t ts, const gchar* from) +{ + gchar *cdn_url_thumbnail; + PurpleHttpURL *httpurl; + PurpleHttpRequest *request; + + httpurl = purple_http_url_parse(url_thumbnail); + + cdn_url_thumbnail = g_strdup_printf("https://%s/%s", SKYPEWEB_STATIC_CDN_HOST, purple_http_url_get_path(httpurl)); + + request = purple_http_request_new(cdn_url_thumbnail); + purple_http_request_set_keepalive_pool(request, sa->keepalive_pool); + purple_http_request_header_set_printf(request, "Cookie", "vdms-skype-token=%s", sa->vdms_token); + purple_http_request_header_set(request, "Accept", "image/*"); + SkypeImgMsgContext *ctx = g_new(SkypeImgMsgContext, 1); + ctx->composetimestamp = ts; + ctx->conv = conv; + ctx->from = g_strdup(from); + purple_http_request(sa->pc, request, skypeweb_got_imagemessage, ctx); + purple_http_request_unref(request); + + purple_conversation_write_img_message(conv, from, text, 0, ts); + + g_free(cdn_url_thumbnail); + purple_http_url_free(httpurl); +} + +static void +skypeweb_got_vm_file(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data) +{ + PurpleXfer *xfer = user_data; + const gchar *data; + gsize len; + + data = purple_http_response_get_data(response, &len); + purple_xfer_write(xfer, (guchar *)data, len); +} + +static void +skypeweb_init_vm_download(PurpleXfer *xfer) +{ + SkypeWebAccount *sa; + JsonObject *file = purple_xfer_get_protocol_data(xfer); + gint64 fileSize; + const gchar *url; + PurpleHttpRequest *request; + + fileSize = json_object_get_int_member(file, "fileSize"); + url = json_object_get_string_member(file, "url"); + + purple_xfer_set_completed(xfer, FALSE); + sa = purple_connection_get_protocol_data(purple_account_get_connection(purple_xfer_get_account(xfer))); + + request = purple_http_request_new(url); + purple_http_request_set_keepalive_pool(request, sa->keepalive_pool); + purple_http_request_set_max_len(request, fileSize); + purple_http_request(sa->pc, request, skypeweb_got_vm_file, xfer); + purple_http_request_unref(request); + + json_object_unref(file); +} + +static void +skypeweb_cancel_vm_download(PurpleXfer *xfer) +{ + JsonObject *file = purple_xfer_get_protocol_data(xfer); + json_object_unref(file); +} + +static void +skypeweb_got_vm_download_info(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + PurpleConversation *conv = user_data; + PurpleXfer *xfer; + JsonObject *obj, *file; + JsonArray *files; + gint64 fileSize; + const gchar *url, *assetId, *status; + gchar *filename; + + if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) + return; + obj = json_node_get_object(node); + + files = json_object_get_array_member(obj, "files"); + file = json_array_get_object_element(files, 0); + if (file != NULL) { + status = json_object_get_string_member(file, "status"); + if (status && g_str_equal(status, "ok")) { + assetId = json_object_get_string_member(obj, "assetId"); + fileSize = json_object_get_int_member(file, "fileSize"); + url = json_object_get_string_member(file, "url"); + (void) url; + + filename = g_strconcat(assetId, ".mp4", NULL); + + xfer = purple_xfer_new(sa->account, PURPLE_XFER_TYPE_RECEIVE, purple_conversation_get_name(conv)); + purple_xfer_set_size(xfer, fileSize); + purple_xfer_set_filename(xfer, filename); + json_object_ref(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); + + g_free(filename); + } else if (status && g_str_equal(status, "running")) { + //skypeweb_download_video_message(sa, sid??????, conv); + } + } +} + +static void +skypeweb_got_vm_info(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + PurpleConversation *conv = user_data; + JsonObject *obj, *response, *media_stream; + const gchar *filename; + + if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) + return; + obj = json_node_get_object(node); + + response = json_object_get_object_member(obj, "response"); + media_stream = json_object_get_object_member(response, "media_stream"); + filename = json_object_get_string_member(media_stream, "filename"); + + if (filename != NULL) { + // Need to keep retrying this url until it comes back with status:ok + gchar *url = g_strdup_printf("/vod/api-create?assetId=%s&profile=mp4-vm", purple_url_encode(filename)); + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, "media.vm.skype.com", url, NULL, skypeweb_got_vm_download_info, conv, TRUE); + g_free(url); + } + +} + +void +skypeweb_download_video_message(SkypeWebAccount *sa, const gchar *sid, PurpleConversation *conv) +{ + gchar *url, *username_encoded; + + username_encoded = g_strdup(purple_url_encode(sa->username)); + url = g_strdup_printf("/users/%s/video_mails/%s", username_encoded, purple_url_encode(sid)); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_VIDEOMAIL_HOST, url, NULL, skypeweb_got_vm_info, conv, TRUE); + + g_free(url); + g_free(username_encoded); + +} + + +static void +skypeweb_free_xfer(PurpleXfer *xfer) +{ + SkypeWebFileTransfer *swft; + + swft = purple_xfer_get_protocol_data(xfer); + g_return_if_fail(swft != NULL); + + if (swft->info != NULL) + json_object_unref(swft->info); + g_free(swft->url); + g_free(swft->id); + g_free(swft->from); + g_free(swft); + + purple_xfer_set_protocol_data(xfer, NULL); +} + +static void +skypeweb_got_file(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data) +{ + SkypeWebFileTransfer *swft = user_data; + PurpleXfer *xfer = swft->xfer; + SkypeWebAccount *sa = swft->sa; + const gchar *data; + gsize len; + + + if (!purple_http_response_is_successful(response)) { + purple_xfer_error(purple_xfer_get_xfer_type(xfer), sa->account, swft->from, purple_http_response_get_error(response)); + purple_xfer_cancel_local(xfer); + } else { + data = purple_http_response_get_data(response, &len); + purple_xfer_write_file(xfer, (guchar *)data, len); + purple_xfer_set_completed(xfer, TRUE); + } + + //cleanup + skypeweb_free_xfer(xfer); + purple_xfer_end(xfer); +} + +static void +skypeweb_init_file_download(PurpleXfer *xfer) +{ + SkypeWebAccount *sa; + SkypeWebFileTransfer *swft; + const gchar *view_location; + gint64 content_full_length; + PurpleHttpRequest *request; + + swft = purple_xfer_get_protocol_data(xfer); + sa = swft->sa; + + 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); + + request = purple_http_request_new(view_location); + purple_http_request_set_keepalive_pool(request, sa->keepalive_pool); + purple_http_request_header_set_printf(request, "Cookie", "skypetoken_asm=%s", sa->skype_token); + purple_http_request_header_set(request, "Accept", "*/*"); + purple_http_request_set_max_len(request, content_full_length); + purple_http_request(sa->pc, request, skypeweb_got_file, swft); + purple_http_request_unref(request); +} + +static void +skypeweb_got_file_info(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data) +{ + JsonObject *obj; + PurpleXfer *xfer; + SkypeWebFileTransfer *swft = user_data; + SkypeWebAccount *sa = swft->sa; + JsonParser *parser; + JsonNode *node; + const gchar *data; + gsize len; + + data = purple_http_response_get_data(response, &len); + + parser = json_parser_new(); + if (!json_parser_load_from_data(parser, data, 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", data); + + if (!json_object_has_member(obj, "content_state") || !purple_strequal(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_TYPE_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_free_xfer); + + 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) +{ + SkypeWebFileTransfer *swft; + PurpleHttpRequest *request; + + swft = g_new0(SkypeWebFileTransfer, 1); + swft->sa = sa; + swft->url = g_strdup(uri); + swft->from = g_strdup(from); + + request = purple_http_request_new(uri); + if (!g_str_has_suffix(uri, "/views/original/status")) { + purple_http_request_set_url_printf(request, "%s%s", uri, "/views/original/status"); + } + purple_http_request_set_keepalive_pool(request, sa->keepalive_pool); + purple_http_request_header_set_printf(request, "Cookie", "skypetoken_asm=%s", sa->skype_token); + purple_http_request_header_set(request, "Accept", "*/*"); + purple_http_request(sa->pc, request, skypeweb_got_file_info, swft); + purple_http_request_unref(request); +} + +static void +got_file_send_progress(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data) +{ + SkypeWebFileTransfer *swft = user_data; + PurpleXfer *xfer = swft->xfer; + SkypeWebAccount *sa = swft->sa; + JsonParser *parser; + JsonNode *node; + JsonObject *obj; + const gchar *data; + gsize len; + + data = purple_http_response_get_data(response, &len); + + //{"content_length":0,"content_full_length":0,"view_length":0,"content_state":"no content","view_state":"none","view_location":"https://nus1-api.asm.skype.com/v1/objects/0-cus-d1-61121cfae8cf601944627a66afdb77ad/views/original","status_location":"https://nus1-api.asm.skype.com/v1/objects/0-cus-d1-61121cfae8cf601944627a66afdb77ad/views/original/status"} + parser = json_parser_new(); + if (!json_parser_load_from_data(parser, data, len, NULL)) { + //probably bad + return; + } + node = json_parser_get_root(parser); + if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) { + //probably bad + return; + } + obj = json_node_get_object(node); + + + if (json_object_has_member(obj, "status_location")) { + g_free(swft->url); + swft->url = g_strdup(json_object_get_string_member(obj, "status_location")); + } + + if (json_object_has_member(obj, "content_state") && purple_strequal(json_object_get_string_member(obj, "content_state"), "ready")) { + PurpleXmlNode *uriobject = purple_xmlnode_new("URIObject"); + PurpleXmlNode *title = purple_xmlnode_new_child(uriobject, "Title"); + PurpleXmlNode *description = purple_xmlnode_new_child(uriobject, "Description"); + PurpleXmlNode *anchor = purple_xmlnode_new_child(uriobject, "a"); + PurpleXmlNode *originalname = purple_xmlnode_new_child(uriobject, "OriginalName"); + PurpleXmlNode *filesize = purple_xmlnode_new_child(uriobject, "FileSize"); + gchar *message, *temp; + //We finally did it! + // May the pesants rejoyce + purple_xfer_set_completed(xfer, TRUE); + + // Don't forget to let the other end know about it + + purple_xmlnode_set_attrib(uriobject, "type", "File.1"); + temp = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), NULL); + purple_xmlnode_set_attrib(uriobject, "uri", temp); + g_free(temp); + temp = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), "/views/thumbnail", NULL); + purple_xmlnode_set_attrib(uriobject, "url_thumbnail", temp); + g_free(temp); + purple_xmlnode_insert_data(title, purple_xfer_get_filename(xfer), -1); + purple_xmlnode_insert_data(description, "Description: ", -1); + temp = g_strconcat("https://login.skype.com/login/sso?go=webclient.xmm&docid=", purple_url_encode(swft->id), NULL); + purple_xmlnode_set_attrib(anchor, "href", temp); + purple_xmlnode_insert_data(anchor, temp, -1); + g_free(temp); + purple_xmlnode_set_attrib(originalname, "v", purple_xfer_get_filename(xfer)); + temp = g_strdup_printf("%" G_GSIZE_FORMAT, (gsize) purple_xfer_get_size(xfer)); + purple_xmlnode_set_attrib(filesize, "v", temp); + g_free(temp); + + temp = purple_xmlnode_to_str(uriobject, NULL); message = purple_strreplace(temp, "'", "\""); g_free(temp); -#if PURPLE_VERSION_CHECK(3, 0, 0)
- PurpleMessage *msg = purple_message_new_outgoing(swft->from, message, PURPLE_MESSAGE_SEND);
- skypeweb_send_im(sa->pc, msg);
- purple_message_destroy(msg);
-#else
- skypeweb_send_im(sa->pc, swft->from, message, PURPLE_MESSAGE_SEND);
-#endif
- g_free(message);
-
- skypeweb_free_xfer(xfer);
- purple_xfer_unref(xfer);
-
- purple_xmlnode_free(uriobject);
- g_object_unref(parser);
- return;
- }
-
-
- g_object_unref(parser);
-
- // probably good
-}
-
-static gboolean
-poll_file_send_progress(gpointer user_data)
-{
- SkypeWebFileTransfer *swft = user_data;
- SkypeWebAccount *sa = swft->sa;
- PurpleHttpRequest *request;
-
- request = purple_http_request_new(swft->url);
- purple_http_request_set_keepalive_pool(request, sa->keepalive_pool);
- purple_http_request_header_set_printf(request, "Cookie", "skypetoken_asm=%s", sa->skype_token);
- purple_http_request_header_set(request, "Accept", "*/*");
- purple_http_request(sa->pc, request, got_file_send_progress, swft);
- purple_http_request_unref(request);
-
- return FALSE;
-}
+#if PURPLE_VERSION_CHECK(3, 0, 0) + PurpleMessage *msg = purple_message_new_outgoing(swft->from, message, PURPLE_MESSAGE_SEND); + skypeweb_send_im(sa->pc, msg); + purple_message_destroy(msg); +#else + skypeweb_send_im(sa->pc, swft->from, message, PURPLE_MESSAGE_SEND); +#endif + g_free(message); + + skypeweb_free_xfer(xfer); + purple_xfer_unref(xfer); + + purple_xmlnode_free(uriobject); + g_object_unref(parser); + return; + } + + + g_object_unref(parser); + + // probably good +} + +static gboolean +poll_file_send_progress(gpointer user_data) +{ + SkypeWebFileTransfer *swft = user_data; + SkypeWebAccount *sa = swft->sa; + PurpleHttpRequest *request; + + request = purple_http_request_new(swft->url); + purple_http_request_set_keepalive_pool(request, sa->keepalive_pool); + purple_http_request_header_set_printf(request, "Cookie", "skypetoken_asm=%s", sa->skype_token); + purple_http_request_header_set(request, "Accept", "*/*"); + purple_http_request(sa->pc, request, got_file_send_progress, swft); + purple_http_request_unref(request); + + return FALSE; +} static void skypeweb_xfer_send_contents_reader(PurpleHttpConnection *con, gchar *buf, size_t offset, size_t len, gpointer user_data, PurpleHttpContentReaderCb cb) { SkypeWebFileTransfer *swft = user_data; PurpleXfer *xfer = swft->xfer; - gsize read;
+ gsize read; - purple_debug_info("skypeweb", "Asked %" G_GSIZE_FORMAT " bytes from offset %" G_GSIZE_FORMAT "\n", len, offset);
+ purple_debug_info("skypeweb", "Asked %" G_GSIZE_FORMAT " bytes from offset %" G_GSIZE_FORMAT "\n", len, offset); purple_xfer_set_bytes_sent(xfer, offset); read = purple_xfer_read_file(xfer, (guchar *)buf, len); - purple_debug_info("skypeweb", "Read %" G_GSIZE_FORMAT " bytes\n", read);
+ purple_debug_info("skypeweb", "Read %" G_GSIZE_FORMAT " bytes\n", read); cb(con, TRUE, read != len, read); } @@ -690,7 +690,7 @@ skypeweb_xfer_send_done(PurpleHttpConnection *conn, PurpleHttpResponse *resp, gp int code = purple_http_response_get_code(resp); purple_debug_info("skypeweb", "Finished [%d]: %s\n", code, error); purple_debug_info("skypeweb", "Server message: %s\n", data); - g_timeout_add_seconds(1, poll_file_send_progress, user_data);
+ g_timeout_add_seconds(1, poll_file_send_progress, user_data); } static void @@ -725,925 +725,925 @@ skypeweb_xfer_send_begin(gpointer user_data) purple_http_request_unref(request); } -static void
-skypeweb_got_object_for_file(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data)
-{
- SkypeWebFileTransfer *swft = user_data;
- PurpleXfer *xfer = swft->xfer;
- JsonParser *parser;
- JsonNode *node;
- JsonObject *obj;
- const gchar *data;
- gsize len;
-
- data = purple_http_response_get_data(response, &len);
-
- //Get back {"id": "0-cus-d3-deadbeefdeadbeef012345678"}
- parser = json_parser_new();
- if (!json_parser_load_from_data(parser, data, len, NULL)) {
- 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->from);
- g_free(swft);
- g_object_unref(parser);
- purple_xfer_cancel_local(xfer);
- return;
- }
- obj = json_node_get_object(node);
-
- if (!json_object_has_member(obj, "id")) {
- g_free(swft->from);
- g_free(swft);
- g_object_unref(parser);
- purple_xfer_cancel_local(xfer);
- return;
- }
-
- swft->id = g_strdup(json_object_get_string_member(obj, "id"));
- swft->url = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), "/views/original/status", NULL);
-
- g_object_unref(parser);
-
- //Send the data
-
- //can't use fetch_url_request because it doesn't handle binary data
+static void +skypeweb_got_object_for_file(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data) +{ + SkypeWebFileTransfer *swft = user_data; + PurpleXfer *xfer = swft->xfer; + JsonParser *parser; + JsonNode *node; + JsonObject *obj; + const gchar *data; + gsize len; + + data = purple_http_response_get_data(response, &len); + + //Get back {"id": "0-cus-d3-deadbeefdeadbeef012345678"} + parser = json_parser_new(); + if (!json_parser_load_from_data(parser, data, len, NULL)) { + 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->from); + g_free(swft); + g_object_unref(parser); + purple_xfer_cancel_local(xfer); + return; + } + obj = json_node_get_object(node); + + if (!json_object_has_member(obj, "id")) { + g_free(swft->from); + g_free(swft); + g_object_unref(parser); + purple_xfer_cancel_local(xfer); + return; + } + + swft->id = g_strdup(json_object_get_string_member(obj, "id")); + swft->url = g_strconcat("https://" SKYPEWEB_XFER_HOST "/v1/objects/", purple_url_encode(swft->id), "/views/original/status", NULL); + + g_object_unref(parser); + + //Send the data + + //can't use fetch_url_request because it doesn't handle binary data skypeweb_xfer_send_begin(user_data); -
-}
-
-static void
-skypeweb_xfer_send_init(PurpleXfer *xfer)
-{
- PurpleConnection *pc = purple_account_get_connection(purple_xfer_get_account(xfer));
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
- gchar *basename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
- gchar *id, *post;
- SkypeWebFileTransfer *swft = purple_xfer_get_protocol_data(xfer);
- JsonObject *obj = json_object_new();
- JsonObject *permissions = json_object_new();
- JsonArray *userpermissions = json_array_new();
- PurpleHttpRequest *request;
-
- purple_xfer_set_filename(xfer, basename);
- purple_xfer_ref(xfer);
-
- json_object_set_string_member(obj, "type", "sharing/file");
- json_object_set_string_member(obj, "filename", basename);
-
- id = g_strconcat(skypeweb_user_url_prefix(swft->from), swft->from, NULL);
- json_array_add_string_element(userpermissions, "read");
- json_object_set_array_member(permissions, id, userpermissions);
- json_object_set_object_member(obj, "permissions", permissions);
-
- post = skypeweb_jsonobj_to_string(obj);
- //POST to api.asm.skype.com /v1/objects
- //{"type":"sharing/file","permissions":{"8:eionrobb":["read"]},"filename":"GiantLobsterMoose.txt"}
-
- request = purple_http_request_new("https://" SKYPEWEB_XFER_HOST "/v1/objects");
- purple_http_request_set_method(request, "POST");
- purple_http_request_set_keepalive_pool(request, sa->keepalive_pool);
- purple_http_request_header_set_printf(request, "Authorization", "skype_token %s", sa->skype_token); //slightly different to normal!
- purple_http_request_header_set(request, "Content-Type", "application/json");
- purple_http_request_header_set(request, "X-Client-Version", SKYPEWEB_CLIENTINFO_VERSION);
- purple_http_request_set_contents(request, post, -1);
- purple_http_request(sa->pc, request, skypeweb_got_object_for_file, swft);
- purple_http_request_unref(request);
-
- g_free(post);
- json_object_unref(obj);
- g_free(id);
- g_free(basename);
-}
-
-PurpleXfer *
-skypeweb_new_xfer(
-#if PURPLE_VERSION_CHECK(3, 0, 0)
-PurpleProtocolXfer *prplxfer,
-#endif
-PurpleConnection *pc, const char *who)
-{
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
- PurpleXfer *xfer;
- SkypeWebFileTransfer *swft;
-
- xfer = purple_xfer_new(sa->account, PURPLE_XFER_TYPE_SEND, who);
-
- swft = g_new0(SkypeWebFileTransfer, 1);
- swft->sa = sa;
- swft->from = g_strdup(who);
- swft->xfer = xfer;
- purple_xfer_set_protocol_data(xfer, swft);
-
- purple_xfer_set_init_fnc(xfer, skypeweb_xfer_send_init);
- //purple_xfer_set_write_fnc(xfer, skypeweb_xfer_send_write);
- //purple_xfer_set_end_fnc(xfer, skypeweb_xfer_send_end);
- purple_xfer_set_request_denied_fnc(xfer, skypeweb_free_xfer);
- purple_xfer_set_cancel_send_fnc(xfer, skypeweb_free_xfer);
-
- return xfer;
-}
-
-void
-skypeweb_send_file(
-#if PURPLE_VERSION_CHECK(3, 0, 0)
-PurpleProtocolXfer *prplxfer,
-#endif
-PurpleConnection *pc, const gchar *who, const gchar *filename)
-{
- PurpleXfer *xfer = skypeweb_new_xfer(
-#if PURPLE_VERSION_CHECK(3, 0, 0)
- prplxfer,
-#endif
- pc, who);
-
- if (filename && *filename)
- purple_xfer_request_accepted(xfer, filename);
- else
- purple_xfer_request(xfer);
-}
-
-gboolean
-skypeweb_can_receive_file(
-#if PURPLE_VERSION_CHECK(3, 0, 0)
-PurpleProtocolXfer *prplxfer,
-#endif
-PurpleConnection *pc, const gchar *who)
-{
- if (!who || g_str_equal(who, purple_account_get_username(purple_connection_get_account(pc))))
- return FALSE;
-
- return TRUE;
-}
-
-
-static void
-skypeweb_got_self_details(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- JsonObject *userobj;
- const gchar *old_alias;
- const gchar *displayname = NULL;
- const gchar *username;
-
- if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT)
- return;
- userobj = json_node_get_object(node);
-
- username = json_object_get_string_member(userobj, "username");
- g_free(sa->username); sa->username = g_strdup(username);
- purple_connection_set_display_name(sa->pc, sa->username);
-
- old_alias = purple_account_get_private_alias(sa->account);
- if (!old_alias || !*old_alias) {
- if (json_object_has_member(userobj, "displayname"))
- displayname = json_object_get_string_member(userobj, "displayname");
- if (!displayname || purple_strequal(displayname, username))
- displayname = json_object_get_string_member(userobj, "firstname");
-
- if (displayname)
- purple_account_set_private_alias(sa->account, displayname);
- }
-
- if (!PURPLE_CONNECTION_IS_CONNECTED(sa->pc)) {
- skypeweb_do_all_the_things(sa);
- }
-
- skypeweb_gather_self_properties(sa);
-}
-
-
-void
-skypeweb_get_self_details(SkypeWebAccount *sa)
-{
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_CONTACTS_HOST, "/users/self/profile", NULL, skypeweb_got_self_details, NULL, TRUE);
-}
-
-
-
-
-
-
-
-
-
-void
-skypeweb_search_results_add_buddy(PurpleConnection *pc, GList *row, void *user_data)
-{
- PurpleAccount *account = purple_connection_get_account(pc);
-
- if (!purple_blist_find_buddy(account, g_list_nth_data(row, 0)))
- purple_blist_request_add_buddy(account, g_list_nth_data(row, 0), "Skype", g_list_nth_data(row, 1));
-}
-
-void
-skypeweb_received_contacts(SkypeWebAccount *sa, PurpleXmlNode *contacts)
-{
- PurpleNotifySearchResults *results;
- PurpleNotifySearchColumn *column;
-
- PurpleXmlNode *contact;
-
- results = purple_notify_searchresults_new();
- if (results == NULL) {
- return;
- }
-
- /* columns: Friend ID, Name */
- column = purple_notify_searchresults_column_new(_("Skype Name"));
- purple_notify_searchresults_column_add(results, column);
- column = purple_notify_searchresults_column_new(_("Display Name"));
- purple_notify_searchresults_column_add(results, column);
-
-
- purple_notify_searchresults_button_add(results,
- PURPLE_NOTIFY_BUTTON_ADD,
- skypeweb_search_results_add_buddy);
-
- for(contact = purple_xmlnode_get_child(contacts, "c"); contact;
- contact = purple_xmlnode_get_next_twin(contact))
- {
- GList *row = NULL;
-
- gchar *contact_id = g_strdup(purple_xmlnode_get_attrib(contact, "s"));
- gchar *contact_name = g_strdup(purple_xmlnode_get_attrib(contact, "f"));
-
- row = g_list_append(row, contact_id);
- row = g_list_append(row, contact_name);
-
- purple_notify_searchresults_row_add(results, row);
- }
-
- purple_notify_searchresults(sa->pc, _("Received contacts"), NULL, NULL, results, NULL, NULL);
-}
-
-static PurpleNotifySearchResults*
-create_search_results(JsonNode *node, gint *olength)
-{
- PurpleNotifySearchColumn *column;
- gint index, length;
- JsonObject *response = NULL;
- JsonArray *resultsarray = NULL;
-
- response = json_node_get_object(node);
- resultsarray = json_object_get_array_member(response, "results");
- length = json_array_get_length(resultsarray);
-
- PurpleNotifySearchResults *results = purple_notify_searchresults_new();
- if (results == NULL || length == 0)
- {
- if (olength)
- {
- *olength = 0;
- }
- return NULL;
- }
-
- /* columns: Friend ID, Name, Network */
- column = purple_notify_searchresults_column_new(_("Skype Name"));
- purple_notify_searchresults_column_add(results, column);
- column = purple_notify_searchresults_column_new(_("Display Name"));
- purple_notify_searchresults_column_add(results, column);
- column = purple_notify_searchresults_column_new(_("City"));
- purple_notify_searchresults_column_add(results, column);
- column = purple_notify_searchresults_column_new(_("Country"));
- purple_notify_searchresults_column_add(results, column);
-
- purple_notify_searchresults_button_add(results,
- PURPLE_NOTIFY_BUTTON_ADD,
- skypeweb_search_results_add_buddy);
-
- for(index = 0; index < length; index++)
- {
- JsonObject *result = json_array_get_object_element(resultsarray, index);
- JsonObject *skypecontact = json_object_get_object_member(result, "nodeProfileData");
-
- /* the row in the search results table */
- /* prepend to it backwards then reverse to speed up adds */
- GList *row = NULL;
-
-#define add_skypecontact_row(value) (\
- row = g_list_prepend(row, \
- !json_object_has_member(skypecontact, (value)) ? NULL : \
- g_strdup(json_object_get_string_member(skypecontact, (value)))\
- ) \
-)
- add_skypecontact_row("skypeId");
- add_skypecontact_row("name");
- add_skypecontact_row("city");
- add_skypecontact_row("country");
-
- row = g_list_reverse(row);
-
- purple_notify_searchresults_row_add(results, row);
- }
-
- if (olength)
- {
- *olength = length;
- }
- return results;
-}
-
-static void
-skypeweb_search_users_text_cb(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- gint length;
- gchar *search_term = user_data;
- PurpleNotifySearchResults *results = create_search_results(node, &length);
-
- if (results == NULL || length == 0)
- {
- gchar *primary_text = g_strdup_printf("Your search for the user \"%s\" returned no results", search_term);
- purple_notify_warning(sa->pc, _("No users found"), primary_text, "", purple_request_cpar_from_connection(sa->pc));
- g_free(primary_text);
- g_free(search_term);
- return;
- }
-
- purple_notify_searchresults(sa->pc, NULL, search_term, NULL, results, NULL, NULL);
-}
-
-static void
-skypeweb_contact_suggestions_received_cb(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- gint length;
- PurpleNotifySearchResults *results = create_search_results(node, &length);
-
- if (results == NULL || length == 0)
- {
- purple_notify_warning(sa->pc, _("No results"), _("There are no contact suggestions available for you"), "", purple_request_cpar_from_connection(sa->pc));
- return;
- }
-
- purple_notify_searchresults(sa->pc, _("Contact suggestions"), NULL, NULL, results, NULL, NULL);
-}
-
-void
-skypeweb_search_users_text(gpointer user_data, const gchar *text)
-{
- SkypeWebAccount *sa = user_data;
- GString *url = g_string_new("/search/v1.1/namesearch/swx/?");
-
- g_string_append_printf(url, "searchstring=%s&", purple_url_encode(text));
- g_string_append(url, "requestId=1&");
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_GRAPH_HOST, url->str, NULL, skypeweb_search_users_text_cb, g_strdup(text), FALSE);
-
- g_string_free(url, TRUE);
-}
-
-void
-skypeweb_search_users(PurpleProtocolAction *action)
-{
- PurpleConnection *pc = purple_protocol_action_get_connection(action);
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
-
- purple_request_input(pc, "Search for Skype Friends",
- "Search for Skype Friends",
- NULL,
- NULL, FALSE, FALSE, NULL,
- _("_Search"), G_CALLBACK(skypeweb_search_users_text),
- _("_Cancel"), NULL,
- purple_request_cpar_from_connection(pc),
- sa);
-
-}
-
-void
-skypeweb_contact_suggestions(PurpleProtocolAction *action)
-{
- PurpleConnection *pc = purple_protocol_action_get_connection(action);
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
-
- GString *url = g_string_new("/v1.1/recommend?requestId=1&locale=en-US&count=20");
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_DEFAULT_CONTACT_SUGGESTIONS_HOST, url->str, NULL, skypeweb_contact_suggestions_received_cb, 0, FALSE);
-
- g_string_free(url, TRUE);
-}
-
-static void
-skypeweb_got_friend_profiles(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- JsonArray *contacts;
- PurpleBuddy *buddy;
- SkypeWebBuddy *sbuddy;
- gint index, length;
-
- if (node == NULL || json_node_get_node_type(node) != JSON_NODE_ARRAY)
- return;
- contacts = json_node_get_array(node);
- length = json_array_get_length(contacts);
-
- for(index = 0; index < length; index++)
- {
- JsonObject *contact = json_array_get_object_element(contacts, index);
-
- const gchar *username = json_object_get_string_member(contact, "username");
- const gchar *new_avatar;
-
- buddy = purple_blist_find_buddy(sa->account, username);
- if (!buddy)
- continue;
- sbuddy = purple_buddy_get_protocol_data(buddy);
- if (sbuddy == NULL) {
- sbuddy = g_new0(SkypeWebBuddy, 1);
- purple_buddy_set_protocol_data(buddy, sbuddy);
- sbuddy->skypename = g_strdup(username);
- sbuddy->sa = sa;
- }
-
- g_free(sbuddy->display_name); sbuddy->display_name = g_strdup(json_object_get_string_member(contact, "displayname"));
- purple_serv_got_alias(sa->pc, username, sbuddy->display_name);
- if (json_object_has_member(contact, "lastname")) {
- gchar *fullname = g_strconcat(json_object_get_string_member(contact, "firstname"), " ", json_object_get_string_member(contact, "lastname"), NULL);
-
- purple_buddy_set_server_alias(buddy, fullname);
-
- g_free(fullname);
- } else {
- purple_buddy_set_server_alias(buddy, json_object_get_string_member(contact, "firstname"));
- }
-
- new_avatar = json_object_get_string_member(contact, "avatarUrl");
- if (new_avatar && *new_avatar && (!sbuddy->avatar_url || !g_str_equal(sbuddy->avatar_url, new_avatar))) {
- g_free(sbuddy->avatar_url);
- sbuddy->avatar_url = g_strdup(new_avatar);
- skypeweb_get_icon(buddy);
- }
-
- g_free(sbuddy->mood); sbuddy->mood = g_strdup(json_object_get_string_member(contact, "mood"));
- }
-}
-
-void
-skypeweb_get_friend_profiles(SkypeWebAccount *sa, GSList *contacts)
-{
- const gchar *profiles_url = "/users/self/contacts/profiles";
- GString *postdata;
- GSList *cur = contacts;
-
- if (contacts == NULL)
- return;
-
- postdata = g_string_new("");
-
- do {
- g_string_append_printf(postdata, "&contacts[]=%s", purple_url_encode(cur->data));
- } while((cur = g_slist_next(cur)));
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_CONTACTS_HOST, profiles_url, postdata->str, skypeweb_got_friend_profiles, NULL, TRUE);
-
- g_string_free(postdata, TRUE);
-}
-
-
-static void
-skypeweb_got_info(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- gchar *username = user_data;
- PurpleNotifyUserInfo *user_info;
- JsonObject *userobj;
- PurpleBuddy *buddy;
- SkypeWebBuddy *sbuddy;
-
- if (node == NULL)
- return;
- if (json_node_get_node_type(node) == JSON_NODE_ARRAY)
- node = json_array_get_element(json_node_get_array(node), 0);
- if (json_node_get_node_type(node) != JSON_NODE_OBJECT)
- return;
- userobj = json_node_get_object(node);
-
- user_info = purple_notify_user_info_new();
-
-#define _SKYPE_USER_INFO(prop, key) if (prop && json_object_has_member(userobj, (prop)) && !json_object_get_null_member(userobj, (prop))) \
- purple_notify_user_info_add_pair_html(user_info, _(key), json_object_get_string_member(userobj, (prop)));
-
- _SKYPE_USER_INFO("firstname", "First Name");
- _SKYPE_USER_INFO("lastname", "Last Name");
- _SKYPE_USER_INFO("birthday", "Birthday");
- //_SKYPE_USER_INFO("gender", "Gender");
- if (json_object_has_member(userobj, "gender") && !json_object_get_null_member(userobj, "gender")) {
- const gchar *gender_output = _("Unknown");
-
- // Can be presented as either a string of a number or as a number argh
- if (json_node_get_value_type(json_object_get_member(userobj, "gender")) == G_TYPE_STRING) {
- const gchar *gender = json_object_get_string_member(userobj, "gender");
- if (gender && *gender == '1') {
- gender_output = _("Male");
- } else if (gender && *gender == '2') {
- gender_output = _("Female");
- }
- } else {
- gint64 gender = json_object_get_int_member(userobj, "gender");
- if (gender == 1) {
- gender_output = _("Male");
- } else if (gender == 2) {
- gender_output = _("Female");
- }
- }
-
- purple_notify_user_info_add_pair_html(user_info, _("Gender"), gender_output);
- }
- _SKYPE_USER_INFO("language", "Language");
- _SKYPE_USER_INFO("country", "Country");
- _SKYPE_USER_INFO("province", "Province");
- _SKYPE_USER_INFO("city", "City");
- _SKYPE_USER_INFO("homepage", "Homepage");
- _SKYPE_USER_INFO("about", "About");
- _SKYPE_USER_INFO("jobtitle", "Job Title");
- _SKYPE_USER_INFO("phoneMobile", "Phone - Mobile");
- _SKYPE_USER_INFO("phoneHome", "Phone - Home");
- _SKYPE_USER_INFO("phoneOffice", "Phone - Office");
- //_SKYPE_USER_INFO("mood", "Mood");
- //_SKYPE_USER_INFO("richMood", "Mood");
- //_SKYPE_USER_INFO("avatarUrl", "Avatar");
-
- buddy = purple_blist_find_buddy(sa->account, username);
- if (buddy) {
- sbuddy = purple_buddy_get_protocol_data(buddy);
- if (sbuddy == NULL) {
- sbuddy = g_new0(SkypeWebBuddy, 1);
- purple_buddy_set_protocol_data(buddy, sbuddy);
- sbuddy->skypename = g_strdup(username);
- sbuddy->sa = sa;
- }
-
- //At the moment, "mood" field is present but always null via this call. Do not clear it.
- if (json_object_has_member(userobj, ("mood")) && !json_object_get_null_member(userobj, ("mood"))) {
- g_free(sbuddy->mood); sbuddy->mood = g_strdup(json_object_get_string_member(userobj, "mood"));
- }
- }
-
- purple_notify_userinfo(sa->pc, username, user_info, NULL, NULL);
-
- g_free(username);
-}
-
-void
-skypeweb_get_info(PurpleConnection *pc, const gchar *username)
-{
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
- gchar *post;
- const gchar *url = "/users/batch/profiles";
- JsonObject *obj;
- JsonArray *usernames_array;
-
- obj = json_object_new();
- usernames_array = json_array_new();
-
- json_array_add_string_element(usernames_array, username);
- json_object_set_array_member(obj, "usernames", usernames_array);
- post = skypeweb_jsonobj_to_string(obj);
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_CONTACTS_HOST, url, post, skypeweb_got_info, g_strdup(username), TRUE);
-
- g_free(post);
- json_object_unref(obj);
-}
-
-void
-skypeweb_get_friend_profile(SkypeWebAccount *sa, const gchar *who)
-{
- GSList *contacts = NULL;
- gchar *whodup;
-
- g_return_if_fail(sa && who && *who);
-
- whodup = g_strdup(who);
- contacts = g_slist_prepend(contacts, whodup);
-
- skypeweb_get_friend_profiles(sa, contacts);
-
- g_free(contacts);
- g_free(whodup);
-}
-
-static void
-skypeweb_get_friend_list_cb(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- JsonObject *obj;
- JsonArray *contacts;
- PurpleGroup *group = NULL;
- GSList *users_to_fetch = NULL;
- guint index, length;
-
- obj = json_node_get_object(node);
- contacts = json_object_get_array_member(obj, "contacts");
- length = json_array_get_length(contacts);
-
- for(index = 0; index < length; index++)
- {
- JsonObject *contact = json_array_get_object_element(contacts, index);
- JsonObject *profile = json_object_get_object_member(contact, "profile");
- const gchar *mri = json_object_get_string_member(contact, "mri");
- const gchar *display_name = json_object_get_string_member(contact, "display_name");
- const gchar *avatar_url = NULL;
- gboolean authorized = json_object_get_boolean_member(contact, "authorized");
- gboolean blocked = json_object_get_boolean_member(contact, "blocked");
-
- const gchar *mood = json_object_get_string_member(profile, "mood");
- JsonObject *name = json_object_get_object_member(profile, "name");
- const gchar *firstname = json_object_get_string_member(name, "first");
- const gchar *surname = NULL;
-
- PurpleBuddy *buddy;
- const gchar *id;
-
- if (json_object_has_member(contact, "suggested") && json_object_get_boolean_member(contact, "suggested") && !authorized) {
- // suggested buddies wtf? some kind of advertising?
- continue;
- }
-
- id = skypeweb_strip_user_prefix(mri);
-
- buddy = purple_blist_find_buddy(sa->account, id);
- if (!buddy)
- {
- if (!group)
- {
- group = purple_blist_find_group("Skype");
- if (!group)
- {
- group = purple_group_new("Skype");
- purple_blist_add_group(group, NULL);
- }
- }
- buddy = purple_buddy_new(sa->account, id, display_name);
- purple_blist_add_buddy(buddy, NULL, group, NULL);
- }
-
- if (name && json_object_has_member(name, "surname"))
- surname = json_object_get_string_member(name, "surname");
-
- // try to free the sbuddy here. no-op if it's not set before, otherwise prevents a leak.
- skypeweb_buddy_free(buddy);
-
- SkypeWebBuddy *sbuddy = g_new0(SkypeWebBuddy, 1);
- sbuddy->skypename = g_strdup(id);
- sbuddy->sa = sa;
- sbuddy->fullname = g_strconcat(firstname, (surname ? " " : NULL), surname, NULL);
- sbuddy->display_name = g_strdup(display_name);
- sbuddy->authorized = authorized;
- sbuddy->blocked = blocked;
- sbuddy->avatar_url = g_strdup(purple_buddy_icons_get_checksum_for_user(buddy));
- sbuddy->mood = g_strdup(mood);
-
- sbuddy->buddy = buddy;
- purple_buddy_set_protocol_data(buddy, sbuddy);
-
- if (!purple_strequal(purple_buddy_get_local_alias(buddy), sbuddy->display_name)) {
- purple_serv_got_alias(sa->pc, id, sbuddy->display_name);
- }
- if (!purple_strequal(purple_buddy_get_server_alias(buddy), sbuddy->fullname)) {
- purple_buddy_set_server_alias(buddy, sbuddy->fullname);
- }
-
- if (json_object_has_member(profile, "avatar_url")) {
- avatar_url = json_object_get_string_member(profile, "avatar_url");
- if (avatar_url && *avatar_url && (!sbuddy->avatar_url || !g_str_equal(sbuddy->avatar_url, avatar_url))) {
- g_free(sbuddy->avatar_url);
- sbuddy->avatar_url = g_strdup(avatar_url);
- skypeweb_get_icon(buddy);
- }
- }
-
- if (blocked == TRUE) {
- purple_account_privacy_deny_add(sa->account, id, TRUE);
- } else {
- users_to_fetch = g_slist_prepend(users_to_fetch, sbuddy->skypename);
- }
-
- if (purple_strequal(skypeweb_strip_user_prefix(id), sa->primary_member_name)) {
- g_free(sa->self_display_name);
- sa->self_display_name = g_strdup(display_name);
- }
- }
-
- if (users_to_fetch)
- {
- //skypeweb_get_friend_profiles(sa, users_to_fetch);
- skypeweb_subscribe_to_contact_status(sa, users_to_fetch);
- g_slist_free(users_to_fetch);
- }
-}
-
-void
-skypeweb_get_friend_list(SkypeWebAccount *sa)
-{
- const gchar *url = "/contacts/v2/users/SELF?delta=&reason=default";
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, skypeweb_get_friend_list_cb, NULL, TRUE);
-}
-
-
-
-void
-skypeweb_auth_accept_cb(
-#if PURPLE_VERSION_CHECK(3, 0, 0)
- const gchar *who,
-#endif
- gpointer sender)
-{
- PurpleBuddy *buddy = sender;
- SkypeWebAccount *sa;
- gchar *url = NULL;
- GSList *users_to_fetch;
- gchar *buddy_name;
-
- sa = purple_connection_get_protocol_data(purple_account_get_connection(purple_buddy_get_account(buddy)));
- buddy_name = g_strdup(purple_buddy_get_name(buddy));
-
- url = g_strdup_printf("/contacts/v2/users/SELF/invites/%s%s/accept", skypeweb_user_url_prefix(buddy_name), purple_url_encode(buddy_name));
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, NULL, NULL, TRUE);
- g_free(url);
-
- // Subscribe to status/message updates
- users_to_fetch = g_slist_prepend(NULL, buddy_name);
- skypeweb_subscribe_to_contact_status(sa, users_to_fetch);
- g_slist_free(users_to_fetch);
- g_free(buddy_name);
-}
-
-void
-skypeweb_auth_reject_cb(
-#if PURPLE_VERSION_CHECK(3, 0, 0)
- const gchar *who,
-#endif
- gpointer sender)
-{
- PurpleBuddy *buddy = sender;
- SkypeWebAccount *sa;
- gchar *url = NULL;
- gchar *buddy_name;
-
- sa = purple_connection_get_protocol_data(purple_account_get_connection(purple_buddy_get_account(buddy)));
- buddy_name = g_strdup(purple_buddy_get_name(buddy));
-
- url = g_strdup_printf("/contacts/v2/users/SELF/invites/%s%s/decline", skypeweb_user_url_prefix(buddy_name), purple_url_encode(buddy_name));
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, NULL, NULL, TRUE);
-
- g_free(url);
- g_free(buddy_name);
-}
-
-static void
-skypeweb_got_authrequests(SkypeWebAccount *sa, JsonNode *node, gpointer user_data)
-{
- JsonObject *requests;
- JsonArray *invite_list;
- guint index, length;
- time_t latest_timestamp = 0;
-
- requests = json_node_get_object(node);
- invite_list = json_object_get_array_member(requests, "invite_list");
- length = json_array_get_length(invite_list);
- for(index = 0; index < length; index++)
- {
- JsonObject *invite = json_array_get_object_element(invite_list, index);
- JsonArray *invites = json_object_get_array_member(invite, "invites");
- const gchar *event_time_iso = json_object_get_string_member(json_array_get_object_element(invites, 0), "time");
- time_t event_timestamp = purple_str_to_time(event_time_iso, TRUE, NULL, NULL, NULL);
- const gchar *sender = json_object_get_string_member(invite, "mri");
- const gchar *greeting = json_object_get_string_member(invite, "greeting");
- if (!greeting)
- greeting = json_object_get_string_member(json_array_get_object_element(invites, 0), "message");
- const gchar *displayname = json_object_get_string_member(invite, "displayname");
-
- latest_timestamp = MAX(latest_timestamp, event_timestamp);
- if (sa->last_authrequest && event_timestamp <= sa->last_authrequest)
- continue;
-
- if (sender == NULL)
- continue;
- sender = skypeweb_strip_user_prefix(sender);
-
- purple_account_request_authorization(
- sa->account, sender, NULL,
- displayname, greeting, FALSE,
- skypeweb_auth_accept_cb, skypeweb_auth_reject_cb, purple_buddy_new(sa->account, sender, displayname));
-
- }
-
- sa->last_authrequest = latest_timestamp;
-}
-
-gboolean
-skypeweb_check_authrequests(SkypeWebAccount *sa)
-{
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, "/contacts/v2/users/SELF/invites", NULL, skypeweb_got_authrequests, NULL, TRUE);
- return TRUE;
-}
-
-
-void
-skypeweb_add_buddy_with_invite(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
-{
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
- gchar *postdata;
- const gchar *url = "/contacts/v2/users/SELF/contacts";
- GSList *users_to_fetch;
- JsonObject *obj;
- gchar *buddy_name, *mri;
-
- //https://contacts.skype.com/contacts/v2/users/SELF/contacts
- // POST {"mri":"2:eionrobb@dequis.onmicrosoft.com","greeting":"Hi, eionrobb@dequis.onmicrosoft.com, I'd like to add you as a contact."}
-
- buddy_name = g_strdup(purple_buddy_get_name(buddy));
- mri = g_strconcat(skypeweb_user_url_prefix(buddy_name), buddy_name, NULL);
-
- obj = json_object_new();
-
- json_object_set_string_member(obj, "mri", mri);
- json_object_set_string_member(obj, "greeting", message ? message : _("Please authorize me so I can add you to my buddy list."));
- postdata = skypeweb_jsonobj_to_string(obj);
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, postdata, NULL, NULL, TRUE);
-
- g_free(mri);
- g_free(postdata);
- json_object_unref(obj);
-
- // Subscribe to status/message updates
- users_to_fetch = g_slist_prepend(NULL, buddy_name);
- skypeweb_subscribe_to_contact_status(sa, users_to_fetch);
- g_slist_free(users_to_fetch);
-
- g_free(buddy_name);
-}
-
-void
-skypeweb_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group)
-{
- skypeweb_add_buddy_with_invite(pc, buddy, group, NULL);
-}
-
-void
-skypeweb_buddy_remove(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group)
-{
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
- gchar *url;
- const gchar *buddy_name = purple_buddy_get_name(buddy);
-
- url = g_strdup_printf("/contacts/v2/users/SELF/contacts/%s%s", skypeweb_user_url_prefix(buddy_name), purple_url_encode(buddy_name));
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_DELETE | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, NULL, NULL, TRUE);
-
- g_free(url);
-
- skypeweb_unsubscribe_from_contact_status(sa, buddy_name);
-}
-
-void
-skypeweb_buddy_block(PurpleConnection *pc, const char *name)
-{
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
- gchar *url;
- const gchar *postdata;
-
- url = g_strdup_printf("/contacts/v2/users/SELF/contacts/blocklist/%s%s", skypeweb_user_url_prefix(name), purple_url_encode(name));
- postdata = "{\"report_abuse\":\"false\",\"ui_version\":\"skype.com\"}";
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, postdata, NULL, NULL, TRUE);
-
- g_free(url);
-}
-
-void
-skypeweb_buddy_unblock(PurpleConnection *pc, const char *name)
-{
- SkypeWebAccount *sa = purple_connection_get_protocol_data(pc);
- gchar *url;
-
- url = g_strdup_printf("/contacts/v2/users/SELF/contacts/blocklist/%s%s", skypeweb_user_url_prefix(name), purple_url_encode(name));
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_DELETE | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, NULL, NULL, TRUE);
-
- g_free(url);
-}
-
-
-void
-skypeweb_set_mood_message(SkypeWebAccount *sa, const gchar *mood)
-{
- JsonObject *obj, *payload;
- gchar *post;
-
- obj = json_object_new();
- payload = json_object_new();
-
- json_object_set_string_member(payload, "mood", mood ? mood : "");
- json_object_set_object_member(obj, "payload", payload);
- post = skypeweb_jsonobj_to_string(obj);
-
- skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_CONTACTS_HOST, "/users/self/profile/partial", post, NULL, NULL, TRUE);
-
- g_free(post);
- json_object_unref(obj);
-}
+ +} + +static void +skypeweb_xfer_send_init(PurpleXfer *xfer) +{ + PurpleConnection *pc = purple_account_get_connection(purple_xfer_get_account(xfer)); + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + gchar *basename = g_path_get_basename(purple_xfer_get_local_filename(xfer)); + gchar *id, *post; + SkypeWebFileTransfer *swft = purple_xfer_get_protocol_data(xfer); + JsonObject *obj = json_object_new(); + JsonObject *permissions = json_object_new(); + JsonArray *userpermissions = json_array_new(); + PurpleHttpRequest *request; + + purple_xfer_set_filename(xfer, basename); + purple_xfer_ref(xfer); + + json_object_set_string_member(obj, "type", "sharing/file"); + json_object_set_string_member(obj, "filename", basename); + + id = g_strconcat(skypeweb_user_url_prefix(swft->from), swft->from, NULL); + json_array_add_string_element(userpermissions, "read"); + json_object_set_array_member(permissions, id, userpermissions); + json_object_set_object_member(obj, "permissions", permissions); + + post = skypeweb_jsonobj_to_string(obj); + //POST to api.asm.skype.com /v1/objects + //{"type":"sharing/file","permissions":{"8:eionrobb":["read"]},"filename":"GiantLobsterMoose.txt"} + + request = purple_http_request_new("https://" SKYPEWEB_XFER_HOST "/v1/objects"); + purple_http_request_set_method(request, "POST"); + purple_http_request_set_keepalive_pool(request, sa->keepalive_pool); + purple_http_request_header_set_printf(request, "Authorization", "skype_token %s", sa->skype_token); //slightly different to normal! + purple_http_request_header_set(request, "Content-Type", "application/json"); + purple_http_request_header_set(request, "X-Client-Version", SKYPEWEB_CLIENTINFO_VERSION); + purple_http_request_set_contents(request, post, -1); + purple_http_request(sa->pc, request, skypeweb_got_object_for_file, swft); + purple_http_request_unref(request); + + g_free(post); + json_object_unref(obj); + g_free(id); + g_free(basename); +} + +PurpleXfer * +skypeweb_new_xfer( +#if PURPLE_VERSION_CHECK(3, 0, 0) +PurpleProtocolXfer *prplxfer, +#endif +PurpleConnection *pc, const char *who) +{ + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + PurpleXfer *xfer; + SkypeWebFileTransfer *swft; + + xfer = purple_xfer_new(sa->account, PURPLE_XFER_TYPE_SEND, who); + + swft = g_new0(SkypeWebFileTransfer, 1); + swft->sa = sa; + swft->from = g_strdup(who); + swft->xfer = xfer; + purple_xfer_set_protocol_data(xfer, swft); + + purple_xfer_set_init_fnc(xfer, skypeweb_xfer_send_init); + //purple_xfer_set_write_fnc(xfer, skypeweb_xfer_send_write); + //purple_xfer_set_end_fnc(xfer, skypeweb_xfer_send_end); + purple_xfer_set_request_denied_fnc(xfer, skypeweb_free_xfer); + purple_xfer_set_cancel_send_fnc(xfer, skypeweb_free_xfer); + + return xfer; +} + +void +skypeweb_send_file( +#if PURPLE_VERSION_CHECK(3, 0, 0) +PurpleProtocolXfer *prplxfer, +#endif +PurpleConnection *pc, const gchar *who, const gchar *filename) +{ + PurpleXfer *xfer = skypeweb_new_xfer( +#if PURPLE_VERSION_CHECK(3, 0, 0) + prplxfer, +#endif + pc, who); + + if (filename && *filename) + purple_xfer_request_accepted(xfer, filename); + else + purple_xfer_request(xfer); +} + +gboolean +skypeweb_can_receive_file( +#if PURPLE_VERSION_CHECK(3, 0, 0) +PurpleProtocolXfer *prplxfer, +#endif +PurpleConnection *pc, const gchar *who) +{ + if (!who || g_str_equal(who, purple_account_get_username(purple_connection_get_account(pc)))) + return FALSE; + + return TRUE; +} + + +static void +skypeweb_got_self_details(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + JsonObject *userobj; + const gchar *old_alias; + const gchar *displayname = NULL; + const gchar *username; + + if (node == NULL || json_node_get_node_type(node) != JSON_NODE_OBJECT) + return; + userobj = json_node_get_object(node); + + username = json_object_get_string_member(userobj, "username"); + g_free(sa->username); sa->username = g_strdup(username); + purple_connection_set_display_name(sa->pc, sa->username); + + old_alias = purple_account_get_private_alias(sa->account); + if (!old_alias || !*old_alias) { + if (json_object_has_member(userobj, "displayname")) + displayname = json_object_get_string_member(userobj, "displayname"); + if (!displayname || purple_strequal(displayname, username)) + displayname = json_object_get_string_member(userobj, "firstname"); + + if (displayname) + purple_account_set_private_alias(sa->account, displayname); + } + + if (!PURPLE_CONNECTION_IS_CONNECTED(sa->pc)) { + skypeweb_do_all_the_things(sa); + } + + skypeweb_gather_self_properties(sa); +} + + +void +skypeweb_get_self_details(SkypeWebAccount *sa) +{ + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_CONTACTS_HOST, "/users/self/profile", NULL, skypeweb_got_self_details, NULL, TRUE); +} + + + + + + + + + +void +skypeweb_search_results_add_buddy(PurpleConnection *pc, GList *row, void *user_data) +{ + PurpleAccount *account = purple_connection_get_account(pc); + + if (!purple_blist_find_buddy(account, g_list_nth_data(row, 0))) + purple_blist_request_add_buddy(account, g_list_nth_data(row, 0), "Skype", g_list_nth_data(row, 1)); +} + +void +skypeweb_received_contacts(SkypeWebAccount *sa, PurpleXmlNode *contacts) +{ + PurpleNotifySearchResults *results; + PurpleNotifySearchColumn *column; + + PurpleXmlNode *contact; + + results = purple_notify_searchresults_new(); + if (results == NULL) { + return; + } + + /* columns: Friend ID, Name */ + column = purple_notify_searchresults_column_new(_("Skype Name")); + purple_notify_searchresults_column_add(results, column); + column = purple_notify_searchresults_column_new(_("Display Name")); + purple_notify_searchresults_column_add(results, column); + + + purple_notify_searchresults_button_add(results, + PURPLE_NOTIFY_BUTTON_ADD, + skypeweb_search_results_add_buddy); + + for(contact = purple_xmlnode_get_child(contacts, "c"); contact; + contact = purple_xmlnode_get_next_twin(contact)) + { + GList *row = NULL; + + gchar *contact_id = g_strdup(purple_xmlnode_get_attrib(contact, "s")); + gchar *contact_name = g_strdup(purple_xmlnode_get_attrib(contact, "f")); + + row = g_list_append(row, contact_id); + row = g_list_append(row, contact_name); + + purple_notify_searchresults_row_add(results, row); + } + + purple_notify_searchresults(sa->pc, _("Received contacts"), NULL, NULL, results, NULL, NULL); +} + +static PurpleNotifySearchResults* +create_search_results(JsonNode *node, gint *olength) +{ + PurpleNotifySearchColumn *column; + gint index, length; + JsonObject *response = NULL; + JsonArray *resultsarray = NULL; + + response = json_node_get_object(node); + resultsarray = json_object_get_array_member(response, "results"); + length = json_array_get_length(resultsarray); + + PurpleNotifySearchResults *results = purple_notify_searchresults_new(); + if (results == NULL || length == 0) + { + if (olength) + { + *olength = 0; + } + return NULL; + } + + /* columns: Friend ID, Name, Network */ + column = purple_notify_searchresults_column_new(_("Skype Name")); + purple_notify_searchresults_column_add(results, column); + column = purple_notify_searchresults_column_new(_("Display Name")); + purple_notify_searchresults_column_add(results, column); + column = purple_notify_searchresults_column_new(_("City")); + purple_notify_searchresults_column_add(results, column); + column = purple_notify_searchresults_column_new(_("Country")); + purple_notify_searchresults_column_add(results, column); + + purple_notify_searchresults_button_add(results, + PURPLE_NOTIFY_BUTTON_ADD, + skypeweb_search_results_add_buddy); + + for(index = 0; index < length; index++) + { + JsonObject *result = json_array_get_object_element(resultsarray, index); + JsonObject *skypecontact = json_object_get_object_member(result, "nodeProfileData"); + + /* the row in the search results table */ + /* prepend to it backwards then reverse to speed up adds */ + GList *row = NULL; + +#define add_skypecontact_row(value) (\ + row = g_list_prepend(row, \ + !json_object_has_member(skypecontact, (value)) ? NULL : \ + g_strdup(json_object_get_string_member(skypecontact, (value)))\ + ) \ +) + add_skypecontact_row("skypeId"); + add_skypecontact_row("name"); + add_skypecontact_row("city"); + add_skypecontact_row("country"); + + row = g_list_reverse(row); + + purple_notify_searchresults_row_add(results, row); + } + + if (olength) + { + *olength = length; + } + return results; +} + +static void +skypeweb_search_users_text_cb(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + gint length; + gchar *search_term = user_data; + PurpleNotifySearchResults *results = create_search_results(node, &length); + + if (results == NULL || length == 0) + { + gchar *primary_text = g_strdup_printf("Your search for the user \"%s\" returned no results", search_term); + purple_notify_warning(sa->pc, _("No users found"), primary_text, "", purple_request_cpar_from_connection(sa->pc)); + g_free(primary_text); + g_free(search_term); + return; + } + + purple_notify_searchresults(sa->pc, NULL, search_term, NULL, results, NULL, NULL); +} + +static void +skypeweb_contact_suggestions_received_cb(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + gint length; + PurpleNotifySearchResults *results = create_search_results(node, &length); + + if (results == NULL || length == 0) + { + purple_notify_warning(sa->pc, _("No results"), _("There are no contact suggestions available for you"), "", purple_request_cpar_from_connection(sa->pc)); + return; + } + + purple_notify_searchresults(sa->pc, _("Contact suggestions"), NULL, NULL, results, NULL, NULL); +} + +void +skypeweb_search_users_text(gpointer user_data, const gchar *text) +{ + SkypeWebAccount *sa = user_data; + GString *url = g_string_new("/search/v1.1/namesearch/swx/?"); + + g_string_append_printf(url, "searchstring=%s&", purple_url_encode(text)); + g_string_append(url, "requestId=1&"); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_GRAPH_HOST, url->str, NULL, skypeweb_search_users_text_cb, g_strdup(text), FALSE); + + g_string_free(url, TRUE); +} + +void +skypeweb_search_users(PurpleProtocolAction *action) +{ + PurpleConnection *pc = purple_protocol_action_get_connection(action); + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + + purple_request_input(pc, "Search for Skype Friends", + "Search for Skype Friends", + NULL, + NULL, FALSE, FALSE, NULL, + _("_Search"), G_CALLBACK(skypeweb_search_users_text), + _("_Cancel"), NULL, + purple_request_cpar_from_connection(pc), + sa); + +} + +void +skypeweb_contact_suggestions(PurpleProtocolAction *action) +{ + PurpleConnection *pc = purple_protocol_action_get_connection(action); + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + + GString *url = g_string_new("/v1.1/recommend?requestId=1&locale=en-US&count=20"); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_DEFAULT_CONTACT_SUGGESTIONS_HOST, url->str, NULL, skypeweb_contact_suggestions_received_cb, 0, FALSE); + + g_string_free(url, TRUE); +} + +static void +skypeweb_got_friend_profiles(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + JsonArray *contacts; + PurpleBuddy *buddy; + SkypeWebBuddy *sbuddy; + gint index, length; + + if (node == NULL || json_node_get_node_type(node) != JSON_NODE_ARRAY) + return; + contacts = json_node_get_array(node); + length = json_array_get_length(contacts); + + for(index = 0; index < length; index++) + { + JsonObject *contact = json_array_get_object_element(contacts, index); + + const gchar *username = json_object_get_string_member(contact, "username"); + const gchar *new_avatar; + + buddy = purple_blist_find_buddy(sa->account, username); + if (!buddy) + continue; + sbuddy = purple_buddy_get_protocol_data(buddy); + if (sbuddy == NULL) { + sbuddy = g_new0(SkypeWebBuddy, 1); + purple_buddy_set_protocol_data(buddy, sbuddy); + sbuddy->skypename = g_strdup(username); + sbuddy->sa = sa; + } + + g_free(sbuddy->display_name); sbuddy->display_name = g_strdup(json_object_get_string_member(contact, "displayname")); + purple_serv_got_alias(sa->pc, username, sbuddy->display_name); + if (json_object_has_member(contact, "lastname")) { + gchar *fullname = g_strconcat(json_object_get_string_member(contact, "firstname"), " ", json_object_get_string_member(contact, "lastname"), NULL); + + purple_buddy_set_server_alias(buddy, fullname); + + g_free(fullname); + } else { + purple_buddy_set_server_alias(buddy, json_object_get_string_member(contact, "firstname")); + } + + new_avatar = json_object_get_string_member(contact, "avatarUrl"); + if (new_avatar && *new_avatar && (!sbuddy->avatar_url || !g_str_equal(sbuddy->avatar_url, new_avatar))) { + g_free(sbuddy->avatar_url); + sbuddy->avatar_url = g_strdup(new_avatar); + skypeweb_get_icon(buddy); + } + + g_free(sbuddy->mood); sbuddy->mood = g_strdup(json_object_get_string_member(contact, "mood")); + } +} + +void +skypeweb_get_friend_profiles(SkypeWebAccount *sa, GSList *contacts) +{ + const gchar *profiles_url = "/users/self/contacts/profiles"; + GString *postdata; + GSList *cur = contacts; + + if (contacts == NULL) + return; + + postdata = g_string_new(""); + + do { + g_string_append_printf(postdata, "&contacts[]=%s", purple_url_encode(cur->data)); + } while((cur = g_slist_next(cur))); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_CONTACTS_HOST, profiles_url, postdata->str, skypeweb_got_friend_profiles, NULL, TRUE); + + g_string_free(postdata, TRUE); +} + + +static void +skypeweb_got_info(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + gchar *username = user_data; + PurpleNotifyUserInfo *user_info; + JsonObject *userobj; + PurpleBuddy *buddy; + SkypeWebBuddy *sbuddy; + + if (node == NULL) + return; + if (json_node_get_node_type(node) == JSON_NODE_ARRAY) + node = json_array_get_element(json_node_get_array(node), 0); + if (json_node_get_node_type(node) != JSON_NODE_OBJECT) + return; + userobj = json_node_get_object(node); + + user_info = purple_notify_user_info_new(); + +#define _SKYPE_USER_INFO(prop, key) if (prop && json_object_has_member(userobj, (prop)) && !json_object_get_null_member(userobj, (prop))) \ + purple_notify_user_info_add_pair_html(user_info, _(key), json_object_get_string_member(userobj, (prop))); + + _SKYPE_USER_INFO("firstname", "First Name"); + _SKYPE_USER_INFO("lastname", "Last Name"); + _SKYPE_USER_INFO("birthday", "Birthday"); + //_SKYPE_USER_INFO("gender", "Gender"); + if (json_object_has_member(userobj, "gender") && !json_object_get_null_member(userobj, "gender")) { + const gchar *gender_output = _("Unknown"); + + // Can be presented as either a string of a number or as a number argh + if (json_node_get_value_type(json_object_get_member(userobj, "gender")) == G_TYPE_STRING) { + const gchar *gender = json_object_get_string_member(userobj, "gender"); + if (gender && *gender == '1') { + gender_output = _("Male"); + } else if (gender && *gender == '2') { + gender_output = _("Female"); + } + } else { + gint64 gender = json_object_get_int_member(userobj, "gender"); + if (gender == 1) { + gender_output = _("Male"); + } else if (gender == 2) { + gender_output = _("Female"); + } + } + + purple_notify_user_info_add_pair_html(user_info, _("Gender"), gender_output); + } + _SKYPE_USER_INFO("language", "Language"); + _SKYPE_USER_INFO("country", "Country"); + _SKYPE_USER_INFO("province", "Province"); + _SKYPE_USER_INFO("city", "City"); + _SKYPE_USER_INFO("homepage", "Homepage"); + _SKYPE_USER_INFO("about", "About"); + _SKYPE_USER_INFO("jobtitle", "Job Title"); + _SKYPE_USER_INFO("phoneMobile", "Phone - Mobile"); + _SKYPE_USER_INFO("phoneHome", "Phone - Home"); + _SKYPE_USER_INFO("phoneOffice", "Phone - Office"); + //_SKYPE_USER_INFO("mood", "Mood"); + //_SKYPE_USER_INFO("richMood", "Mood"); + //_SKYPE_USER_INFO("avatarUrl", "Avatar"); + + buddy = purple_blist_find_buddy(sa->account, username); + if (buddy) { + sbuddy = purple_buddy_get_protocol_data(buddy); + if (sbuddy == NULL) { + sbuddy = g_new0(SkypeWebBuddy, 1); + purple_buddy_set_protocol_data(buddy, sbuddy); + sbuddy->skypename = g_strdup(username); + sbuddy->sa = sa; + } + + //At the moment, "mood" field is present but always null via this call. Do not clear it. + if (json_object_has_member(userobj, ("mood")) && !json_object_get_null_member(userobj, ("mood"))) { + g_free(sbuddy->mood); sbuddy->mood = g_strdup(json_object_get_string_member(userobj, "mood")); + } + } + + purple_notify_userinfo(sa->pc, username, user_info, NULL, NULL); + + g_free(username); +} + +void +skypeweb_get_info(PurpleConnection *pc, const gchar *username) +{ + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + gchar *post; + const gchar *url = "/users/batch/profiles"; + JsonObject *obj; + JsonArray *usernames_array; + + obj = json_object_new(); + usernames_array = json_array_new(); + + json_array_add_string_element(usernames_array, username); + json_object_set_array_member(obj, "usernames", usernames_array); + post = skypeweb_jsonobj_to_string(obj); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_CONTACTS_HOST, url, post, skypeweb_got_info, g_strdup(username), TRUE); + + g_free(post); + json_object_unref(obj); +} + +void +skypeweb_get_friend_profile(SkypeWebAccount *sa, const gchar *who) +{ + GSList *contacts = NULL; + gchar *whodup; + + g_return_if_fail(sa && who && *who); + + whodup = g_strdup(who); + contacts = g_slist_prepend(contacts, whodup); + + skypeweb_get_friend_profiles(sa, contacts); + + g_free(contacts); + g_free(whodup); +} + +static void +skypeweb_get_friend_list_cb(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + JsonObject *obj; + JsonArray *contacts; + PurpleGroup *group = NULL; + GSList *users_to_fetch = NULL; + guint index, length; + + obj = json_node_get_object(node); + contacts = json_object_get_array_member(obj, "contacts"); + length = json_array_get_length(contacts); + + for(index = 0; index < length; index++) + { + JsonObject *contact = json_array_get_object_element(contacts, index); + JsonObject *profile = json_object_get_object_member(contact, "profile"); + const gchar *mri = json_object_get_string_member(contact, "mri"); + const gchar *display_name = json_object_get_string_member(contact, "display_name"); + const gchar *avatar_url = NULL; + gboolean authorized = json_object_get_boolean_member(contact, "authorized"); + gboolean blocked = json_object_get_boolean_member(contact, "blocked"); + + const gchar *mood = json_object_get_string_member(profile, "mood"); + JsonObject *name = json_object_get_object_member(profile, "name"); + const gchar *firstname = json_object_get_string_member(name, "first"); + const gchar *surname = NULL; + + PurpleBuddy *buddy; + const gchar *id; + + if (json_object_has_member(contact, "suggested") && json_object_get_boolean_member(contact, "suggested") && !authorized) { + // suggested buddies wtf? some kind of advertising? + continue; + } + + id = skypeweb_strip_user_prefix(mri); + + buddy = purple_blist_find_buddy(sa->account, id); + if (!buddy) + { + if (!group) + { + group = purple_blist_find_group("Skype"); + if (!group) + { + group = purple_group_new("Skype"); + purple_blist_add_group(group, NULL); + } + } + buddy = purple_buddy_new(sa->account, id, display_name); + purple_blist_add_buddy(buddy, NULL, group, NULL); + } + + if (name && json_object_has_member(name, "surname")) + surname = json_object_get_string_member(name, "surname"); + + // try to free the sbuddy here. no-op if it's not set before, otherwise prevents a leak. + skypeweb_buddy_free(buddy); + + SkypeWebBuddy *sbuddy = g_new0(SkypeWebBuddy, 1); + sbuddy->skypename = g_strdup(id); + sbuddy->sa = sa; + sbuddy->fullname = g_strconcat(firstname, (surname ? " " : NULL), surname, NULL); + sbuddy->display_name = g_strdup(display_name); + sbuddy->authorized = authorized; + sbuddy->blocked = blocked; + sbuddy->avatar_url = g_strdup(purple_buddy_icons_get_checksum_for_user(buddy)); + sbuddy->mood = g_strdup(mood); + + sbuddy->buddy = buddy; + purple_buddy_set_protocol_data(buddy, sbuddy); + + if (!purple_strequal(purple_buddy_get_local_alias(buddy), sbuddy->display_name)) { + purple_serv_got_alias(sa->pc, id, sbuddy->display_name); + } + if (!purple_strequal(purple_buddy_get_server_alias(buddy), sbuddy->fullname)) { + purple_buddy_set_server_alias(buddy, sbuddy->fullname); + } + + if (json_object_has_member(profile, "avatar_url")) { + avatar_url = json_object_get_string_member(profile, "avatar_url"); + if (avatar_url && *avatar_url && (!sbuddy->avatar_url || !g_str_equal(sbuddy->avatar_url, avatar_url))) { + g_free(sbuddy->avatar_url); + sbuddy->avatar_url = g_strdup(avatar_url); + skypeweb_get_icon(buddy); + } + } + + if (blocked == TRUE) { + purple_account_privacy_deny_add(sa->account, id, TRUE); + } else { + users_to_fetch = g_slist_prepend(users_to_fetch, sbuddy->skypename); + } + + if (purple_strequal(skypeweb_strip_user_prefix(id), sa->primary_member_name)) { + g_free(sa->self_display_name); + sa->self_display_name = g_strdup(display_name); + } + } + + if (users_to_fetch) + { + //skypeweb_get_friend_profiles(sa, users_to_fetch); + skypeweb_subscribe_to_contact_status(sa, users_to_fetch); + g_slist_free(users_to_fetch); + } +} + +void +skypeweb_get_friend_list(SkypeWebAccount *sa) +{ + const gchar *url = "/contacts/v2/users/SELF?delta=&reason=default"; + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, skypeweb_get_friend_list_cb, NULL, TRUE); +} + + + +void +skypeweb_auth_accept_cb( +#if PURPLE_VERSION_CHECK(3, 0, 0) + const gchar *who, +#endif + gpointer sender) +{ + PurpleBuddy *buddy = sender; + SkypeWebAccount *sa; + gchar *url = NULL; + GSList *users_to_fetch; + gchar *buddy_name; + + sa = purple_connection_get_protocol_data(purple_account_get_connection(purple_buddy_get_account(buddy))); + buddy_name = g_strdup(purple_buddy_get_name(buddy)); + + url = g_strdup_printf("/contacts/v2/users/SELF/invites/%s%s/accept", skypeweb_user_url_prefix(buddy_name), purple_url_encode(buddy_name)); + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, NULL, NULL, TRUE); + g_free(url); + + // Subscribe to status/message updates + users_to_fetch = g_slist_prepend(NULL, buddy_name); + skypeweb_subscribe_to_contact_status(sa, users_to_fetch); + g_slist_free(users_to_fetch); + g_free(buddy_name); +} + +void +skypeweb_auth_reject_cb( +#if PURPLE_VERSION_CHECK(3, 0, 0) + const gchar *who, +#endif + gpointer sender) +{ + PurpleBuddy *buddy = sender; + SkypeWebAccount *sa; + gchar *url = NULL; + gchar *buddy_name; + + sa = purple_connection_get_protocol_data(purple_account_get_connection(purple_buddy_get_account(buddy))); + buddy_name = g_strdup(purple_buddy_get_name(buddy)); + + url = g_strdup_printf("/contacts/v2/users/SELF/invites/%s%s/decline", skypeweb_user_url_prefix(buddy_name), purple_url_encode(buddy_name)); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, NULL, NULL, TRUE); + + g_free(url); + g_free(buddy_name); +} + +static void +skypeweb_got_authrequests(SkypeWebAccount *sa, JsonNode *node, gpointer user_data) +{ + JsonObject *requests; + JsonArray *invite_list; + guint index, length; + time_t latest_timestamp = 0; + + requests = json_node_get_object(node); + invite_list = json_object_get_array_member(requests, "invite_list"); + length = json_array_get_length(invite_list); + for(index = 0; index < length; index++) + { + JsonObject *invite = json_array_get_object_element(invite_list, index); + JsonArray *invites = json_object_get_array_member(invite, "invites"); + const gchar *event_time_iso = json_object_get_string_member(json_array_get_object_element(invites, 0), "time"); + time_t event_timestamp = purple_str_to_time(event_time_iso, TRUE, NULL, NULL, NULL); + const gchar *sender = json_object_get_string_member(invite, "mri"); + const gchar *greeting = json_object_get_string_member(invite, "greeting"); + if (!greeting) + greeting = json_object_get_string_member(json_array_get_object_element(invites, 0), "message"); + const gchar *displayname = json_object_get_string_member(invite, "displayname"); + + latest_timestamp = MAX(latest_timestamp, event_timestamp); + if (sa->last_authrequest && event_timestamp <= sa->last_authrequest) + continue; + + if (sender == NULL) + continue; + sender = skypeweb_strip_user_prefix(sender); + + purple_account_request_authorization( + sa->account, sender, NULL, + displayname, greeting, FALSE, + skypeweb_auth_accept_cb, skypeweb_auth_reject_cb, purple_buddy_new(sa->account, sender, displayname)); + + } + + sa->last_authrequest = latest_timestamp; +} + +gboolean +skypeweb_check_authrequests(SkypeWebAccount *sa) +{ + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_GET | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, "/contacts/v2/users/SELF/invites", NULL, skypeweb_got_authrequests, NULL, TRUE); + return TRUE; +} + + +void +skypeweb_add_buddy_with_invite(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message) +{ + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + gchar *postdata; + const gchar *url = "/contacts/v2/users/SELF/contacts"; + GSList *users_to_fetch; + JsonObject *obj; + gchar *buddy_name, *mri; + + //https://contacts.skype.com/contacts/v2/users/SELF/contacts + // POST {"mri":"2:eionrobb@dequis.onmicrosoft.com","greeting":"Hi, eionrobb@dequis.onmicrosoft.com, I'd like to add you as a contact."} + + buddy_name = g_strdup(purple_buddy_get_name(buddy)); + mri = g_strconcat(skypeweb_user_url_prefix(buddy_name), buddy_name, NULL); + + obj = json_object_new(); + + json_object_set_string_member(obj, "mri", mri); + json_object_set_string_member(obj, "greeting", message ? message : _("Please authorize me so I can add you to my buddy list.")); + postdata = skypeweb_jsonobj_to_string(obj); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, postdata, NULL, NULL, TRUE); + + g_free(mri); + g_free(postdata); + json_object_unref(obj); + + // Subscribe to status/message updates + users_to_fetch = g_slist_prepend(NULL, buddy_name); + skypeweb_subscribe_to_contact_status(sa, users_to_fetch); + g_slist_free(users_to_fetch); + + g_free(buddy_name); +} + +void +skypeweb_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) +{ + skypeweb_add_buddy_with_invite(pc, buddy, group, NULL); +} + +void +skypeweb_buddy_remove(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group) +{ + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + gchar *url; + const gchar *buddy_name = purple_buddy_get_name(buddy); + + url = g_strdup_printf("/contacts/v2/users/SELF/contacts/%s%s", skypeweb_user_url_prefix(buddy_name), purple_url_encode(buddy_name)); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_DELETE | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, NULL, NULL, TRUE); + + g_free(url); + + skypeweb_unsubscribe_from_contact_status(sa, buddy_name); +} + +void +skypeweb_buddy_block(PurpleConnection *pc, const char *name) +{ + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + gchar *url; + const gchar *postdata; + + url = g_strdup_printf("/contacts/v2/users/SELF/contacts/blocklist/%s%s", skypeweb_user_url_prefix(name), purple_url_encode(name)); + postdata = "{\"report_abuse\":\"false\",\"ui_version\":\"skype.com\"}"; + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_PUT | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, postdata, NULL, NULL, TRUE); + + g_free(url); +} + +void +skypeweb_buddy_unblock(PurpleConnection *pc, const char *name) +{ + SkypeWebAccount *sa = purple_connection_get_protocol_data(pc); + gchar *url; + + url = g_strdup_printf("/contacts/v2/users/SELF/contacts/blocklist/%s%s", skypeweb_user_url_prefix(name), purple_url_encode(name)); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_DELETE | SKYPEWEB_METHOD_SSL, SKYPEWEB_NEW_CONTACTS_HOST, url, NULL, NULL, NULL, TRUE); + + g_free(url); +} + + +void +skypeweb_set_mood_message(SkypeWebAccount *sa, const gchar *mood) +{ + JsonObject *obj, *payload; + gchar *post; + + obj = json_object_new(); + payload = json_object_new(); + + json_object_set_string_member(payload, "mood", mood ? mood : ""); + json_object_set_object_member(obj, "payload", payload); + post = skypeweb_jsonobj_to_string(obj); + + skypeweb_post_or_get(sa, SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_SSL, SKYPEWEB_CONTACTS_HOST, "/users/self/profile/partial", post, NULL, NULL, TRUE); + + g_free(post); + json_object_unref(obj); +} |