11360
|
1 /* $Id: common.c 13582 2005-08-28 22:46:01Z boler $ */
|
|
2
|
|
3 /*
|
|
4 * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
|
|
5 * Robert J. Woźny <speedy@ziew.org>
|
|
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 <sys/types.h>
|
|
23 #include <sys/ioctl.h>
|
|
24 #include <sys/socket.h>
|
|
25 #include <netinet/in.h>
|
|
26 #include <arpa/inet.h>
|
|
27 #ifdef sun
|
|
28 # include <sys/filio.h>
|
|
29 #endif
|
|
30
|
|
31 #include <errno.h>
|
|
32 #include <fcntl.h>
|
|
33 #include <netdb.h>
|
|
34 #include <stdarg.h>
|
|
35 #include <stdio.h>
|
|
36 #include <stdlib.h>
|
|
37 #include <string.h>
|
|
38 #include <unistd.h>
|
|
39
|
|
40 #include "libgadu.h"
|
|
41
|
|
42 FILE *gg_debug_file = NULL;
|
|
43
|
|
44 #ifndef GG_DEBUG_DISABLE
|
|
45
|
|
46 /*
|
|
47 * gg_debug() // funkcja wewnętrzna
|
|
48 *
|
|
49 * wyświetla komunikat o danym poziomie, o ile użytkownik sobie tego życzy.
|
|
50 *
|
|
51 * - level - poziom wiadomości
|
|
52 * - format... - treść wiadomości (kompatybilna z printf())
|
|
53 */
|
|
54 void gg_debug(int level, const char *format, ...)
|
|
55 {
|
|
56 va_list ap;
|
|
57 int old_errno = errno;
|
|
58
|
|
59 if (gg_debug_handler) {
|
|
60 va_start(ap, format);
|
|
61 (*gg_debug_handler)(level, format, ap);
|
|
62 va_end(ap);
|
|
63
|
|
64 goto cleanup;
|
|
65 }
|
|
66
|
|
67 if ((gg_debug_level & level)) {
|
|
68 va_start(ap, format);
|
|
69 vfprintf((gg_debug_file) ? gg_debug_file : stderr, format, ap);
|
|
70 va_end(ap);
|
|
71 }
|
|
72
|
|
73 cleanup:
|
|
74 errno = old_errno;
|
|
75 }
|
|
76
|
|
77 #endif
|
|
78
|
|
79 /*
|
|
80 * gg_vsaprintf() // funkcja pomocnicza
|
|
81 *
|
|
82 * robi dokładnie to samo, co vsprintf(), tyle że alokuje sobie wcześniej
|
|
83 * miejsce na dane. powinno działać na tych maszynach, które mają funkcję
|
|
84 * vsnprintf() zgodną z C99, jak i na wcześniejszych.
|
|
85 *
|
|
86 * - format - opis wyświetlanego tekstu jak dla printf()
|
|
87 * - ap - lista argumentów dla printf()
|
|
88 *
|
|
89 * zaalokowany bufor, który należy później zwolnić, lub NULL
|
|
90 * jeśli nie udało się wykonać zadania.
|
|
91 */
|
|
92 char *gg_vsaprintf(const char *format, va_list ap)
|
|
93 {
|
|
94 int size = 0;
|
|
95 const char *start;
|
|
96 char *buf = NULL;
|
|
97
|
|
98 #ifdef __GG_LIBGADU_HAVE_VA_COPY
|
|
99 va_list aq;
|
|
100
|
|
101 va_copy(aq, ap);
|
|
102 #else
|
|
103 # ifdef __GG_LIBGADU_HAVE___VA_COPY
|
|
104 va_list aq;
|
|
105
|
|
106 __va_copy(aq, ap);
|
|
107 # endif
|
|
108 #endif
|
|
109
|
|
110 start = format;
|
|
111
|
|
112 #ifndef __GG_LIBGADU_HAVE_C99_VSNPRINTF
|
|
113 {
|
|
114 int res;
|
|
115 char *tmp;
|
|
116
|
|
117 size = 128;
|
|
118 do {
|
|
119 size *= 2;
|
|
120 if (!(tmp = realloc(buf, size))) {
|
|
121 free(buf);
|
|
122 return NULL;
|
|
123 }
|
|
124 buf = tmp;
|
|
125 res = vsnprintf(buf, size, format, ap);
|
|
126 } while (res == size - 1 || res == -1);
|
|
127 }
|
|
128 #else
|
|
129 {
|
|
130 char tmp[2];
|
|
131
|
|
132 /* libce Solarisa przy buforze NULL zawsze zwracają -1, więc
|
|
133 * musimy podać coś istniejącego jako cel printf()owania. */
|
|
134 size = vsnprintf(tmp, sizeof(tmp), format, ap);
|
|
135 if (!(buf = malloc(size + 1)))
|
|
136 return NULL;
|
|
137 }
|
|
138 #endif
|
|
139
|
|
140 format = start;
|
|
141
|
|
142 #ifdef __GG_LIBGADU_HAVE_VA_COPY
|
|
143 vsnprintf(buf, size + 1, format, aq);
|
|
144 va_end(aq);
|
|
145 #else
|
|
146 # ifdef __GG_LIBGADU_HAVE___VA_COPY
|
|
147 vsnprintf(buf, size + 1, format, aq);
|
|
148 va_end(aq);
|
|
149 # else
|
|
150 vsnprintf(buf, size + 1, format, ap);
|
|
151 # endif
|
|
152 #endif
|
|
153
|
|
154 return buf;
|
|
155 }
|
|
156
|
|
157 /*
|
|
158 * gg_saprintf() // funkcja pomocnicza
|
|
159 *
|
|
160 * robi dokładnie to samo, co sprintf(), tyle że alokuje sobie wcześniej
|
|
161 * miejsce na dane. powinno działać na tych maszynach, które mają funkcję
|
|
162 * vsnprintf() zgodną z C99, jak i na wcześniejszych.
|
|
163 *
|
|
164 * - format... - treść taka sama jak w funkcji printf()
|
|
165 *
|
|
166 * zaalokowany bufor, który należy później zwolnić, lub NULL
|
|
167 * jeśli nie udało się wykonać zadania.
|
|
168 */
|
|
169 char *gg_saprintf(const char *format, ...)
|
|
170 {
|
|
171 va_list ap;
|
|
172 char *res;
|
|
173
|
|
174 va_start(ap, format);
|
|
175 res = gg_vsaprintf(format, ap);
|
|
176 va_end(ap);
|
|
177
|
|
178 return res;
|
|
179 }
|
|
180
|
|
181 /*
|
|
182 * gg_get_line() // funkcja pomocnicza
|
|
183 *
|
|
184 * podaje kolejną linię z bufora tekstowego. niszczy go bezpowrotnie, dzieląc
|
|
185 * na kolejne stringi. zdarza się, nie ma potrzeby pisania funkcji dublującej
|
|
186 * bufor żeby tylko mieć nieruszone dane wejściowe, skoro i tak nie będą nam
|
|
187 * poźniej potrzebne. obcina `\r\n'.
|
|
188 *
|
|
189 * - ptr - wskaźnik do zmiennej, która przechowuje aktualną pozycję
|
|
190 * w przemiatanym buforze
|
|
191 *
|
|
192 * wskaźnik do kolejnej linii tekstu lub NULL, jeśli to już koniec bufora.
|
|
193 */
|
|
194 char *gg_get_line(char **ptr)
|
|
195 {
|
|
196 char *foo, *res;
|
|
197
|
|
198 if (!ptr || !*ptr || !strcmp(*ptr, ""))
|
|
199 return NULL;
|
|
200
|
|
201 res = *ptr;
|
|
202
|
|
203 if (!(foo = strchr(*ptr, '\n')))
|
|
204 *ptr += strlen(*ptr);
|
|
205 else {
|
|
206 *ptr = foo + 1;
|
|
207 *foo = 0;
|
|
208 if (strlen(res) > 1 && res[strlen(res) - 1] == '\r')
|
|
209 res[strlen(res) - 1] = 0;
|
|
210 }
|
|
211
|
|
212 return res;
|
|
213 }
|
|
214
|
|
215 /*
|
|
216 * gg_connect() // funkcja pomocnicza
|
|
217 *
|
|
218 * łączy się z serwerem. pierwszy argument jest typu (void *), żeby nie
|
|
219 * musieć niczego inkludować w libgadu.h i nie psuć jakiś głupich zależności
|
|
220 * na dziwnych systemach.
|
|
221 *
|
|
222 * - addr - adres serwera (struct in_addr *)
|
|
223 * - port - port serwera
|
|
224 * - async - asynchroniczne połączenie
|
|
225 *
|
|
226 * deskryptor gniazda lub -1 w przypadku błędu (kod błędu w zmiennej errno).
|
|
227 */
|
|
228 int gg_connect(void *addr, int port, int async)
|
|
229 {
|
|
230 int sock, one = 1, errno2;
|
|
231 struct sockaddr_in sin;
|
|
232 struct in_addr *a = addr;
|
|
233 struct sockaddr_in myaddr;
|
|
234
|
|
235 gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async);
|
|
236
|
|
237 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
|
|
238 gg_debug(GG_DEBUG_MISC, "// gg_connect() socket() failed (errno=%d, %s)\n", errno, strerror(errno));
|
|
239 return -1;
|
|
240 }
|
|
241
|
|
242 memset(&myaddr, 0, sizeof(myaddr));
|
|
243 myaddr.sin_family = AF_INET;
|
|
244
|
|
245 myaddr.sin_addr.s_addr = gg_local_ip;
|
|
246
|
|
247 if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) {
|
|
248 gg_debug(GG_DEBUG_MISC, "// gg_connect() bind() failed (errno=%d, %s)\n", errno, strerror(errno));
|
|
249 return -1;
|
|
250 }
|
|
251
|
|
252 #ifdef ASSIGN_SOCKETS_TO_THREADS
|
|
253 gg_win32_thread_socket(0, sock);
|
|
254 #endif
|
|
255
|
|
256 if (async) {
|
|
257 #ifdef FIONBIO
|
|
258 if (ioctl(sock, FIONBIO, &one) == -1) {
|
|
259 #else
|
|
260 if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
|
|
261 #endif
|
|
262 gg_debug(GG_DEBUG_MISC, "// gg_connect() ioctl() failed (errno=%d, %s)\n", errno, strerror(errno));
|
|
263 errno2 = errno;
|
|
264 close(sock);
|
|
265 errno = errno2;
|
|
266 return -1;
|
|
267 }
|
|
268 }
|
|
269
|
|
270 sin.sin_port = htons(port);
|
|
271 sin.sin_family = AF_INET;
|
|
272 sin.sin_addr.s_addr = a->s_addr;
|
|
273
|
|
274 if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
|
|
275 if (errno && (!async || errno != EINPROGRESS)) {
|
|
276 gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() failed (errno=%d, %s)\n", errno, strerror(errno));
|
|
277 errno2 = errno;
|
|
278 close(sock);
|
|
279 errno = errno2;
|
|
280 return -1;
|
|
281 }
|
|
282 gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() in progress\n");
|
|
283 }
|
|
284
|
|
285 return sock;
|
|
286 }
|
|
287
|
|
288 /*
|
|
289 * gg_read_line() // funkcja pomocnicza
|
|
290 *
|
|
291 * czyta jedną linię tekstu z gniazda.
|
|
292 *
|
|
293 * - sock - deskryptor gniazda
|
|
294 * - buf - wskaźnik do bufora
|
|
295 * - length - długość bufora
|
|
296 *
|
|
297 * jeśli trafi na błąd odczytu lub podano nieprawidłowe parametry, zwraca NULL.
|
|
298 * inaczej zwraca buf.
|
|
299 */
|
|
300 char *gg_read_line(int sock, char *buf, int length)
|
|
301 {
|
|
302 int ret;
|
|
303
|
|
304 if (!buf || length < 0)
|
|
305 return NULL;
|
|
306
|
|
307 for (; length > 1; buf++, length--) {
|
|
308 do {
|
|
309 if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) {
|
|
310 gg_debug(GG_DEBUG_MISC, "// gg_read_line() error on read (errno=%d, %s)\n", errno, strerror(errno));
|
|
311 *buf = 0;
|
|
312 return NULL;
|
|
313 } else if (ret == 0) {
|
|
314 gg_debug(GG_DEBUG_MISC, "// gg_read_line() eof reached\n");
|
|
315 *buf = 0;
|
|
316 return NULL;
|
|
317 }
|
|
318 } while (ret == -1 && errno == EINTR);
|
|
319
|
|
320 if (*buf == '\n') {
|
|
321 buf++;
|
|
322 break;
|
|
323 }
|
|
324 }
|
|
325
|
|
326 *buf = 0;
|
|
327 return buf;
|
|
328 }
|
|
329
|
|
330 /*
|
|
331 * gg_chomp() // funkcja pomocnicza
|
|
332 *
|
|
333 * ucina "\r\n" lub "\n" z końca linii.
|
|
334 *
|
|
335 * - line - linia do przycięcia
|
|
336 */
|
|
337 void gg_chomp(char *line)
|
|
338 {
|
|
339 int len;
|
|
340
|
|
341 if (!line)
|
|
342 return;
|
|
343
|
|
344 len = strlen(line);
|
|
345
|
|
346 if (len > 0 && line[len - 1] == '\n')
|
|
347 line[--len] = 0;
|
|
348 if (len > 0 && line[len - 1] == '\r')
|
|
349 line[--len] = 0;
|
|
350 }
|
|
351
|
|
352 /*
|
|
353 * gg_urlencode() // funkcja wewnętrzna
|
|
354 *
|
|
355 * zamienia podany tekst na ciąg znaków do formularza http. przydaje się
|
|
356 * przy różnych usługach katalogu publicznego.
|
|
357 *
|
|
358 * - str - ciąg znaków do zakodowania
|
|
359 *
|
|
360 * zaalokowany bufor, który należy później zwolnić albo NULL
|
|
361 * w przypadku błędu.
|
|
362 */
|
|
363 char *gg_urlencode(const char *str)
|
|
364 {
|
|
365 char *q, *buf, hex[] = "0123456789abcdef";
|
|
366 const char *p;
|
|
367 unsigned int size = 0;
|
|
368
|
|
369 if (!str)
|
|
370 str = "";
|
|
371
|
|
372 for (p = str; *p; p++, size++) {
|
|
373 if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == ' ') || (*p == '@') || (*p == '.') || (*p == '-'))
|
|
374 size += 2;
|
|
375 }
|
|
376
|
|
377 if (!(buf = malloc(size + 1)))
|
|
378 return NULL;
|
|
379
|
|
380 for (p = str, q = buf; *p; p++, q++) {
|
|
381 if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || (*p == '@') || (*p == '.') || (*p == '-'))
|
|
382 *q = *p;
|
|
383 else {
|
|
384 if (*p == ' ')
|
|
385 *q = '+';
|
|
386 else {
|
|
387 *q++ = '%';
|
|
388 *q++ = hex[*p >> 4 & 15];
|
|
389 *q = hex[*p & 15];
|
|
390 }
|
|
391 }
|
|
392 }
|
|
393
|
|
394 *q = 0;
|
|
395
|
|
396 return buf;
|
|
397 }
|
|
398
|
|
399 /*
|
|
400 * gg_http_hash() // funkcja wewnętrzna
|
|
401 *
|
|
402 * funkcja licząca hash dla adresu e-mail, hasła i paru innych.
|
|
403 *
|
|
404 * - format... - format kolejnych parametrów ('s' jeśli dany parametr jest
|
|
405 * ciągiem znaków lub 'u' jeśli numerem GG)
|
|
406 *
|
|
407 * hash wykorzystywany przy rejestracji i wszelkich manipulacjach własnego
|
|
408 * wpisu w katalogu publicznym.
|
|
409 */
|
|
410 int gg_http_hash(const char *format, ...)
|
|
411 {
|
|
412 unsigned int a, c, i, j;
|
|
413 va_list ap;
|
|
414 int b = -1;
|
|
415
|
|
416 va_start(ap, format);
|
|
417
|
|
418 for (j = 0; j < strlen(format); j++) {
|
|
419 char *arg, buf[16];
|
|
420
|
|
421 if (format[j] == 'u') {
|
|
422 snprintf(buf, sizeof(buf), "%d", va_arg(ap, uin_t));
|
|
423 arg = buf;
|
|
424 } else {
|
|
425 if (!(arg = va_arg(ap, char*)))
|
|
426 arg = "";
|
|
427 }
|
|
428
|
|
429 i = 0;
|
|
430 while ((c = (unsigned char) arg[i++]) != 0) {
|
|
431 a = (c ^ b) + (c << 8);
|
|
432 b = (a >> 24) | (a << 8);
|
|
433 }
|
|
434 }
|
|
435
|
|
436 va_end(ap);
|
|
437
|
|
438 return (b < 0 ? -b : b);
|
|
439 }
|
|
440
|
|
441 /*
|
|
442 * gg_gethostbyname() // funkcja pomocnicza
|
|
443 *
|
|
444 * odpowiednik gethostbyname() troszczący się o współbieżność, gdy mamy do
|
|
445 * dyspozycji funkcję gethostbyname_r().
|
|
446 *
|
|
447 * - hostname - nazwa serwera
|
|
448 *
|
|
449 * zwraca wskaźnik na strukturę in_addr, którą należy zwolnić.
|
|
450 */
|
|
451 struct in_addr *gg_gethostbyname(const char *hostname)
|
|
452 {
|
|
453 struct in_addr *addr = NULL;
|
|
454
|
|
455 #ifdef HAVE_GETHOSTBYNAME_R
|
|
456 char *tmpbuf = NULL, *buf = NULL;
|
|
457 struct hostent *hp = NULL, *hp2 = NULL;
|
|
458 int h_errnop, ret;
|
|
459 size_t buflen = 1024;
|
|
460 int new_errno;
|
|
461
|
|
462 new_errno = ENOMEM;
|
|
463
|
|
464 if (!(addr = malloc(sizeof(struct in_addr))))
|
|
465 goto cleanup;
|
|
466
|
|
467 if (!(hp = calloc(1, sizeof(*hp))))
|
|
468 goto cleanup;
|
|
469
|
|
470 if (!(buf = malloc(buflen)))
|
|
471 goto cleanup;
|
|
472
|
|
473 tmpbuf = buf;
|
|
474
|
|
475 while ((ret = gethostbyname_r(hostname, hp, buf, buflen, &hp2, &h_errnop)) == ERANGE) {
|
|
476 buflen *= 2;
|
|
477
|
|
478 if (!(tmpbuf = realloc(buf, buflen)))
|
|
479 break;
|
|
480
|
|
481 buf = tmpbuf;
|
|
482 }
|
|
483
|
|
484 if (ret)
|
|
485 new_errno = h_errnop;
|
|
486
|
|
487 if (ret || !hp2 || !tmpbuf)
|
|
488 goto cleanup;
|
|
489
|
|
490 memcpy(addr, hp->h_addr, sizeof(struct in_addr));
|
|
491
|
|
492 free(buf);
|
|
493 free(hp);
|
|
494
|
|
495 return addr;
|
|
496
|
|
497 cleanup:
|
|
498 errno = new_errno;
|
|
499
|
|
500 if (addr)
|
|
501 free(addr);
|
|
502 if (hp)
|
|
503 free(hp);
|
|
504 if (buf)
|
|
505 free(buf);
|
|
506
|
|
507 return NULL;
|
|
508 #else
|
|
509 struct hostent *hp;
|
|
510
|
|
511 if (!(addr = malloc(sizeof(struct in_addr)))) {
|
|
512 goto cleanup;
|
|
513 }
|
|
514
|
|
515 if (!(hp = gethostbyname(hostname)))
|
|
516 goto cleanup;
|
|
517
|
|
518 memcpy(addr, hp->h_addr, sizeof(struct in_addr));
|
|
519
|
|
520 return addr;
|
|
521
|
|
522 cleanup:
|
|
523 if (addr)
|
|
524 free(addr);
|
|
525
|
|
526 return NULL;
|
|
527 #endif
|
|
528 }
|
|
529
|
|
530 #ifdef ASSIGN_SOCKETS_TO_THREADS
|
|
531
|
|
532 typedef struct gg_win32_thread {
|
|
533 int id;
|
|
534 int socket;
|
|
535 struct gg_win32_thread *next;
|
|
536 } gg_win32_thread;
|
|
537
|
|
538 struct gg_win32_thread *gg_win32_threads = 0;
|
|
539
|
|
540 /*
|
|
541 * gg_win32_thread_socket() // funkcja pomocnicza, tylko dla win32
|
|
542 *
|
|
543 * zwraca deskryptor gniazda, które było ostatnio tworzone dla wątku
|
|
544 * o podanym identyfikatorze.
|
|
545 *
|
|
546 * jeśli na win32 przy połączeniach synchronicznych zapamiętamy w jakim
|
|
547 * wątku uruchomiliśmy funkcję, która się z czymkolwiek łączy, to z osobnego
|
|
548 * wątku możemy anulować połączenie poprzez gg_win32_thread_socket(watek, -1);
|
|
549 *
|
|
550 * - thread_id - id wątku. jeśli jest równe 0, brany jest aktualny wątek,
|
|
551 * jeśli równe -1, usuwa wpis o podanym sockecie.
|
|
552 * - socket - deskryptor gniazda. jeśli równe 0, zwraca deskryptor gniazda
|
|
553 * dla podanego wątku, jeśli równe -1, usuwa wpis, jeśli coś
|
|
554 * innego, ustawia dla podanego wątku dany numer deskryptora.
|
|
555 *
|
|
556 * jeśli socket jest równe 0, zwraca deskryptor gniazda dla podanego wątku.
|
|
557 */
|
|
558 int gg_win32_thread_socket(int thread_id, int socket)
|
|
559 {
|
|
560 char close = (thread_id == -1) || socket == -1;
|
|
561 gg_win32_thread *wsk = gg_win32_threads;
|
|
562 gg_win32_thread **p_wsk = &gg_win32_threads;
|
|
563
|
|
564 if (!thread_id)
|
|
565 thread_id = GetCurrentThreadId();
|
|
566
|
|
567 while (wsk) {
|
|
568 if ((thread_id == -1 && wsk->socket == socket) || wsk->id == thread_id) {
|
|
569 if (close) {
|
|
570 /* socket zostaje usuniety */
|
|
571 closesocket(wsk->socket);
|
|
572 *p_wsk = wsk->next;
|
|
573 free(wsk);
|
|
574 return 1;
|
|
575 } else if (!socket) {
|
|
576 /* socket zostaje zwrocony */
|
|
577 return wsk->socket;
|
|
578 } else {
|
|
579 /* socket zostaje ustawiony */
|
|
580 wsk->socket = socket;
|
|
581 return socket;
|
|
582 }
|
|
583 }
|
|
584 p_wsk = &(wsk->next);
|
|
585 wsk = wsk->next;
|
|
586 }
|
|
587
|
|
588 if (close && socket != -1)
|
|
589 closesocket(socket);
|
|
590 if (close || !socket)
|
|
591 return 0;
|
|
592
|
|
593 /* Dodaje nowy element */
|
|
594 wsk = malloc(sizeof(gg_win32_thread));
|
|
595 wsk->id = thread_id;
|
|
596 wsk->socket = socket;
|
|
597 wsk->next = 0;
|
|
598 *p_wsk = wsk;
|
|
599
|
|
600 return socket;
|
|
601 }
|
|
602
|
|
603 #endif /* ASSIGN_SOCKETS_TO_THREADS */
|
|
604
|
|
605 static char gg_base64_charset[] =
|
|
606 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
607
|
|
608 /*
|
|
609 * gg_base64_encode()
|
|
610 *
|
|
611 * zapisuje ciąg znaków w base64.
|
|
612 *
|
|
613 * - buf - ciąg znaków.
|
|
614 *
|
|
615 * zaalokowany bufor.
|
|
616 */
|
|
617 char *gg_base64_encode(const char *buf)
|
|
618 {
|
|
619 char *out, *res;
|
|
620 unsigned int i = 0, j = 0, k = 0, len = strlen(buf);
|
|
621
|
|
622 res = out = malloc((len / 3 + 1) * 4 + 2);
|
|
623
|
|
624 if (!res)
|
|
625 return NULL;
|
|
626
|
|
627 while (j <= len) {
|
|
628 switch (i % 4) {
|
|
629 case 0:
|
|
630 k = (buf[j] & 252) >> 2;
|
|
631 break;
|
|
632 case 1:
|
|
633 if (j < len)
|
|
634 k = ((buf[j] & 3) << 4) | ((buf[j + 1] & 240) >> 4);
|
|
635 else
|
|
636 k = (buf[j] & 3) << 4;
|
|
637
|
|
638 j++;
|
|
639 break;
|
|
640 case 2:
|
|
641 if (j < len)
|
|
642 k = ((buf[j] & 15) << 2) | ((buf[j + 1] & 192) >> 6);
|
|
643 else
|
|
644 k = (buf[j] & 15) << 2;
|
|
645
|
|
646 j++;
|
|
647 break;
|
|
648 case 3:
|
|
649 k = buf[j++] & 63;
|
|
650 break;
|
|
651 }
|
|
652 *out++ = gg_base64_charset[k];
|
|
653 i++;
|
|
654 }
|
|
655
|
|
656 if (i % 4)
|
|
657 for (j = 0; j < 4 - (i % 4); j++, out++)
|
|
658 *out = '=';
|
|
659
|
|
660 *out = 0;
|
|
661
|
|
662 return res;
|
|
663 }
|
|
664
|
|
665 /*
|
|
666 * gg_base64_decode()
|
|
667 *
|
|
668 * dekoduje ciąg znaków z base64.
|
|
669 *
|
|
670 * - buf - ciąg znaków.
|
|
671 *
|
|
672 * zaalokowany bufor.
|
|
673 */
|
|
674 char *gg_base64_decode(const char *buf)
|
|
675 {
|
|
676 char *res, *save, *foo, val;
|
|
677 const char *end;
|
|
678 unsigned int index = 0;
|
|
679
|
|
680 if (!buf)
|
|
681 return NULL;
|
|
682
|
|
683 save = res = calloc(1, (strlen(buf) / 4 + 1) * 3 + 2);
|
|
684
|
|
685 if (!save)
|
|
686 return NULL;
|
|
687
|
|
688 end = buf + strlen(buf);
|
|
689
|
|
690 while (*buf && buf < end) {
|
|
691 if (*buf == '\r' || *buf == '\n') {
|
|
692 buf++;
|
|
693 continue;
|
|
694 }
|
|
695 if (!(foo = strchr(gg_base64_charset, *buf)))
|
|
696 foo = gg_base64_charset;
|
|
697 val = (int)(foo - gg_base64_charset);
|
|
698 buf++;
|
|
699 switch (index) {
|
|
700 case 0:
|
|
701 *res |= val << 2;
|
|
702 break;
|
|
703 case 1:
|
|
704 *res++ |= val >> 4;
|
|
705 *res |= val << 4;
|
|
706 break;
|
|
707 case 2:
|
|
708 *res++ |= val >> 2;
|
|
709 *res |= val << 6;
|
|
710 break;
|
|
711 case 3:
|
|
712 *res++ |= val;
|
|
713 break;
|
|
714 }
|
|
715 index++;
|
|
716 index %= 4;
|
|
717 }
|
|
718 *res = 0;
|
|
719
|
|
720 return save;
|
|
721 }
|
|
722
|
|
723 /*
|
|
724 * gg_proxy_auth() // funkcja wewnętrzna
|
|
725 *
|
|
726 * tworzy nagłówek autoryzacji dla proxy.
|
|
727 *
|
|
728 * zaalokowany tekst lub NULL, jeśli proxy nie jest włączone lub nie wymaga
|
|
729 * autoryzacji.
|
|
730 */
|
|
731 char *gg_proxy_auth()
|
|
732 {
|
|
733 char *tmp, *enc, *out;
|
|
734 unsigned int tmp_size;
|
|
735
|
|
736 if (!gg_proxy_enabled || !gg_proxy_username || !gg_proxy_password)
|
|
737 return NULL;
|
|
738
|
|
739 if (!(tmp = malloc((tmp_size = strlen(gg_proxy_username) + strlen(gg_proxy_password) + 2))))
|
|
740 return NULL;
|
|
741
|
|
742 snprintf(tmp, tmp_size, "%s:%s", gg_proxy_username, gg_proxy_password);
|
|
743
|
|
744 if (!(enc = gg_base64_encode(tmp))) {
|
|
745 free(tmp);
|
|
746 return NULL;
|
|
747 }
|
|
748
|
|
749 free(tmp);
|
|
750
|
|
751 if (!(out = malloc(strlen(enc) + 40))) {
|
|
752 free(enc);
|
|
753 return NULL;
|
|
754 }
|
|
755
|
|
756 snprintf(out, strlen(enc) + 40, "Proxy-Authorization: Basic %s\r\n", enc);
|
|
757
|
|
758 free(enc);
|
|
759
|
|
760 return out;
|
|
761 }
|
|
762
|
|
763 static uint32_t gg_crc32_table[256];
|
|
764 static int gg_crc32_initialized = 0;
|
|
765
|
|
766 /*
|
|
767 * gg_crc32_make_table() // funkcja wewnętrzna
|
|
768 */
|
|
769 static void gg_crc32_make_table()
|
|
770 {
|
|
771 uint32_t h = 1;
|
|
772 unsigned int i, j;
|
|
773
|
|
774 memset(gg_crc32_table, 0, sizeof(gg_crc32_table));
|
|
775
|
|
776 for (i = 128; i; i >>= 1) {
|
|
777 h = (h >> 1) ^ ((h & 1) ? 0xedb88320L : 0);
|
|
778
|
|
779 for (j = 0; j < 256; j += 2 * i)
|
|
780 gg_crc32_table[i + j] = gg_crc32_table[j] ^ h;
|
|
781 }
|
|
782
|
|
783 gg_crc32_initialized = 1;
|
|
784 }
|
|
785
|
|
786 /*
|
|
787 * gg_crc32()
|
|
788 *
|
|
789 * wyznacza sumę kontrolną CRC32 danego bloku danych.
|
|
790 *
|
|
791 * - crc - suma kontrola poprzedniego bloku danych lub 0 jeśli pierwszy
|
|
792 * - buf - bufor danych
|
|
793 * - size - ilość danych
|
|
794 *
|
|
795 * suma kontrolna CRC32.
|
|
796 */
|
|
797 uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len)
|
|
798 {
|
|
799 if (!gg_crc32_initialized)
|
|
800 gg_crc32_make_table();
|
|
801
|
|
802 if (!buf || len < 0)
|
|
803 return crc;
|
|
804
|
|
805 crc ^= 0xffffffffL;
|
|
806
|
|
807 while (len--)
|
|
808 crc = (crc >> 8) ^ gg_crc32_table[(crc ^ *buf++) & 0xff];
|
|
809
|
|
810 return crc ^ 0xffffffffL;
|
|
811 }
|
|
812
|
|
813
|
|
814 /*
|
|
815 * Local variables:
|
|
816 * c-indentation-style: k&r
|
|
817 * c-basic-offset: 8
|
|
818 * indent-tabs-mode: notnil
|
|
819 * End:
|
|
820 *
|
|
821 * vim: shiftwidth=8:
|
|
822 */
|