1 /* $Id: common.c,v 1.3 2004/07/31 10:47:20 konst Exp $ */
4 * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
5 * Robert J. Wo¼ny <speedy@ziew.org>
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.
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.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <sys/types.h>
22 #include <sys/ioctl.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
27 # include <sys/filio.h>
41 FILE *gg_debug_file
= NULL
;
43 #ifndef GG_DEBUG_DISABLE
46 * gg_debug() // funkcja wewnêtrzna
48 * wy¶wietla komunikat o danym poziomie, o ile u¿ytkownik sobie tego ¿yczy.
50 * - level - poziom wiadomo¶ci
51 * - format... - tre¶æ wiadomo¶ci (kompatybilna z printf())
53 void gg_debug(int level
, const char *format
, ...)
56 int old_errno
= errno
;
58 if (gg_debug_handler
) {
60 (*gg_debug_handler
)(level
, format
, ap
);
66 if ((gg_debug_level
& level
)) {
68 vfprintf((gg_debug_file
) ? gg_debug_file
: stderr
, format
, ap
);
79 * gg_vsaprintf() // funkcja pomocnicza
81 * robi dok³adnie to samo, co vsprintf(), tyle ¿e alokuje sobie wcze¶niej
82 * miejsce na dane. powinno dzia³aæ na tych maszynach, które maj± funkcjê
83 * vsnprintf() zgodn± z C99, jak i na wcze¶niejszych.
85 * - format - opis wy¶wietlanego tekstu jak dla printf()
86 * - ap - lista argumentów dla printf()
88 * zaalokowany bufor, który nale¿y pó¼niej zwolniæ, lub NULL
89 * je¶li nie uda³o siê wykonaæ zadania.
91 char *gg_vsaprintf(const char *format
, va_list ap
)
97 #ifdef __GG_LIBGADU_HAVE_VA_COPY
102 # ifdef __GG_LIBGADU_HAVE___VA_COPY
111 #ifndef __GG_LIBGADU_HAVE_C99_VSNPRINTF
119 if (!(tmp
= realloc(buf
, size
))) {
124 res
= vsnprintf(buf
, size
, format
, ap
);
125 } while (res
== size
- 1 || res
== -1);
131 /* libce Solarisa przy buforze NULL zawsze zwracaj± -1, wiêc
132 * musimy podaæ co¶ istniej±cego jako cel printf()owania. */
133 size
= vsnprintf(tmp
, sizeof(tmp
), format
, ap
);
134 if (!(buf
= malloc(size
+ 1)))
141 #ifdef __GG_LIBGADU_HAVE_VA_COPY
142 vsnprintf(buf
, size
+ 1, format
, aq
);
145 # ifdef __GG_LIBGADU_HAVE___VA_COPY
146 vsnprintf(buf
, size
+ 1, format
, aq
);
149 vsnprintf(buf
, size
+ 1, format
, ap
);
157 * gg_saprintf() // funkcja pomocnicza
159 * robi dok³adnie to samo, co sprintf(), tyle ¿e alokuje sobie wcze¶niej
160 * miejsce na dane. powinno dzia³aæ na tych maszynach, które maj± funkcjê
161 * vsnprintf() zgodn± z C99, jak i na wcze¶niejszych.
163 * - format... - tre¶æ taka sama jak w funkcji printf()
165 * zaalokowany bufor, który nale¿y pó¼niej zwolniæ, lub NULL
166 * je¶li nie uda³o siê wykonaæ zadania.
168 char *gg_saprintf(const char *format
, ...)
173 va_start(ap
, format
);
174 res
= gg_vsaprintf(format
, ap
);
181 * gg_get_line() // funkcja pomocnicza
183 * podaje kolejn± liniê z bufora tekstowego. niszczy go bezpowrotnie, dziel±c
184 * na kolejne stringi. zdarza siê, nie ma potrzeby pisania funkcji dubluj±cej
185 * bufor ¿eby tylko mieæ nieruszone dane wej¶ciowe, skoro i tak nie bêd± nam
186 * po¼niej potrzebne. obcina `\r\n'.
188 * - ptr - wska¼nik do zmiennej, która przechowuje aktualn± pozycjê
189 * w przemiatanym buforze
191 * wska¼nik do kolejnej linii tekstu lub NULL, je¶li to ju¿ koniec bufora.
193 char *gg_get_line(char **ptr
)
197 if (!ptr
|| !*ptr
|| !strcmp(*ptr
, ""))
202 if (!(foo
= strchr(*ptr
, '\n')))
203 *ptr
+= strlen(*ptr
);
207 if (strlen(res
) > 1 && res
[strlen(res
) - 1] == '\r')
208 res
[strlen(res
) - 1] = 0;
215 * gg_connect() // funkcja pomocnicza
217 * ³±czy siê z serwerem. pierwszy argument jest typu (void *), ¿eby nie
218 * musieæ niczego inkludowaæ w libgadu.h i nie psuæ jaki¶ g³upich zale¿no¶ci
219 * na dziwnych systemach.
221 * - addr - adres serwera (struct in_addr *)
222 * - port - port serwera
223 * - async - asynchroniczne po³±czenie
225 * deskryptor gniazda lub -1 w przypadku b³êdu (kod b³êdu w zmiennej errno).
227 int gg_connect(void *addr
, int port
, int async
)
230 struct sockaddr_in sin
;
231 struct in_addr
*a
= addr
;
233 gg_debug(GG_DEBUG_FUNCTION
, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a
), port
, async
);
235 if ((sock
= socket(AF_INET
, SOCK_STREAM
, IPPROTO_TCP
)) == -1) {
236 gg_debug(GG_DEBUG_MISC
, "// gg_connect() socket() failed (errno=%d, %s)\n", errno
, strerror(errno
));
240 #ifdef ASSIGN_SOCKETS_TO_THREADS
241 gg_win32_thread_socket(0, sock
);
246 if (ioctl(sock
, FIONBIO
, &one
) == -1) {
248 if (fcntl(sock
, F_SETFL
, O_NONBLOCK
) == -1) {
250 gg_debug(GG_DEBUG_MISC
, "// gg_connect() ioctl() failed (errno=%d, %s)\n", errno
, strerror(errno
));
256 sin
.sin_port
= htons(port
);
257 sin
.sin_family
= AF_INET
;
258 sin
.sin_addr
.s_addr
= a
->s_addr
;
260 if(cw_connect(sock
, (struct sockaddr
*) &sin
, sizeof(sin
), 0) == -1) {
261 if (errno
&& (!async
|| errno
!= EINPROGRESS
)) {
262 gg_debug(GG_DEBUG_MISC
, "// gg_connect() connect() failed (errno=%d, %s)\n", errno
, strerror(errno
));
266 gg_debug(GG_DEBUG_MISC
, "// gg_connect() connect() in progress\n");
273 * gg_read_line() // funkcja pomocnicza
275 * czyta jedn± liniê tekstu z gniazda.
277 * - sock - deskryptor gniazda
278 * - buf - wska¼nik do bufora
279 * - length - d³ugo¶æ bufora
281 * je¶li trafi na b³±d odczytu, zwraca NULL. inaczej zwraca buf.
283 char *gg_read_line(int sock
, char *buf
, int length
)
287 if (!buf
|| length
< 0)
289 for (; length
> 1; buf
++, length
--) {
291 if ((ret
= read(sock
, buf
, 1)) == -1 && errno
!= EINTR
) {
292 gg_debug(GG_DEBUG_MISC
, "// gg_read_line() error on read (errno=%d, %s)\n", errno
, strerror(errno
));
295 } else if (ret
== 0) {
296 gg_debug(GG_DEBUG_MISC
, "// gg_read_line() eof reached\n");
300 } while (ret
== -1 && errno
== EINTR
);
313 * gg_chomp() // funkcja pomocnicza
315 * ucina "\r\n" lub "\n" z koñca linii.
317 * - line - linia do przyciêcia
319 void gg_chomp(char *line
)
321 if (!line
|| strlen(line
) < 1)
324 if (line
[strlen(line
) - 1] == '\n')
325 line
[strlen(line
) - 1] = 0;
326 if (line
[strlen(line
) - 1] == '\r')
327 line
[strlen(line
) - 1] = 0;
331 * gg_urlencode() // funkcja wewnêtrzna
333 * zamienia podany tekst na ci±g znaków do formularza http. przydaje siê
334 * przy ró¿nych us³ugach katalogu publicznego.
336 * - str - ci±g znaków do zakodowania
338 * zaalokowany bufor, który nale¿y pó¼niej zwolniæ albo NULL
341 char *gg_urlencode(const char *str
)
343 char *q
, *buf
, hex
[] = "0123456789abcdef";
345 unsigned int size
= 0;
347 if (!str
&& !(str
= strdup("")))
350 for (p
= str
; *p
; p
++, size
++) {
351 if (!((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z') || (*p
>= '0' && *p
<= '9') || *p
== ' ') || (*p
== '@') || (*p
== '.') || (*p
== '-'))
355 if (!(buf
= malloc(size
+ 1)))
358 for (p
= str
, q
= buf
; *p
; p
++, q
++) {
359 if ((*p
>= 'a' && *p
<= 'z') || (*p
>= 'A' && *p
<= 'Z') || (*p
>= '0' && *p
<= '9') || (*p
== '@') || (*p
== '.') || (*p
== '-'))
366 *q
++ = hex
[*p
>> 4 & 15];
378 * gg_http_hash() // funkcja wewnêtrzna
380 * funkcja licz±ca hash dla adresu e-mail, has³a i paru innych.
382 * - format... - format kolejnych parametrów ('s' je¶li dany parametr jest
383 * ci±giem znaków lub 'u' je¶li numerem GG)
385 * hash wykorzystywany przy rejestracji i wszelkich manipulacjach w³asnego
386 * wpisu w katalogu publicznym.
388 int gg_http_hash(const char *format
, ...)
390 unsigned int a
, c
, i
, j
;
394 va_start(ap
, format
);
396 for (j
= 0; j
< strlen(format
); j
++) {
399 if (format
[j
] == 'u') {
400 snprintf(buf
, sizeof(buf
), "%d", va_arg(ap
, uin_t
));
403 if (!(arg
= va_arg(ap
, char*)))
408 while ((c
= (unsigned char) arg
[i
++]) != 0) {
409 a
= (c
^ b
) + (c
<< 8);
410 b
= (a
>> 24) | (a
<< 8);
416 return (b
< 0 ? -b
: b
);
420 * gg_gethostbyname() // funkcja pomocnicza
422 * odpowiednik gethostbyname() u¿ywaj±cy gethostbyname_r(), gdy potrzebna
423 * jest wielobie¿no¶æ. chwilowo korzysta ze zwyk³ego gethostbyname().
425 * - hostname - nazwa serwera
427 * zaalokowany bufor, który nale¿y zwolniæ lub NULL w przypadku b³êdu.
429 struct hostent
*gg_gethostbyname(const char *hostname
)
431 /* XXX u¿yæ gethostbyname_r() */
433 struct hostent
*hp
, *hp2
;
435 if (!(hp
= gethostbyname(hostname
)))
438 if (!(hp2
= calloc(1, sizeof(*hp
))))
441 memcpy(hp2
, hp
, sizeof(*hp
));
446 #ifdef ASSIGN_SOCKETS_TO_THREADS
448 typedef struct gg_win32_thread
{
451 struct gg_win32_thread
*next
;
454 struct gg_win32_thread
*gg_win32_threads
= 0;
457 * gg_win32_thread_socket() // funkcja pomocnicza, tylko dla win32
459 * zwraca deskryptor gniazda, które by³o ostatnio tworzone dla w±tku
460 * o podanym identyfikatorze.
462 * je¶li na win32 przy po³±czeniach synchronicznych zapamiêtamy w jakim
463 * w±tku uruchomili¶my funkcjê, która siê z czymkolwiek ³±czy, to z osobnego
464 * w±tku mo¿emy anulowaæ po³±czenie poprzez gg_win32_thread_socket(watek, -1);
466 * - thread_id - id w±tku. je¶li jest równe 0, brany jest aktualny w±tek,
467 * je¶li równe -1, usuwa wpis o podanym sockecie.
468 * - socket - deskryptor gniazda. je¶li równe 0, zwraca deskryptor gniazda
469 * dla podanego w±tku, je¶li równe -1, usuwa wpis, je¶li co¶
470 * innego, ustawia dla podanego w±tku dany numer deskryptora.
472 * je¶li socket jest równe 0, zwraca deskryptor gniazda dla podanego w±tku.
474 int gg_win32_thread_socket(int thread_id
, int socket
)
476 char close
= (thread_id
== -1) || socket
== -1;
477 gg_win32_thread
*wsk
= gg_win32_threads
;
478 gg_win32_thread
**p_wsk
= &gg_win32_threads
;
481 thread_id
= GetCurrentThreadId();
484 if ((thread_id
== -1 && wsk
->socket
== socket
) || wsk
->id
== thread_id
) {
486 /* socket zostaje usuniety */
487 closesocket(wsk
->socket
);
491 } else if (!socket
) {
492 /* socket zostaje zwrocony */
495 /* socket zostaje ustawiony */
496 wsk
->socket
= socket
;
501 p_wsk
= &(wsk
->next
);
505 if (close
&& socket
!= -1)
507 if (close
|| !socket
)
510 /* Dodaje nowy element */
511 wsk
= malloc(sizeof(gg_win32_thread
));
513 wsk
->socket
= socket
;
520 #endif /* ASSIGN_SOCKETS_TO_THREADS */
522 static char gg_base64_charset
[] =
523 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
528 * zapisuje ci±g znaków w base64.
530 * - buf - ci±g znaków.
534 char *gg_base64_encode(const char *buf
)
537 unsigned int i
= 0, j
= 0, k
= 0, len
= strlen(buf
);
539 res
= out
= malloc((len
/ 3 + 1) * 4 + 2);
547 k
= (buf
[j
] & 252) >> 2;
551 k
= ((buf
[j
] & 3) << 4) | ((buf
[j
+ 1] & 240) >> 4);
553 k
= (buf
[j
] & 3) << 4;
559 k
= ((buf
[j
] & 15) << 2) | ((buf
[j
+ 1] & 192) >> 6);
561 k
= (buf
[j
] & 15) << 2;
569 *out
++ = gg_base64_charset
[k
];
574 for (j
= 0; j
< 4 - (i
% 4); j
++, out
++)
585 * dekoduje ci±g znaków z base64.
587 * - buf - ci±g znaków.
591 char *gg_base64_decode(const char *buf
)
593 char *res
, *save
, *foo
, val
;
595 unsigned int index
= 0;
600 save
= res
= calloc(1, (strlen(buf
) / 4 + 1) * 3 + 2);
605 end
= buf
+ strlen(buf
);
607 while (*buf
&& buf
< end
) {
608 if (*buf
== '\r' || *buf
== '\n') {
612 if (!(foo
= strchr(gg_base64_charset
, *buf
)))
613 foo
= gg_base64_charset
;
614 val
= (int)(foo
- gg_base64_charset
);
641 * gg_proxy_auth() // funkcja wewnêtrzna
643 * tworzy nag³ówek autoryzacji dla proxy.
645 * zaalokowany tekst lub NULL, je¶li proxy nie jest w³±czone lub nie wymaga
648 char *gg_proxy_auth()
650 char *tmp
, *enc
, *out
;
651 unsigned int tmp_size
;
653 if (!gg_proxy_enabled
|| !gg_proxy_username
|| !gg_proxy_password
)
656 if (!(tmp
= malloc((tmp_size
= strlen(gg_proxy_username
) + strlen(gg_proxy_password
) + 2))))
659 snprintf(tmp
, tmp_size
, "%s:%s", gg_proxy_username
, gg_proxy_password
);
661 if (!(enc
= gg_base64_encode(tmp
))) {
668 if (!(out
= malloc(strlen(enc
) + 40))) {
673 snprintf(out
, strlen(enc
) + 40, "Proxy-Authorization: Basic %s\r\n", enc
);
680 static uint32_t gg_crc32_table
[256];
681 static int gg_crc32_initialized
= 0;
684 * gg_crc32_make_table() // funkcja wewnêtrzna
686 static void gg_crc32_make_table()
691 memset(gg_crc32_table
, 0, sizeof(gg_crc32_table
));
693 for (i
= 128; i
; i
>>= 1) {
694 h
= (h
>> 1) ^ ((h
& 1) ? 0xedb88320L
: 0);
696 for (j
= 0; j
< 256; j
+= 2 * i
)
697 gg_crc32_table
[i
+ j
] = gg_crc32_table
[j
] ^ h
;
700 gg_crc32_initialized
= 1;
706 * wyznacza sumê kontroln± CRC32 danego bloku danych.
708 * - crc - suma kontrola poprzedniego bloku danych lub 0 je¶li pierwszy
709 * - buf - bufor danych
710 * - size - ilo¶æ danych
712 * suma kontrolna CRC32.
714 uint32_t gg_crc32(uint32_t crc
, const unsigned char *buf
, int len
)
716 if (!gg_crc32_initialized
)
717 gg_crc32_make_table();
724 crc
= (crc
>> 8) ^ gg_crc32_table
[(crc
^ *buf
++) & 0xff];
726 return crc
^ 0xffffffffL
;
732 * c-indentation-style: k&r
734 * indent-tabs-mode: notnil