1 /*
2 * SkypeWeb Plugin for libpurple/Pidgin
3 * Copyright (c) 2014-2020 Eion Robb
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "skypeweb_connection.h"
20
21 #include "http.h"
22
23 static void
skypeweb_destroy_connection(SkypeWebConnection * conn)24 skypeweb_destroy_connection(SkypeWebConnection *conn)
25 {
26 g_free(conn->url);
27 g_free(conn);
28 }
29
30 static void
skypeweb_post_or_get_cb(PurpleHttpConnection * http_conn,PurpleHttpResponse * response,gpointer user_data)31 skypeweb_post_or_get_cb(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, gpointer user_data)
32 {
33 SkypeWebConnection *conn = user_data;
34 const gchar *data;
35 gsize len;
36
37 data = purple_http_response_get_data(response, &len);
38
39 if (conn->callback != NULL) {
40 if (!len)
41 {
42 purple_debug_info("skypeweb", "No data in response\n");
43 conn->callback(conn->sa, NULL, conn->user_data);
44 } else {
45 JsonParser *parser = json_parser_new();
46 if (!json_parser_load_from_data(parser, data, len, NULL))
47 {
48 if (conn->error_callback != NULL) {
49 conn->error_callback(conn->sa, data, len, conn->user_data);
50 } else {
51 purple_debug_error("skypeweb", "Error parsing response: %s\n", data);
52 }
53 } else {
54 JsonNode *root = json_parser_get_root(parser);
55
56 purple_debug_info("skypeweb", "executing callback for %s\n", conn->url);
57 conn->callback(conn->sa, root, conn->user_data);
58 }
59 g_object_unref(parser);
60 }
61 }
62
63 skypeweb_destroy_connection(conn);
64 }
65
skypeweb_post_or_get(SkypeWebAccount * sa,SkypeWebMethod method,const gchar * host,const gchar * url,const gchar * postdata,SkypeWebProxyCallbackFunc callback_func,gpointer user_data,gboolean keepalive)66 SkypeWebConnection *skypeweb_post_or_get(SkypeWebAccount *sa, SkypeWebMethod method,
67 const gchar *host, const gchar *url, const gchar *postdata,
68 SkypeWebProxyCallbackFunc callback_func, gpointer user_data,
69 gboolean keepalive)
70 {
71 SkypeWebConnection *conn;
72 PurpleHttpRequest *request;
73 const gchar* const *languages;
74 gchar *language_names;
75 gchar *real_url;
76
77 g_return_val_if_fail(host != NULL, NULL);
78 g_return_val_if_fail(url != NULL, NULL);
79
80 real_url = g_strdup_printf("%s://%s%s", method & SKYPEWEB_METHOD_SSL ? "https" : "http", host, url);
81
82 request = purple_http_request_new(real_url);
83 if (method & SKYPEWEB_METHOD_POST) {
84 purple_http_request_set_method(request, "POST");
85 } else if (method & SKYPEWEB_METHOD_PUT) {
86 purple_http_request_set_method(request, "PUT");
87 } else if (method & SKYPEWEB_METHOD_DELETE) {
88 purple_http_request_set_method(request, "DELETE");
89 }
90 if (keepalive) {
91 purple_http_request_set_keepalive_pool(request, sa->keepalive_pool);
92 }
93
94 purple_http_request_set_max_redirects(request, 0);
95 purple_http_request_set_timeout(request, 120);
96
97 if (method & (SKYPEWEB_METHOD_POST | SKYPEWEB_METHOD_PUT)) {
98 if (postdata && (postdata[0] == '[' || postdata[0] == '{')) {
99 purple_http_request_header_set(request, "Content-Type", "application/json"); // hax
100 } else {
101 purple_http_request_header_set(request, "Content-Type", "application/x-www-form-urlencoded");
102 }
103 purple_http_request_set_contents(request, postdata, -1);
104
105 //Zero-length PUT's dont get the content-length header set
106 if ((method & SKYPEWEB_METHOD_PUT) && (!postdata || !*postdata)) {
107 purple_http_request_header_set(request, "Content-Length", "0");
108 }
109 }
110
111 if (g_str_equal(host, SKYPEWEB_CONTACTS_HOST) || g_str_equal(host, SKYPEWEB_VIDEOMAIL_HOST) || g_str_equal(host, SKYPEWEB_NEW_CONTACTS_HOST)) {
112 purple_http_request_header_set(request, "X-Skypetoken", sa->skype_token);
113 purple_http_request_header_set(request, "X-Stratus-Caller", SKYPEWEB_CLIENTINFO_NAME);
114 purple_http_request_header_set(request, "X-Stratus-Request", "abcd1234");
115 purple_http_request_header_set(request, "Origin", "https://web.skype.com");
116 purple_http_request_header_set(request, "Referer", "https://web.skype.com/main");
117 purple_http_request_header_set(request, "Accept", "application/json; ver=1.0;");
118 } else if (g_str_equal(host, SKYPEWEB_GRAPH_HOST)) {
119 purple_http_request_header_set(request, "X-Skypetoken", sa->skype_token);
120 purple_http_request_header_set(request, "Accept", "application/json");
121 } else if (g_str_equal(host, sa->messages_host)) {
122 purple_http_request_header_set(request, "RegistrationToken", sa->registration_token);
123 purple_http_request_header_set(request, "Referer", "https://web.skype.com/main");
124 purple_http_request_header_set(request, "Accept", "application/json; ver=1.0");
125 purple_http_request_header_set(request, "ClientInfo", "os=Windows; osVer=8.1; proc=Win32; lcid=en-us; deviceType=1; country=n/a; clientName=" SKYPEWEB_CLIENTINFO_NAME "; clientVer=" SKYPEWEB_CLIENTINFO_VERSION);
126 } else if (g_str_equal(host, SKYPEWEB_DEFAULT_CONTACT_SUGGESTIONS_HOST)) {
127 purple_http_request_header_set(request, "X-RecommenderServiceSettings", "{\"experiment\":\"default\",\"recommend\":\"true\"}");
128 purple_http_request_header_set(request, "X-ECS-ETag", SKYPEWEB_CLIENTINFO_NAME);
129 purple_http_request_header_set(request, "X-Skypetoken", sa->skype_token);
130 purple_http_request_header_set(request, "Accept", "application/json");
131 purple_http_request_header_set(request, "X-Skype-Client", SKYPEWEB_CLIENTINFO_VERSION);
132 } else {
133 purple_http_request_header_set(request, "Accept", "*/*");
134 purple_http_request_set_cookie_jar(request, sa->cookie_jar);
135 }
136
137 /* Tell the server what language we accept, so that we get error messages in our language (rather than our IP's) */
138 languages = g_get_language_names();
139 language_names = g_strjoinv(", ", (gchar **)languages);
140 purple_util_chrreplace(language_names, '_', '-');
141 purple_http_request_header_set(request, "Accept-Language", language_names);
142 g_free(language_names);
143
144 conn = g_new0(SkypeWebConnection, 1);
145 conn->sa = sa;
146 conn->user_data = user_data;
147 conn->url = real_url;
148 conn->callback = callback_func;
149
150 conn->http_conn = purple_http_request(sa->pc, request, skypeweb_post_or_get_cb, conn);
151 purple_http_connection_set_add(sa->conns, conn->http_conn);
152
153 purple_http_request_unref(request);
154
155 return conn;
156 }
157