libpurple/protocols/gg/edisc.c

changeset 34380
2179667660bc
parent 34378
63439e75c0b1
child 34383
4b1a106bbf1d
equal deleted inserted replaced
34379:ae843cc7b7dd 34380:2179667660bc
1 #include "edisc.h"
2
3 #include <debug.h>
4
5 #include "gg.h"
6 #include "libgaduw.h"
7 #include <http.h>
8
9 #define GGP_EDISC_HOSTNAME "MyComputer"
10 #define GGP_EDISC_OS "WINNT x86-msvc"
11 #define GGP_EDISC_TYPE "desktop"
12
13 #define GGP_EDISC_RESPONSE_MAX 10240
14
15 typedef struct _ggp_edisc_auth_data ggp_edisc_auth_data;
16
17 typedef struct _ggp_edisc_xfer ggp_edisc_xfer;
18
19 struct _ggp_edisc_session_data
20 {
21 PurpleHttpCookieJar *cookies;
22 gchar *security_token;
23
24 PurpleHttpConnection *auth_request;
25 gboolean auth_done;
26 GList *auth_pending;
27 };
28
29 struct _ggp_edisc_xfer
30 {
31 PurpleConnection *gc;
32 };
33
34 typedef void (*ggp_ggdrive_auth_cb)(PurpleConnection *gc, gboolean success,
35 gpointer user_data);
36
37 static void ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb,
38 gpointer user_data);
39
40 static void ggp_edisc_xfer_free(PurpleXfer *xfer);
41
42 /*******************************************************************************
43 * Setting up.
44 ******************************************************************************/
45
46 static inline ggp_edisc_session_data *
47 ggp_edisc_get_sdata(PurpleConnection *gc)
48 {
49 GGPInfo *accdata = purple_connection_get_protocol_data(gc);
50 return accdata->edisc_data;
51 }
52
53 void ggp_edisc_setup(PurpleConnection *gc)
54 {
55 GGPInfo *accdata = purple_connection_get_protocol_data(gc);
56 ggp_edisc_session_data *sdata = g_new0(ggp_edisc_session_data, 1);
57
58 accdata->edisc_data = sdata;
59
60 sdata->cookies = purple_http_cookie_jar_new();
61 }
62
63 void ggp_edisc_cleanup(PurpleConnection *gc)
64 {
65 ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
66
67 purple_http_conn_cancel(sdata->auth_request);
68 g_list_free_full(sdata->auth_pending, g_free);
69 g_free(sdata->security_token);
70
71 purple_http_cookie_jar_unref(sdata->cookies);
72
73 g_free(sdata);
74 }
75
76 /*******************************************************************************
77 * Sending a file.
78 ******************************************************************************/
79
80 static void ggp_edisc_xfer_init(PurpleXfer *xfer);
81 static void ggp_edisc_xfer_init_authenticated(PurpleConnection *gc,
82 gboolean success, gpointer _xfer);
83
84 static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg);
85
86 static void ggp_edisc_xfer_free(PurpleXfer *xfer)
87 {
88 ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer);
89
90 if (edisc_xfer == NULL)
91 return;
92
93 g_free(edisc_xfer);
94 purple_xfer_set_protocol_data(xfer, NULL);
95 }
96
97 static void ggp_edisc_xfer_error(PurpleXfer *xfer, const gchar *msg)
98 {
99 purple_xfer_error(
100 purple_xfer_get_type(xfer),
101 purple_xfer_get_account(xfer),
102 purple_xfer_get_remote_user(xfer),
103 msg);
104 ggp_edisc_xfer_free(xfer);
105 }
106
107 gboolean ggp_edisc_xfer_can_receive_file(PurpleConnection *gc, const char *who)
108 {
109 return TRUE; /* TODO: only online, buddies (?) */
110 }
111
112 static void ggp_edisc_xfer_init(PurpleXfer *xfer)
113 {
114 ggp_edisc_xfer *edisc_xfer = purple_xfer_get_protocol_data(xfer);
115
116 if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND) {
117 purple_debug_error("gg", "ggp_edisc_xfer_init: "
118 "Not yet implemented\n");
119 return;
120 }
121
122 ggp_ggdrive_auth(edisc_xfer->gc, ggp_edisc_xfer_init_authenticated, xfer);
123 }
124
125 static void ggp_edisc_xfer_init_authenticated(PurpleConnection *gc,
126 gboolean success, gpointer _xfer)
127 {
128 PurpleXfer *xfer = _xfer;
129
130 if (!success) {
131 ggp_edisc_xfer_error(xfer, _("Authentication failed"));
132 return;
133 }
134
135 /* TODO: requesting a ticket */
136
137 purple_xfer_start(xfer, -1, NULL, 0);
138 }
139
140 static void ggp_edisc_xfer_start(PurpleXfer *xfer)
141 {
142 g_return_if_fail(xfer != NULL);
143
144 if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND) {
145 purple_debug_error("gg", "ggp_edisc_xfer_start: "
146 "Not yet implemented\n");
147 return;
148 }
149
150 purple_debug_info("gg", "Starting a file transfer...\n");
151 }
152
153 PurpleXfer * ggp_edisc_xfer_new(PurpleConnection *gc, const char *who)
154 {
155 PurpleXfer *xfer;
156 ggp_edisc_xfer *edisc_xfer;
157
158 g_return_val_if_fail(gc != NULL, NULL);
159 g_return_val_if_fail(who != NULL, NULL);
160
161 xfer = purple_xfer_new(purple_connection_get_account(gc),
162 PURPLE_XFER_SEND, who);
163 edisc_xfer = g_new0(ggp_edisc_xfer, 1);
164 purple_xfer_set_protocol_data(xfer, edisc_xfer);
165
166 edisc_xfer->gc = gc;
167
168 purple_xfer_set_init_fnc(xfer, ggp_edisc_xfer_init);
169 purple_xfer_set_start_fnc(xfer, ggp_edisc_xfer_start);
170
171 //purple_xfer_set_cancel_send_fnc(xfer, bonjour_xfer_cancel_send);
172 //purple_xfer_set_end_fnc(xfer, bonjour_xfer_end);
173
174 return xfer;
175 }
176
177 void ggp_edisc_xfer_send_file(PurpleConnection *gc, const char *who,
178 const char *filename)
179 {
180 PurpleXfer *xfer;
181
182 g_return_if_fail(gc != NULL);
183 g_return_if_fail(who != NULL);
184
185 /* Nothing interesting here, this code is common among prpls.
186 * See ggp_edisc_new_xfer. */
187
188 xfer = ggp_edisc_xfer_new(gc, who);
189 if (filename)
190 purple_xfer_request_accepted(xfer, filename);
191 else
192 purple_xfer_request(xfer);
193 }
194
195 /*******************************************************************************
196 * Authentication
197 ******************************************************************************/
198
199 struct _ggp_edisc_auth_data
200 {
201 ggp_ggdrive_auth_cb cb;
202 gpointer user_data;
203 };
204
205 static void ggp_ggdrive_auth_done(PurpleHttpConnection *hc,
206 PurpleHttpResponse *response, gpointer user_data);
207
208 static void ggp_ggdrive_auth(PurpleConnection *gc, ggp_ggdrive_auth_cb cb,
209 gpointer user_data)
210 {
211 GGPInfo *accdata = purple_connection_get_protocol_data(gc);
212 ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
213 ggp_edisc_auth_data *auth;
214 const gchar *imtoken;
215 gchar *metadata;
216 PurpleHttpRequest *req;
217
218 imtoken = ggp_get_imtoken(gc);
219 if (!imtoken)
220 {
221 cb(gc, FALSE, user_data);
222 return;
223 }
224
225 if (sdata->auth_done)
226 {
227 cb(gc, sdata->security_token != NULL, user_data);
228 return;
229 }
230
231 auth = g_new0(ggp_edisc_auth_data, 1);
232 auth->cb = cb;
233 auth->user_data = user_data;
234 sdata->auth_pending = g_list_prepend(sdata->auth_pending, auth);
235
236 if (sdata->auth_request)
237 return;
238
239 purple_debug_info("gg", "ggp_ggdrive_auth(gc=%p)\n", gc);
240
241 req = purple_http_request_new("https://drive.mpa.gg.pl/signin");
242 purple_http_request_set_method(req, "PUT");
243
244 /* TODO: defaults (browser name, etc) */
245 purple_http_request_set_max_len(req, GGP_EDISC_RESPONSE_MAX);
246 purple_http_request_set_cookie_jar(req, sdata->cookies);
247
248 metadata = g_strdup_printf("{"
249 "\"id\": \"%032x\", "
250 "\"name\": \"" GGP_EDISC_HOSTNAME "\", "
251 "\"os_version\": \"" GGP_EDISC_OS "\", "
252 "\"client_version\": \"%s\", "
253 "\"type\": \"" GGP_EDISC_TYPE "\"}",
254 g_random_int_range(1, 1 << 16),
255 ggp_libgaduw_version(gc));
256
257 purple_http_request_header_set_printf(req, "Authorization",
258 "IMToken %s", imtoken);
259 purple_http_request_header_set_printf(req, "X-gged-user",
260 "gg/pl:%u", accdata->session->uin);
261 purple_http_request_header_set(req, "X-gged-client-metadata", metadata);
262 purple_http_request_header_set(req, "X-gged-api-version", "6");
263 g_free(metadata);
264
265 sdata->auth_request = purple_http_request(gc, req,
266 ggp_ggdrive_auth_done, NULL);
267 purple_http_request_unref(req);
268 }
269
270 static void ggp_ggdrive_auth_results(PurpleConnection *gc, gboolean success)
271 {
272 ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
273 GList *it;
274
275 purple_debug_info("gg", "ggp_ggdrive_auth_results(gc=%p): %d\n",
276 gc, success);
277
278 it = g_list_first(sdata->auth_pending);
279 while (it) {
280 ggp_edisc_auth_data *auth = it->data;
281 it = g_list_next(it);
282
283 auth->cb(gc, success, auth->user_data);
284 g_free(auth);
285 }
286 g_list_free(sdata->auth_pending);
287 sdata->auth_pending = NULL;
288 sdata->auth_done = TRUE;
289 }
290
291 static void ggp_ggdrive_auth_done(PurpleHttpConnection *hc,
292 PurpleHttpResponse *response, gpointer user_data)
293 {
294 PurpleConnection *gc = purple_http_conn_get_purple_connection(hc);
295 ggp_edisc_session_data *sdata = ggp_edisc_get_sdata(gc);
296
297 sdata->auth_request = NULL;
298
299 if (!purple_http_response_is_successfull(response) ||
300 0 != strcmp(purple_http_response_get_data(response),
301 "{\"result\":{\"status\":0}}")) {
302 ggp_ggdrive_auth_results(gc, FALSE);
303 return;
304 }
305
306 sdata->security_token = g_strdup(purple_http_response_get_header(
307 response, "X-gged-security-token"));
308 if (!sdata->security_token) {
309 ggp_ggdrive_auth_results(gc, FALSE);
310 return;
311 }
312
313 if (purple_debug_is_unsafe())
314 purple_debug_misc("gg", "ggp_ggdrive_auth_done: "
315 "security_token=%s\n", sdata->security_token);
316 ggp_ggdrive_auth_results(gc, TRUE);
317 }

mercurial