Mercurial > pidgin
annotate src/protocols/gg/lib/pubdir.c @ 11851:3bfb2cffcef2
[gaim-migrate @ 14142]
inspired by Richard Stellingwerff's patch 1339606, this workaround for
annoying visible borders on tab close buttons is no longer required with
at least gtk 2.6 (if someone can confirm if it was fixed in 2.4 we could
remove it there too)
committer: Tailor Script <tailor@pidgin.im>
| author | Stu Tomlinson <stu@nosnilmot.com> |
|---|---|
| date | Thu, 27 Oct 2005 15:15:52 +0000 |
| parents | 3c536224f0d0 |
| children |
| rev | line source |
|---|---|
|
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
1 /* $Id: pubdir.c 13801 2005-09-14 19:10:39Z datallah $ */ |
| 11360 | 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 } | |
|
11546
3c536224f0d0
[gaim-migrate @ 13801]
Daniel Atallah <daniel.atallah@gmail.com>
parents:
11360
diff
changeset
|
148 |
| 11360 | 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 */ |
