Remove useless comparison
[pidgin-git.git] / libpurple / protocols / gg / lib / pubdir.c
blob199da1f1c7f408999bdfe0e3db019c9779799ec7
1 /* $Id$ */
3 /*
4 * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
5 * Dawid Jarosz <dawjar@poczta.onet.pl>
6 * Adam Wysocki <gophi@ekg.chmurka.net>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU Lesser General Public License Version
10 * 2.1 as published by the Free Software Foundation.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
20 * USA.
23 /**
24 * \file pubdir.c
26 * \brief Obsługa katalogu publicznego
29 #include "network.h"
30 #include <ctype.h>
31 #include <errno.h>
32 #include <stdlib.h>
33 #include <string.h>
35 #include "libgadu.h"
37 /**
38 * Rejestruje nowego użytkownika.
40 * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
42 * \param email Adres e-mail
43 * \param password Hasło
44 * \param tokenid Identyfikator tokenu
45 * \param tokenval Zawartość tokenu
46 * \param async Flaga połączenia asynchronicznego
48 * \return Struktura \c gg_http lub \c NULL w przypadku błędu
50 * \ingroup register
52 struct gg_http *gg_register3(const char *email, const char *password,
53 const char *tokenid, const char *tokenval, int async)
55 struct gg_http *h;
56 char *__pwd, *__email, *__tokenid, *__tokenval, *form, *query;
58 if (!email || !password || !tokenid || !tokenval) {
59 gg_debug(GG_DEBUG_MISC, "=> register, NULL parameter\n");
60 errno = EFAULT;
61 return NULL;
64 __pwd = gg_urlencode(password);
65 __email = gg_urlencode(email);
66 __tokenid = gg_urlencode(tokenid);
67 __tokenval = gg_urlencode(tokenval);
69 if (!__pwd || !__email || !__tokenid || !__tokenval) {
70 gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form fields\n");
71 free(__pwd);
72 free(__email);
73 free(__tokenid);
74 free(__tokenval);
75 return NULL;
78 form = gg_saprintf("pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u",
79 __pwd, __email, __tokenid, __tokenval,
80 gg_http_hash("ss", email, password));
82 free(__pwd);
83 free(__email);
84 free(__tokenid);
85 free(__tokenval);
87 if (!form) {
88 gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form query\n");
89 return NULL;
92 gg_debug(GG_DEBUG_MISC, "=> register, %s\n", form);
94 query = gg_saprintf(
95 "Host: " GG_REGISTER_HOST "\r\n"
96 "Content-Type: application/x-www-form-urlencoded\r\n"
97 "User-Agent: " GG_HTTP_USERAGENT "\r\n"
98 "Content-Length: %d\r\n"
99 "Pragma: no-cache\r\n"
100 "\r\n"
101 "%s",
102 (int) strlen(form), form);
104 free(form);
106 if (!query) {
107 gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for query\n");
108 return NULL;
111 if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async,
112 "POST", "/appsvc/fmregister3.asp", query)))
114 gg_debug(GG_DEBUG_MISC, "=> register, gg_http_connect() failed mysteriously\n");
115 free(query);
116 return NULL;
119 h->type = GG_SESSION_REGISTER;
121 free(query);
123 h->callback = gg_pubdir_watch_fd;
124 h->destroy = gg_pubdir_free;
126 if (!async)
127 gg_pubdir_watch_fd(h);
129 return h;
132 #ifdef DOXYGEN
135 * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
137 * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
138 * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
139 * znajdzie się w polu \c error.
141 * \note W rzeczywistości funkcja jest makrem rozwijanym do
142 * \c gg_pubdir_watch_fd().
144 * \param h Struktura połączenia
146 * \return 0 jeśli się powiodło, -1 w przypadku błędu
148 * \ingroup register
150 int gg_register_watch_fd(struct gg_httpd *h)
152 return gg_pubdir_watch_fd(h);
156 * Zwalnia zasoby po operacji.
158 * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
160 * \param h Struktura połączenia
162 * \ingroup register
164 void gg_register_free(struct gg_http *h)
166 return gg_pubdir_free(h);
169 #endif /* DOXYGEN */
172 * Usuwa użytkownika.
174 * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
176 * \param uin Numer Gadu-Gadu
177 * \param password Hasło
178 * \param tokenid Identyfikator tokenu
179 * \param tokenval Zawartość tokenu
180 * \param async Flaga połączenia asynchronicznego
182 * \return Struktura \c gg_http lub \c NULL w przypadku błędu
184 * \ingroup unregister
186 struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async)
188 struct gg_http *h;
189 char *__fmpwd, *__pwd, *__tokenid, *__tokenval, *form, *query;
191 if (!password || !tokenid || !tokenval) {
192 gg_debug(GG_DEBUG_MISC, "=> unregister, NULL parameter\n");
193 errno = EFAULT;
194 return NULL;
197 __pwd = gg_saprintf("%d", rand());
198 __fmpwd = gg_urlencode(password);
199 __tokenid = gg_urlencode(tokenid);
200 __tokenval = gg_urlencode(tokenval);
202 if (!__fmpwd || !__pwd || !__tokenid || !__tokenval) {
203 gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form fields\n");
204 free(__pwd);
205 free(__fmpwd);
206 free(__tokenid);
207 free(__tokenval);
208 return NULL;
211 form = gg_saprintf("fmnumber=%d&fmpwd=%s&delete=1&pwd=%s&"
212 "email=deletedaccount@gadu-gadu.pl&tokenid=%s&tokenval=%s&"
213 "code=%u", uin, __fmpwd, __pwd, __tokenid, __tokenval,
214 gg_http_hash("ss", "deletedaccount@gadu-gadu.pl", __pwd));
216 free(__fmpwd);
217 free(__pwd);
218 free(__tokenid);
219 free(__tokenval);
221 if (!form) {
222 gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form query\n");
223 return NULL;
226 gg_debug(GG_DEBUG_MISC, "=> unregister, %s\n", form);
228 query = gg_saprintf(
229 "Host: " GG_REGISTER_HOST "\r\n"
230 "Content-Type: application/x-www-form-urlencoded\r\n"
231 "User-Agent: " GG_HTTP_USERAGENT "\r\n"
232 "Content-Length: %d\r\n"
233 "Pragma: no-cache\r\n"
234 "\r\n"
235 "%s",
236 (int) strlen(form), form);
238 free(form);
240 if (!query) {
241 gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for query\n");
242 return NULL;
245 if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async,
246 "POST", "/appsvc/fmregister3.asp", query)))
248 gg_debug(GG_DEBUG_MISC, "=> unregister, gg_http_connect() failed mysteriously\n");
249 free(query);
250 return NULL;
253 h->type = GG_SESSION_UNREGISTER;
255 free(query);
257 h->callback = gg_pubdir_watch_fd;
258 h->destroy = gg_pubdir_free;
260 if (!async)
261 gg_pubdir_watch_fd(h);
263 return h;
266 #ifdef DOXYGEN
269 * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
271 * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
272 * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
273 * znajdzie się w polu \c error.
275 * \note W rzeczywistości funkcja jest makrem rozwijanym do
276 * \c gg_pubdir_watch_fd().
278 * \param h Struktura połączenia
280 * \return 0 jeśli się powiodło, -1 w przypadku błędu
282 * \ingroup unregister
284 int gg_unregister_watch_fd(struct gg_httpd *h)
286 return gg_pubdir_watch_fd(h);
290 * Zwalnia zasoby po operacji.
292 * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
294 * \param h Struktura połączenia
296 * \ingroup unregister
298 void gg_unregister_free(struct gg_http *h)
300 return gg_pubdir_free(h);
303 #endif /* DOXYGEN */
306 * Zmienia hasło użytkownika.
308 * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
310 * \param uin Numer Gadu-Gadu
311 * \param email Adres e-mail
312 * \param passwd Obecne hasło
313 * \param newpasswd Nowe hasło
314 * \param tokenid Identyfikator tokenu
315 * \param tokenval Zawartość tokenu
316 * \param async Flaga połączenia asynchronicznego
318 * \return Struktura \c gg_http lub \c NULL w przypadku błędu
320 * \ingroup passwd
322 struct gg_http *gg_change_passwd4(uin_t uin, const char *email,
323 const char *passwd, const char *newpasswd, const char *tokenid,
324 const char *tokenval, int async)
326 struct gg_http *h;
327 char *form, *query, *__email, *__fmpwd, *__pwd, *__tokenid, *__tokenval;
329 if (!uin || !email || !passwd || !newpasswd || !tokenid || !tokenval) {
330 gg_debug(GG_DEBUG_MISC, "=> change, NULL parameter\n");
331 errno = EFAULT;
332 return NULL;
335 __fmpwd = gg_urlencode(passwd);
336 __pwd = gg_urlencode(newpasswd);
337 __email = gg_urlencode(email);
338 __tokenid = gg_urlencode(tokenid);
339 __tokenval = gg_urlencode(tokenval);
341 if (!__fmpwd || !__pwd || !__email || !__tokenid || !__tokenval) {
342 gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n");
343 free(__fmpwd);
344 free(__pwd);
345 free(__email);
346 free(__tokenid);
347 free(__tokenval);
348 return NULL;
351 if (!(form = gg_saprintf("fmnumber=%d&fmpwd=%s&pwd=%s&email=%s&"
352 "tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __email,
353 __tokenid, __tokenval, gg_http_hash("ss", email, newpasswd))))
355 gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n");
356 free(__fmpwd);
357 free(__pwd);
358 free(__email);
359 free(__tokenid);
360 free(__tokenval);
362 return NULL;
365 free(__fmpwd);
366 free(__pwd);
367 free(__email);
368 free(__tokenid);
369 free(__tokenval);
371 gg_debug(GG_DEBUG_MISC, "=> change, %s\n", form);
373 query = gg_saprintf(
374 "Host: " GG_REGISTER_HOST "\r\n"
375 "Content-Type: application/x-www-form-urlencoded\r\n"
376 "User-Agent: " GG_HTTP_USERAGENT "\r\n"
377 "Content-Length: %d\r\n"
378 "Pragma: no-cache\r\n"
379 "\r\n"
380 "%s",
381 (int) strlen(form), form);
383 free(form);
385 if (!query) {
386 gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for query\n");
387 return NULL;
390 if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async,
391 "POST", "/appsvc/fmregister3.asp", query)))
393 gg_debug(GG_DEBUG_MISC, "=> change, gg_http_connect() failed mysteriously\n");
394 free(query);
395 return NULL;
398 h->type = GG_SESSION_PASSWD;
400 free(query);
402 h->callback = gg_pubdir_watch_fd;
403 h->destroy = gg_pubdir_free;
405 if (!async)
406 gg_pubdir_watch_fd(h);
408 return h;
411 #ifdef DOXYGEN
414 * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
416 * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
417 * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
418 * znajdzie się w polu \c error.
420 * \note W rzeczywistości funkcja jest makrem rozwijanym do
421 * \c gg_pubdir_watch_fd().
423 * \param h Struktura połączenia
425 * \return 0 jeśli się powiodło, -1 w przypadku błędu
427 * \ingroup passwd
429 int gg_change_passwd_watch_fd(struct gg_httpd *h)
431 return gg_pubdir_watch_fd(h);
435 * Zwalnia zasoby po operacji.
437 * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
439 * \param h Struktura połączenia
441 * \ingroup passwd
443 void gg_change_passwd_free(struct gg_http *h)
445 return gg_pubdir_free(h);
448 #endif /* DOXYGEN */
451 * Wysyła hasło użytkownika na e-mail.
453 * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
455 * \param uin Numer Gadu-Gadu
456 * \param email Adres e-mail (podany przy rejestracji)
457 * \param tokenid Identyfikator tokenu
458 * \param tokenval Zawartość tokenu
459 * \param async Flaga połączenia asynchronicznego
461 * \return Struktura \c gg_http lub \c NULL w przypadku błędu
463 * \ingroup remind
465 struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async)
467 struct gg_http *h;
468 char *form, *query, *__tokenid, *__tokenval, *__email;
470 if (!tokenid || !tokenval || !email) {
471 gg_debug(GG_DEBUG_MISC, "=> remind, NULL parameter\n");
472 errno = EFAULT;
473 return NULL;
476 __tokenid = gg_urlencode(tokenid);
477 __tokenval = gg_urlencode(tokenval);
478 __email = gg_urlencode(email);
480 if (!__tokenid || !__tokenval || !__email) {
481 gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
482 free(__tokenid);
483 free(__tokenval);
484 free(__email);
485 return NULL;
488 if (!(form = gg_saprintf("userid=%d&code=%u&tokenid=%s&tokenval=%s&"
489 "email=%s", uin, gg_http_hash("u", uin), __tokenid, __tokenval,
490 __email)))
492 gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
493 free(__tokenid);
494 free(__tokenval);
495 free(__email);
496 return NULL;
499 free(__tokenid);
500 free(__tokenval);
501 free(__email);
503 gg_debug(GG_DEBUG_MISC, "=> remind, %s\n", form);
505 query = gg_saprintf(
506 "Host: " GG_REMIND_HOST "\r\n"
507 "Content-Type: application/x-www-form-urlencoded\r\n"
508 "User-Agent: " GG_HTTP_USERAGENT "\r\n"
509 "Content-Length: %d\r\n"
510 "Pragma: no-cache\r\n"
511 "\r\n"
512 "%s",
513 (int) strlen(form), form);
515 free(form);
517 if (!query) {
518 gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for query\n");
519 return NULL;
522 if (!(h = gg_http_connect(GG_REMIND_HOST, GG_REMIND_PORT, async, "POST", "/appsvc/fmsendpwd3.asp", query))) {
523 gg_debug(GG_DEBUG_MISC, "=> remind, gg_http_connect() failed mysteriously\n");
524 free(query);
525 return NULL;
528 h->type = GG_SESSION_REMIND;
530 free(query);
532 h->callback = gg_pubdir_watch_fd;
533 h->destroy = gg_pubdir_free;
535 if (!async)
536 gg_pubdir_watch_fd(h);
538 return h;
541 #ifdef DOXYGEN
544 * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
546 * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
547 * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
548 * znajdzie się w polu \c error.
550 * \note W rzeczywistości funkcja jest makrem rozwijanym do
551 * \c gg_pubdir_watch_fd().
553 * \param h Struktura połączenia
555 * \return 0 jeśli się powiodło, -1 w przypadku błędu
557 * \ingroup remind
559 int gg_remind_watch_fd(struct gg_httpd *h)
561 return gg_pubdir_watch_fd(h);
565 * Zwalnia zasoby po operacji.
567 * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
569 * \param h Struktura połączenia
571 * \ingroup remind
573 void gg_remind_free(struct gg_http *h)
575 return gg_pubdir_free(h);
578 #endif /* DOXYGEN */
581 * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
583 * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
584 * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
585 * znajdzie się w polu \c error.
587 * \param h Struktura połączenia
589 * \return 0 jeśli się powiodło, -1 w przypadku błędu
591 int gg_pubdir_watch_fd(struct gg_http *h)
593 struct gg_pubdir *p;
594 char *tmp;
596 if (!h) {
597 errno = EFAULT;
598 return -1;
601 if (h->state == GG_STATE_ERROR) {
602 gg_debug(GG_DEBUG_MISC, "=> pubdir, watch_fd issued on failed session\n");
603 errno = EINVAL;
604 return -1;
607 if (h->state != GG_STATE_PARSING) {
608 if (gg_http_watch_fd(h) == -1) {
609 gg_debug(GG_DEBUG_MISC, "=> pubdir, http failure\n");
610 errno = EINVAL;
611 return -1;
615 if (h->state != GG_STATE_PARSING)
616 return 0;
618 h->state = GG_STATE_DONE;
620 if (!(h->data = p = malloc(sizeof(struct gg_pubdir)))) {
621 gg_debug(GG_DEBUG_MISC, "=> pubdir, not enough memory for results\n");
622 return -1;
625 p->success = 0;
626 p->uin = 0;
628 gg_debug(GG_DEBUG_MISC, "=> pubdir, let's parse \"%s\"\n", h->body);
630 if ((tmp = strstr(h->body, "Tokens okregisterreply_packet.reg.dwUserId="))) {
631 p->success = 1;
632 p->uin = strtol(tmp + sizeof("Tokens okregisterreply_packet.reg.dwUserId=") - 1, NULL, 0);
633 p->error = GG_PUBDIR_ERROR_NONE;
634 gg_debug(GG_DEBUG_MISC, "=> pubdir, success (okregisterreply, uin=%d)\n", p->uin);
635 } else if ((tmp = strstr(h->body, "success")) || (tmp = strstr(h->body, "results"))) {
636 p->success = 1;
637 if (tmp[7] == ':')
638 p->uin = strtol(tmp + 8, NULL, 0);
639 p->error = GG_PUBDIR_ERROR_NONE;
640 gg_debug(GG_DEBUG_MISC, "=> pubdir, success (uin=%d)\n", p->uin);
641 } else if (strncmp(h->body, "error1", 6) == 0 || strncmp(h->body, "error3", 6) == 0) {
642 p->error = GG_PUBDIR_ERROR_NEW_PASSWORD;
643 gg_debug(GG_DEBUG_MISC, "=> pubdir, invalid new password\n");
644 } else if (strncmp(h->body, "not authenticated", 17) == 0) {
645 p->error = GG_PUBDIR_ERROR_OLD_PASSWORD;
646 gg_debug(GG_DEBUG_MISC, "=> pubdir, invalid old password\n");
647 } else if (strncmp(h->body, "bad_tokenval", 12) == 0) {
648 p->error = GG_PUBDIR_ERROR_TOKEN;
649 gg_debug(GG_DEBUG_MISC, "=> pubdir, invalid token\n");
650 } else {
651 p->error = GG_PUBDIR_ERROR_OTHER;
652 gg_debug(GG_DEBUG_MISC, "=> pubdir, unknown error\n");
655 return 0;
659 * Zwalnia zasoby po operacji na katalogu publicznym.
661 * \param h Struktura połączenia
663 void gg_pubdir_free(struct gg_http *h)
665 if (!h)
666 return;
668 free(h->data);
669 gg_http_free(h);
673 * Pobiera token do autoryzacji operacji na katalogu publicznym.
675 * Token jest niezbędny do tworzenia nowego i usuwania użytkownika,
676 * zmiany hasła itd.
678 * \param async Flaga połączenia asynchronicznego
680 * \return Struktura \c gg_http lub \c NULL w przypadku błędu
682 * \ingroup token
684 struct gg_http *gg_token(int async)
686 struct gg_http *h;
687 const char *query;
689 query = "Host: " GG_REGISTER_HOST "\r\n"
690 "Content-Type: application/x-www-form-urlencoded\r\n"
691 "User-Agent: " GG_HTTP_USERAGENT "\r\n"
692 "Content-Length: 0\r\n"
693 "Pragma: no-cache\r\n"
694 "\r\n";
696 if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/regtoken.asp", query))) {
697 gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n");
698 return NULL;
701 h->type = GG_SESSION_TOKEN;
703 h->callback = gg_token_watch_fd;
704 h->destroy = gg_token_free;
706 if (!async)
707 gg_token_watch_fd(h);
709 return h;
713 * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
715 * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
716 * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
717 * znajdzie się w polu \c error.
719 * \param h Struktura połączenia
721 * \return 0 jeśli się powiodło, -1 w przypadku błędu
723 * \ingroup token
725 int gg_token_watch_fd(struct gg_http *h)
727 if (!h) {
728 errno = EFAULT;
729 return -1;
732 if (h->state == GG_STATE_ERROR) {
733 gg_debug(GG_DEBUG_MISC, "=> token, watch_fd issued on failed session\n");
734 errno = EINVAL;
735 return -1;
738 if (h->state != GG_STATE_PARSING) {
739 if (gg_http_watch_fd(h) == -1) {
740 gg_debug(GG_DEBUG_MISC, "=> token, http failure\n");
741 errno = EINVAL;
742 return -1;
746 if (h->state != GG_STATE_PARSING)
747 return 0;
749 /* jeśli h->data jest puste, to ściągaliśmy tokenid i url do niego,
750 * ale jeśli coś tam jest, to znaczy, że mamy drugi etap polegający
751 * na pobieraniu tokenu. */
752 if (!h->data) {
753 int width, height, length;
754 char *url = NULL, *tokenid = NULL, *path, *headers;
755 const char *host;
756 struct gg_http *h2;
757 struct gg_token *t;
758 size_t results_len;
760 gg_debug(GG_DEBUG_MISC, "=> token body \"%s\"\n", h->body);
762 results_len = h->body ? strlen(h->body) : 0;
764 if (h->body && (!(url = malloc(results_len)) || !(tokenid = malloc(results_len)))) {
765 gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for results\n");
766 free(url);
767 return -1;
770 if (!h->body || sscanf(h->body, "%d %d %d\r\n%s\r\n%s", &width, &height, &length, tokenid, url) != 5) {
771 gg_debug(GG_DEBUG_MISC, "=> token, parsing failed\n");
772 free(url);
773 free(tokenid);
774 errno = EINVAL;
775 return -1;
778 /* dostaliśmy tokenid i wszystkie niezbędne informacje,
779 * więc pobierzmy obrazek z tokenem */
781 if (strncmp(url, "http://", 7)) {
782 path = gg_saprintf("%s?tokenid=%s", url, tokenid);
783 host = GG_REGISTER_HOST;
784 } else {
785 char *slash = strchr(url + 7, '/');
787 if (slash) {
788 path = gg_saprintf("%s?tokenid=%s", slash, tokenid);
789 *slash = 0;
790 host = url + 7;
791 } else {
792 gg_debug(GG_DEBUG_MISC, "=> token, url parsing failed\n");
793 free(url);
794 free(tokenid);
795 errno = EINVAL;
796 return -1;
800 if (!path) {
801 gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n");
802 free(url);
803 free(tokenid);
804 return -1;
807 if (!(headers = gg_saprintf("Host: %s\r\nUser-Agent: " GG_HTTP_USERAGENT "\r\n\r\n", host))) {
808 gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n");
809 free(path);
810 free(url);
811 free(tokenid);
812 return -1;
815 if (!(h2 = gg_http_connect(host, GG_REGISTER_PORT, h->async, "GET", path, headers))) {
816 gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n");
817 free(headers);
818 free(url);
819 free(path);
820 free(tokenid);
821 return -1;
824 free(headers);
825 free(path);
826 free(url);
828 gg_http_free_fields(h);
830 memcpy(h, h2, sizeof(struct gg_http));
831 free(h2);
833 h->type = GG_SESSION_TOKEN;
835 h->callback = gg_token_watch_fd;
836 h->destroy = gg_token_free;
838 if (!h->async)
839 gg_token_watch_fd(h);
841 if (!(h->data = t = malloc(sizeof(struct gg_token)))) {
842 gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token data\n");
843 free(tokenid);
844 return -1;
847 t->width = width;
848 t->height = height;
849 t->length = length;
850 t->tokenid = tokenid;
851 } else {
852 /* obrazek mamy w h->body */
853 h->state = GG_STATE_DONE;
856 return 0;
860 * Zwalnia zasoby po operacji pobierania tokenu.
862 * \param h Struktura połączenia
864 * \ingroup token
866 void gg_token_free(struct gg_http *h)
868 struct gg_token *t;
870 if (!h)
871 return;
873 if ((t = h->data))
874 free(t->tokenid);
876 free(h->data);
877 gg_http_free(h);
881 * Local variables:
882 * c-indentation-style: k&r
883 * c-basic-offset: 8
884 * indent-tabs-mode: notnil
885 * End:
887 * vim: shiftwidth=8: