| 1 /* $Id: pubdir.c 13801 2005-09-14 19:10:39Z datallah $ */ |
|
| 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 */ |
|