1 /* $Id: pubdir.c,v 1.6 2005/08/12 09:49:42 thrulliq Exp $ */
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  */
gg_register3(const char * email,const char * password,const char * tokenid,const char * tokenval,int async)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  */
gg_unregister3(uin_t uin,const char * password,const char * tokenid,const char * tokenval,int async)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  */
gg_change_passwd4(uin_t uin,const char * email,const char * passwd,const char * newpasswd,const char * tokenid,const char * tokenval,int async)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  */
gg_remind_passwd3(uin_t uin,const char * email,const char * tokenid,const char * tokenval,int async)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  */
gg_pubdir_watch_fd(struct gg_http * h)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  */
gg_pubdir_free(struct gg_http * h)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  */
gg_token(int async)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  */
gg_token_watch_fd(struct gg_http * h)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  */
gg_token_free(struct gg_http * h)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  */
685