| |
1 /* $Id: pubdir.c 16856 2006-08-19 01:13:25Z evands $ */ |
| |
2 |
| |
3 /* |
| |
4 * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> |
| |
5 * Dawid Jarosz <dawjar@poczta.onet.pl> |
| |
6 * |
| |
7 * This program is free software; you can redistribute it and/or modify |
| |
8 * it under the terms of the GNU Lesser General Public License Version |
| |
9 * 2.1 as published by the Free Software Foundation. |
| |
10 * |
| |
11 * This program is distributed in the hope that it will be useful, |
| |
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| |
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| |
14 * GNU Lesser General Public License for more details. |
| |
15 * |
| |
16 * You should have received a copy of the GNU Lesser General Public |
| |
17 * License along with this program; if not, write to the Free Software |
| |
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, |
| |
19 * USA. |
| |
20 */ |
| |
21 |
| |
22 #include <ctype.h> |
| |
23 #include <errno.h> |
| |
24 #include <stdarg.h> |
| |
25 #include <stdio.h> |
| |
26 #include <stdlib.h> |
| |
27 #include <string.h> |
| |
28 #include <unistd.h> |
| |
29 |
| |
30 #include "libgadu.h" |
| |
31 |
| |
32 /* |
| |
33 * gg_register3() |
| |
34 * |
| |
35 * rozpoczyna rejestrację użytkownika protokołem GG 6.0. wymaga wcześniejszego |
| |
36 * pobrania tokenu za pomocą funkcji gg_token(). |
| |
37 * |
| |
38 * - email - adres e-mail klienta |
| |
39 * - password - hasło klienta |
| |
40 * - tokenid - identyfikator tokenu |
| |
41 * - tokenval - wartość tokenu |
| |
42 * - async - połączenie asynchroniczne |
| |
43 * |
| |
44 * zaalokowana struct gg_http, którą poźniej należy zwolnić |
| |
45 * funkcją gg_register_free(), albo NULL jeśli wystąpił błąd. |
| |
46 */ |
| |
47 struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async) |
| |
48 { |
| |
49 struct gg_http *h; |
| |
50 char *__pwd, *__email, *__tokenid, *__tokenval, *form, *query; |
| |
51 |
| |
52 if (!email || !password || !tokenid || !tokenval) { |
| |
53 gg_debug(GG_DEBUG_MISC, "=> register, NULL parameter\n"); |
| |
54 errno = EFAULT; |
| |
55 return NULL; |
| |
56 } |
| |
57 |
| |
58 __pwd = gg_urlencode(password); |
| |
59 __email = gg_urlencode(email); |
| |
60 __tokenid = gg_urlencode(tokenid); |
| |
61 __tokenval = gg_urlencode(tokenval); |
| |
62 |
| |
63 if (!__pwd || !__email || !__tokenid || !__tokenval) { |
| |
64 gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form fields\n"); |
| |
65 free(__pwd); |
| |
66 free(__email); |
| |
67 free(__tokenid); |
| |
68 free(__tokenval); |
| |
69 return NULL; |
| |
70 } |
| |
71 |
| |
72 form = gg_saprintf("pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u", |
| |
73 __pwd, __email, __tokenid, __tokenval, |
| |
74 gg_http_hash("ss", email, password)); |
| |
75 |
| |
76 free(__pwd); |
| |
77 free(__email); |
| |
78 free(__tokenid); |
| |
79 free(__tokenval); |
| |
80 |
| |
81 if (!form) { |
| |
82 gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form query\n"); |
| |
83 return NULL; |
| |
84 } |
| |
85 |
| |
86 gg_debug(GG_DEBUG_MISC, "=> register, %s\n", form); |
| |
87 |
| |
88 query = gg_saprintf( |
| |
89 "Host: " GG_REGISTER_HOST "\r\n" |
| |
90 "Content-Type: application/x-www-form-urlencoded\r\n" |
| |
91 "User-Agent: " GG_HTTP_USERAGENT "\r\n" |
| |
92 "Content-Length: %d\r\n" |
| |
93 "Pragma: no-cache\r\n" |
| |
94 "\r\n" |
| |
95 "%s", |
| |
96 (int) strlen(form), form); |
| |
97 |
| |
98 free(form); |
| |
99 |
| |
100 if (!query) { |
| |
101 gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for query\n"); |
| |
102 return NULL; |
| |
103 } |
| |
104 |
| |
105 if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { |
| |
106 gg_debug(GG_DEBUG_MISC, "=> register, gg_http_connect() failed mysteriously\n"); |
| |
107 free(query); |
| |
108 return NULL; |
| |
109 } |
| |
110 |
| |
111 h->type = GG_SESSION_REGISTER; |
| |
112 |
| |
113 free(query); |
| |
114 |
| |
115 h->callback = gg_pubdir_watch_fd; |
| |
116 h->destroy = gg_pubdir_free; |
| |
117 |
| |
118 if (!async) |
| |
119 gg_pubdir_watch_fd(h); |
| |
120 |
| |
121 return h; |
| |
122 } |
| |
123 |
| |
124 /* |
| |
125 * gg_unregister3() |
| |
126 * |
| |
127 * usuwa konto użytkownika z serwera protokołem GG 6.0 |
| |
128 * |
| |
129 * - uin - numerek GG |
| |
130 * - password - hasło klienta |
| |
131 * - tokenid - identyfikator tokenu |
| |
132 * - tokenval - wartość tokenu |
| |
133 * - async - połączenie asynchroniczne |
| |
134 * |
| |
135 * zaalokowana struct gg_http, którą poźniej należy zwolnić |
| |
136 * funkcją gg_unregister_free(), albo NULL jeśli wystąpił błąd. |
| |
137 */ |
| |
138 struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async) |
| |
139 { |
| |
140 struct gg_http *h; |
| |
141 char *__fmpwd, *__pwd, *__tokenid, *__tokenval, *form, *query; |
| |
142 |
| |
143 if (!password || !tokenid || !tokenval) { |
| |
144 gg_debug(GG_DEBUG_MISC, "=> unregister, NULL parameter\n"); |
| |
145 errno = EFAULT; |
| |
146 return NULL; |
| |
147 } |
| |
148 |
| |
149 __pwd = gg_saprintf("%ld", random()); |
| |
150 __fmpwd = gg_urlencode(password); |
| |
151 __tokenid = gg_urlencode(tokenid); |
| |
152 __tokenval = gg_urlencode(tokenval); |
| |
153 |
| |
154 if (!__fmpwd || !__pwd || !__tokenid || !__tokenval) { |
| |
155 gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form fields\n"); |
| |
156 free(__pwd); |
| |
157 free(__fmpwd); |
| |
158 free(__tokenid); |
| |
159 free(__tokenval); |
| |
160 return NULL; |
| |
161 } |
| |
162 |
| |
163 form = gg_saprintf("fmnumber=%d&fmpwd=%s&delete=1&pwd=%s&email=deletedaccount@gadu-gadu.pl&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __tokenid, __tokenval, gg_http_hash("ss", "deletedaccount@gadu-gadu.pl", __pwd)); |
| |
164 |
| |
165 free(__fmpwd); |
| |
166 free(__pwd); |
| |
167 free(__tokenid); |
| |
168 free(__tokenval); |
| |
169 |
| |
170 if (!form) { |
| |
171 gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form query\n"); |
| |
172 return NULL; |
| |
173 } |
| |
174 |
| |
175 gg_debug(GG_DEBUG_MISC, "=> unregister, %s\n", form); |
| |
176 |
| |
177 query = gg_saprintf( |
| |
178 "Host: " GG_REGISTER_HOST "\r\n" |
| |
179 "Content-Type: application/x-www-form-urlencoded\r\n" |
| |
180 "User-Agent: " GG_HTTP_USERAGENT "\r\n" |
| |
181 "Content-Length: %d\r\n" |
| |
182 "Pragma: no-cache\r\n" |
| |
183 "\r\n" |
| |
184 "%s", |
| |
185 (int) strlen(form), form); |
| |
186 |
| |
187 free(form); |
| |
188 |
| |
189 if (!query) { |
| |
190 gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for query\n"); |
| |
191 return NULL; |
| |
192 } |
| |
193 |
| |
194 if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { |
| |
195 gg_debug(GG_DEBUG_MISC, "=> unregister, gg_http_connect() failed mysteriously\n"); |
| |
196 free(query); |
| |
197 return NULL; |
| |
198 } |
| |
199 |
| |
200 h->type = GG_SESSION_UNREGISTER; |
| |
201 |
| |
202 free(query); |
| |
203 |
| |
204 h->callback = gg_pubdir_watch_fd; |
| |
205 h->destroy = gg_pubdir_free; |
| |
206 |
| |
207 if (!async) |
| |
208 gg_pubdir_watch_fd(h); |
| |
209 |
| |
210 return h; |
| |
211 } |
| |
212 |
| |
213 /* |
| |
214 * gg_change_passwd4() |
| |
215 * |
| |
216 * wysyła żądanie zmiany hasła zgodnie z protokołem GG 6.0. wymaga |
| |
217 * wcześniejszego pobrania tokenu za pomocą funkcji gg_token(). |
| |
218 * |
| |
219 * - uin - numer |
| |
220 * - email - adres e-mail |
| |
221 * - passwd - stare hasło |
| |
222 * - newpasswd - nowe hasło |
| |
223 * - tokenid - identyfikator tokenu |
| |
224 * - tokenval - wartość tokenu |
| |
225 * - async - połączenie asynchroniczne |
| |
226 * |
| |
227 * zaalokowana struct gg_http, którą poźniej należy zwolnić |
| |
228 * funkcją gg_change_passwd_free(), albo NULL jeśli wystąpił błąd. |
| |
229 */ |
| |
230 struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async) |
| |
231 { |
| |
232 struct gg_http *h; |
| |
233 char *form, *query, *__email, *__fmpwd, *__pwd, *__tokenid, *__tokenval; |
| |
234 |
| |
235 if (!uin || !email || !passwd || !newpasswd || !tokenid || !tokenval) { |
| |
236 gg_debug(GG_DEBUG_MISC, "=> change, NULL parameter\n"); |
| |
237 errno = EFAULT; |
| |
238 return NULL; |
| |
239 } |
| |
240 |
| |
241 __fmpwd = gg_urlencode(passwd); |
| |
242 __pwd = gg_urlencode(newpasswd); |
| |
243 __email = gg_urlencode(email); |
| |
244 __tokenid = gg_urlencode(tokenid); |
| |
245 __tokenval = gg_urlencode(tokenval); |
| |
246 |
| |
247 if (!__fmpwd || !__pwd || !__email || !__tokenid || !__tokenval) { |
| |
248 gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n"); |
| |
249 free(__fmpwd); |
| |
250 free(__pwd); |
| |
251 free(__email); |
| |
252 free(__tokenid); |
| |
253 free(__tokenval); |
| |
254 return NULL; |
| |
255 } |
| |
256 |
| |
257 if (!(form = gg_saprintf("fmnumber=%d&fmpwd=%s&pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __email, __tokenid, __tokenval, gg_http_hash("ss", email, newpasswd)))) { |
| |
258 gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n"); |
| |
259 free(__fmpwd); |
| |
260 free(__pwd); |
| |
261 free(__email); |
| |
262 free(__tokenid); |
| |
263 free(__tokenval); |
| |
264 |
| |
265 return NULL; |
| |
266 } |
| |
267 |
| |
268 free(__fmpwd); |
| |
269 free(__pwd); |
| |
270 free(__email); |
| |
271 free(__tokenid); |
| |
272 free(__tokenval); |
| |
273 |
| |
274 gg_debug(GG_DEBUG_MISC, "=> change, %s\n", form); |
| |
275 |
| |
276 query = gg_saprintf( |
| |
277 "Host: " GG_REGISTER_HOST "\r\n" |
| |
278 "Content-Type: application/x-www-form-urlencoded\r\n" |
| |
279 "User-Agent: " GG_HTTP_USERAGENT "\r\n" |
| |
280 "Content-Length: %d\r\n" |
| |
281 "Pragma: no-cache\r\n" |
| |
282 "\r\n" |
| |
283 "%s", |
| |
284 (int) strlen(form), form); |
| |
285 |
| |
286 free(form); |
| |
287 |
| |
288 if (!query) { |
| |
289 gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for query\n"); |
| |
290 return NULL; |
| |
291 } |
| |
292 |
| |
293 if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) { |
| |
294 gg_debug(GG_DEBUG_MISC, "=> change, gg_http_connect() failed mysteriously\n"); |
| |
295 free(query); |
| |
296 return NULL; |
| |
297 } |
| |
298 |
| |
299 h->type = GG_SESSION_PASSWD; |
| |
300 |
| |
301 free(query); |
| |
302 |
| |
303 h->callback = gg_pubdir_watch_fd; |
| |
304 h->destroy = gg_pubdir_free; |
| |
305 |
| |
306 if (!async) |
| |
307 gg_pubdir_watch_fd(h); |
| |
308 |
| |
309 return h; |
| |
310 } |
| |
311 |
| |
312 /* |
| |
313 * gg_remind_passwd3() |
| |
314 * |
| |
315 * wysyła żądanie przypomnienia hasła e-mailem. |
| |
316 * |
| |
317 * - uin - numer |
| |
318 * - email - adres e-mail taki, jak ten zapisany na serwerze |
| |
319 * - async - połączenie asynchroniczne |
| |
320 * - tokenid - identyfikator tokenu |
| |
321 * - tokenval - wartość tokenu |
| |
322 * |
| |
323 * zaalokowana struct gg_http, którą poźniej należy zwolnić |
| |
324 * funkcją gg_remind_passwd_free(), albo NULL jeśli wystąpił błąd. |
| |
325 */ |
| |
326 struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async) |
| |
327 { |
| |
328 struct gg_http *h; |
| |
329 char *form, *query, *__tokenid, *__tokenval, *__email; |
| |
330 |
| |
331 if (!tokenid || !tokenval || !email) { |
| |
332 gg_debug(GG_DEBUG_MISC, "=> remind, NULL parameter\n"); |
| |
333 errno = EFAULT; |
| |
334 return NULL; |
| |
335 } |
| |
336 |
| |
337 __tokenid = gg_urlencode(tokenid); |
| |
338 __tokenval = gg_urlencode(tokenval); |
| |
339 __email = gg_urlencode(email); |
| |
340 |
| |
341 if (!__tokenid || !__tokenval || !__email) { |
| |
342 gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n"); |
| |
343 free(__tokenid); |
| |
344 free(__tokenval); |
| |
345 free(__email); |
| |
346 return NULL; |
| |
347 } |
| |
348 |
| |
349 if (!(form = gg_saprintf("userid=%d&code=%u&tokenid=%s&tokenval=%s&email=%s", uin, gg_http_hash("u", uin), __tokenid, __tokenval, __email))) { |
| |
350 gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n"); |
| |
351 free(__tokenid); |
| |
352 free(__tokenval); |
| |
353 free(__email); |
| |
354 return NULL; |
| |
355 } |
| |
356 |
| |
357 free(__tokenid); |
| |
358 free(__tokenval); |
| |
359 free(__email); |
| |
360 |
| |
361 gg_debug(GG_DEBUG_MISC, "=> remind, %s\n", form); |
| |
362 |
| |
363 query = gg_saprintf( |
| |
364 "Host: " GG_REMIND_HOST "\r\n" |
| |
365 "Content-Type: application/x-www-form-urlencoded\r\n" |
| |
366 "User-Agent: " GG_HTTP_USERAGENT "\r\n" |
| |
367 "Content-Length: %d\r\n" |
| |
368 "Pragma: no-cache\r\n" |
| |
369 "\r\n" |
| |
370 "%s", |
| |
371 (int) strlen(form), form); |
| |
372 |
| |
373 free(form); |
| |
374 |
| |
375 if (!query) { |
| |
376 gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for query\n"); |
| |
377 return NULL; |
| |
378 } |
| |
379 |
| |
380 if (!(h = gg_http_connect(GG_REMIND_HOST, GG_REMIND_PORT, async, "POST", "/appsvc/fmsendpwd3.asp", query))) { |
| |
381 gg_debug(GG_DEBUG_MISC, "=> remind, gg_http_connect() failed mysteriously\n"); |
| |
382 free(query); |
| |
383 return NULL; |
| |
384 } |
| |
385 |
| |
386 h->type = GG_SESSION_REMIND; |
| |
387 |
| |
388 free(query); |
| |
389 |
| |
390 h->callback = gg_pubdir_watch_fd; |
| |
391 h->destroy = gg_pubdir_free; |
| |
392 |
| |
393 if (!async) |
| |
394 gg_pubdir_watch_fd(h); |
| |
395 |
| |
396 return h; |
| |
397 } |
| |
398 |
| |
399 /* |
| |
400 * gg_pubdir_watch_fd() |
| |
401 * |
| |
402 * przy asynchronicznych operacjach na katalogu publicznym należy wywoływać |
| |
403 * tę funkcję przy zmianach na obserwowanym deskryptorze. |
| |
404 * |
| |
405 * - h - struktura opisująca połączenie |
| |
406 * |
| |
407 * jeśli wszystko poszło dobrze to 0, inaczej -1. operacja będzie |
| |
408 * zakończona, jeśli h->state == GG_STATE_DONE. jeśli wystąpi jakiś |
| |
409 * błąd, to będzie tam GG_STATE_ERROR i odpowiedni kod błędu w h->error. |
| |
410 */ |
| |
411 int gg_pubdir_watch_fd(struct gg_http *h) |
| |
412 { |
| |
413 struct gg_pubdir *p; |
| |
414 char *tmp; |
| |
415 |
| |
416 if (!h) { |
| |
417 errno = EFAULT; |
| |
418 return -1; |
| |
419 } |
| |
420 |
| |
421 if (h->state == GG_STATE_ERROR) { |
| |
422 gg_debug(GG_DEBUG_MISC, "=> pubdir, watch_fd issued on failed session\n"); |
| |
423 errno = EINVAL; |
| |
424 return -1; |
| |
425 } |
| |
426 |
| |
427 if (h->state != GG_STATE_PARSING) { |
| |
428 if (gg_http_watch_fd(h) == -1) { |
| |
429 gg_debug(GG_DEBUG_MISC, "=> pubdir, http failure\n"); |
| |
430 errno = EINVAL; |
| |
431 return -1; |
| |
432 } |
| |
433 } |
| |
434 |
| |
435 if (h->state != GG_STATE_PARSING) |
| |
436 return 0; |
| |
437 |
| |
438 h->state = GG_STATE_DONE; |
| |
439 |
| |
440 if (!(h->data = p = malloc(sizeof(struct gg_pubdir)))) { |
| |
441 gg_debug(GG_DEBUG_MISC, "=> pubdir, not enough memory for results\n"); |
| |
442 return -1; |
| |
443 } |
| |
444 |
| |
445 p->success = 0; |
| |
446 p->uin = 0; |
| |
447 |
| |
448 gg_debug(GG_DEBUG_MISC, "=> pubdir, let's parse \"%s\"\n", h->body); |
| |
449 |
| |
450 if ((tmp = strstr(h->body, "success")) || (tmp = strstr(h->body, "results"))) { |
| |
451 p->success = 1; |
| |
452 if (tmp[7] == ':') |
| |
453 p->uin = strtol(tmp + 8, NULL, 0); |
| |
454 gg_debug(GG_DEBUG_MISC, "=> pubdir, success (uin=%d)\n", p->uin); |
| |
455 } else |
| |
456 gg_debug(GG_DEBUG_MISC, "=> pubdir, error.\n"); |
| |
457 |
| |
458 return 0; |
| |
459 } |
| |
460 |
| |
461 /* |
| |
462 * gg_pubdir_free() |
| |
463 * |
| |
464 * zwalnia pamięć po efektach operacji na katalogu publicznym. |
| |
465 * |
| |
466 * - h - zwalniana struktura |
| |
467 */ |
| |
468 void gg_pubdir_free(struct gg_http *h) |
| |
469 { |
| |
470 if (!h) |
| |
471 return; |
| |
472 |
| |
473 free(h->data); |
| |
474 gg_http_free(h); |
| |
475 } |
| |
476 |
| |
477 /* |
| |
478 * gg_token() |
| |
479 * |
| |
480 * pobiera z serwera token do autoryzacji zakładania konta, usuwania |
| |
481 * konta i zmiany hasła. |
| |
482 * |
| |
483 * zaalokowana struct gg_http, którą poźniej należy zwolnić |
| |
484 * funkcją gg_token_free(), albo NULL jeśli wystąpił błąd. |
| |
485 */ |
| |
486 struct gg_http *gg_token(int async) |
| |
487 { |
| |
488 struct gg_http *h; |
| |
489 const char *query; |
| |
490 |
| |
491 query = "Host: " GG_REGISTER_HOST "\r\n" |
| |
492 "Content-Type: application/x-www-form-urlencoded\r\n" |
| |
493 "User-Agent: " GG_HTTP_USERAGENT "\r\n" |
| |
494 "Content-Length: 0\r\n" |
| |
495 "Pragma: no-cache\r\n" |
| |
496 "\r\n"; |
| |
497 |
| |
498 if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/regtoken.asp", query))) { |
| |
499 gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n"); |
| |
500 return NULL; |
| |
501 } |
| |
502 |
| |
503 h->type = GG_SESSION_TOKEN; |
| |
504 |
| |
505 h->callback = gg_token_watch_fd; |
| |
506 h->destroy = gg_token_free; |
| |
507 |
| |
508 if (!async) |
| |
509 gg_token_watch_fd(h); |
| |
510 |
| |
511 return h; |
| |
512 } |
| |
513 |
| |
514 /* |
| |
515 * gg_token_watch_fd() |
| |
516 * |
| |
517 * przy asynchronicznych operacjach związanych z tokenem należy wywoływać |
| |
518 * tę funkcję przy zmianach na obserwowanym deskryptorze. |
| |
519 * |
| |
520 * - h - struktura opisująca połączenie |
| |
521 * |
| |
522 * jeśli wszystko poszło dobrze to 0, inaczej -1. operacja będzie |
| |
523 * zakończona, jeśli h->state == GG_STATE_DONE. jeśli wystąpi jakiś |
| |
524 * błąd, to będzie tam GG_STATE_ERROR i odpowiedni kod błędu w h->error. |
| |
525 */ |
| |
526 int gg_token_watch_fd(struct gg_http *h) |
| |
527 { |
| |
528 if (!h) { |
| |
529 errno = EFAULT; |
| |
530 return -1; |
| |
531 } |
| |
532 |
| |
533 if (h->state == GG_STATE_ERROR) { |
| |
534 gg_debug(GG_DEBUG_MISC, "=> token, watch_fd issued on failed session\n"); |
| |
535 errno = EINVAL; |
| |
536 return -1; |
| |
537 } |
| |
538 |
| |
539 if (h->state != GG_STATE_PARSING) { |
| |
540 if (gg_http_watch_fd(h) == -1) { |
| |
541 gg_debug(GG_DEBUG_MISC, "=> token, http failure\n"); |
| |
542 errno = EINVAL; |
| |
543 return -1; |
| |
544 } |
| |
545 } |
| |
546 |
| |
547 if (h->state != GG_STATE_PARSING) |
| |
548 return 0; |
| |
549 |
| |
550 /* jeśli h->data jest puste, to ściągaliśmy tokenid i url do niego, |
| |
551 * ale jeśli coś tam jest, to znaczy, że mamy drugi etap polegający |
| |
552 * na pobieraniu tokenu. */ |
| |
553 if (!h->data) { |
| |
554 int width, height, length; |
| |
555 char *url = NULL, *tokenid = NULL, *path, *headers; |
| |
556 const char *host; |
| |
557 struct gg_http *h2; |
| |
558 struct gg_token *t; |
| |
559 |
| |
560 gg_debug(GG_DEBUG_MISC, "=> token body \"%s\"\n", h->body); |
| |
561 |
| |
562 if (h->body && (!(url = malloc(strlen(h->body))) || !(tokenid = malloc(strlen(h->body))))) { |
| |
563 gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for results\n"); |
| |
564 free(url); |
| |
565 return -1; |
| |
566 } |
| |
567 |
| |
568 if (!h->body || sscanf(h->body, "%d %d %d\r\n%s\r\n%s", &width, &height, &length, tokenid, url) != 5) { |
| |
569 gg_debug(GG_DEBUG_MISC, "=> token, parsing failed\n"); |
| |
570 free(url); |
| |
571 free(tokenid); |
| |
572 errno = EINVAL; |
| |
573 return -1; |
| |
574 } |
| |
575 |
| |
576 /* dostaliśmy tokenid i wszystkie niezbędne informacje, |
| |
577 * więc pobierzmy obrazek z tokenem */ |
| |
578 |
| |
579 if (strncmp(url, "http://", 7)) { |
| |
580 path = gg_saprintf("%s?tokenid=%s", url, tokenid); |
| |
581 host = GG_REGISTER_HOST; |
| |
582 } else { |
| |
583 char *slash = strchr(url + 7, '/'); |
| |
584 |
| |
585 if (slash) { |
| |
586 path = gg_saprintf("%s?tokenid=%s", slash, tokenid); |
| |
587 *slash = 0; |
| |
588 host = url + 7; |
| |
589 } else { |
| |
590 gg_debug(GG_DEBUG_MISC, "=> token, url parsing failed\n"); |
| |
591 free(url); |
| |
592 free(tokenid); |
| |
593 errno = EINVAL; |
| |
594 return -1; |
| |
595 } |
| |
596 } |
| |
597 |
| |
598 if (!path) { |
| |
599 gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n"); |
| |
600 free(url); |
| |
601 free(tokenid); |
| |
602 return -1; |
| |
603 } |
| |
604 |
| |
605 if (!(headers = gg_saprintf("Host: %s\r\nUser-Agent: " GG_HTTP_USERAGENT "\r\n\r\n", host))) { |
| |
606 gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n"); |
| |
607 free(path); |
| |
608 free(url); |
| |
609 free(tokenid); |
| |
610 return -1; |
| |
611 } |
| |
612 |
| |
613 if (!(h2 = gg_http_connect(host, GG_REGISTER_PORT, h->async, "GET", path, headers))) { |
| |
614 gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n"); |
| |
615 free(headers); |
| |
616 free(url); |
| |
617 free(path); |
| |
618 free(tokenid); |
| |
619 return -1; |
| |
620 } |
| |
621 |
| |
622 free(headers); |
| |
623 free(path); |
| |
624 free(url); |
| |
625 |
| |
626 memcpy(h, h2, sizeof(struct gg_http)); |
| |
627 free(h2); |
| |
628 |
| |
629 h->type = GG_SESSION_TOKEN; |
| |
630 |
| |
631 h->callback = gg_token_watch_fd; |
| |
632 h->destroy = gg_token_free; |
| |
633 |
| |
634 if (!h->async) |
| |
635 gg_token_watch_fd(h); |
| |
636 |
| |
637 if (!(h->data = t = malloc(sizeof(struct gg_token)))) { |
| |
638 gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token data\n"); |
| |
639 free(tokenid); |
| |
640 return -1; |
| |
641 } |
| |
642 |
| |
643 t->width = width; |
| |
644 t->height = height; |
| |
645 t->length = length; |
| |
646 t->tokenid = tokenid; |
| |
647 } else { |
| |
648 /* obrazek mamy w h->body */ |
| |
649 h->state = GG_STATE_DONE; |
| |
650 } |
| |
651 |
| |
652 return 0; |
| |
653 } |
| |
654 |
| |
655 /* |
| |
656 * gg_token_free() |
| |
657 * |
| |
658 * zwalnia pamięć po efektach pobierania tokenu. |
| |
659 * |
| |
660 * - h - zwalniana struktura |
| |
661 */ |
| |
662 void gg_token_free(struct gg_http *h) |
| |
663 { |
| |
664 struct gg_token *t; |
| |
665 |
| |
666 if (!h) |
| |
667 return; |
| |
668 |
| |
669 if ((t = h->data)) |
| |
670 free(t->tokenid); |
| |
671 |
| |
672 free(h->data); |
| |
673 gg_http_free(h); |
| |
674 } |
| |
675 |
| |
676 /* |
| |
677 * Local variables: |
| |
678 * c-indentation-style: k&r |
| |
679 * c-basic-offset: 8 |
| |
680 * indent-tabs-mode: notnil |
| |
681 * End: |
| |
682 * |
| |
683 * vim: shiftwidth=8: |
| |
684 */ |