Mercurial > pidgin.yaz
diff libpurple/protocols/gg/lib/common.c @ 29938:6359fde67f4c
Update our internal libgadu to 1.9.0-rc2. This does not yet build on Windows.
Refs #10542. The Windows build errors are the only reason this isn't on
`im.pidgin.pidgin` already.
author | John Bailey <rekkanoryo@rekkanoryo.org> |
---|---|
date | Sun, 21 Feb 2010 16:52:42 +0000 |
parents | 259bbfb423d4 |
children | db6735e579f8 |
line wrap: on
line diff
--- a/libpurple/protocols/gg/lib/common.c Sun Feb 21 00:11:56 2010 +0000 +++ b/libpurple/protocols/gg/lib/common.c Sun Feb 21 16:52:42 2010 +0000 @@ -1,8 +1,8 @@ -/* $Id: common.c 16856 2006-08-19 01:13:25Z evands $ */ +/* $Id: common.c 878 2009-11-16 23:48:19Z wojtekka $ */ /* * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl> - * Robert J. WoĽny <speedy@ziew.org> + * Robert J. WoĹşny <speedy@ziew.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License Version @@ -15,13 +15,38 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, * USA. */ -#include "libgadu.h" +/* + * Funkcje konwersji miÄ™dzy UTF-8 i CP1250 sÄ… oparte o kod biblioteki iconv. + * Informacje o prawach autorskich oryginalnego kodu zamieszczono poniĹĽej: + * + * Copyright (C) 1999-2001, 2004 Free Software Foundation, Inc. + * This file is part of the GNU LIBICONV Library. + * + * The GNU LIBICONV Library is free software; you can redistribute it + * and/or modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * The GNU LIBICONV Library is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with the GNU LIBICONV Library; see the file COPYING.LIB. + * If not, write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301, USA. + */ -#ifndef _WIN32 +/** + * \file common.c + * + * \brief Funkcje wykorzystywane przez różne moduĹ‚y biblioteki + */ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/socket.h> @@ -30,94 +55,133 @@ #ifdef sun # include <sys/filio.h> #endif -#endif #include <errno.h> #include <fcntl.h> -#ifndef _WIN32 #include <netdb.h> -#endif #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include "libgadu.h" +#include "libgadu-internal.h" + +/** + * Plik, do ktĂłrego bÄ™dÄ… przekazywane informacje odpluskwiania. + * + * Funkcja \c gg_debug() i pochodne mogÄ… być przechwytywane przez aplikacjÄ™ + * korzystajÄ…cÄ… z biblioteki, by wyĹ›wietlić je na ĹĽÄ…danie uĹĽytkownika lub + * zapisać do późniejszej analizy. JeĹ›li nie okreĹ›lono pliku, wybrane + * informacje bÄ™dÄ… wysyĹ‚ane do standardowego wyjĹ›cia bĹ‚Ä™du (\c stderr). + * + * \ingroup debug + */ FILE *gg_debug_file = NULL; #ifndef GG_DEBUG_DISABLE -/* - * gg_debug() // funkcja wewnętrzna +/** + * \internal Przekazuje informacje odpluskwiania do odpowiedniej funkcji. + * + * JeĹ›li aplikacja ustawiĹ‚a odpowiedniÄ… funkcjÄ™ obsĹ‚ugi w + * \c gg_debug_handler_session lub \c gg_debug_handler, jest ona wywoĹ‚ywana. + * W przeciwnym wypadku wynik jest wysyĹ‚any do standardowego wyjĹ›cia bĹ‚Ä™du. * - * wy¶wietla komunikat o danym poziomie, o ile użytkownik sobie tego życzy. + * \param sess Struktura sesji (moĹĽe być \c NULL) + * \param level Poziom informacji + * \param format Format wiadomoĹ›ci (zgodny z \c printf) + * \param ap Lista argumentĂłw (zgodna z \c printf) + */ +void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap) +{ + if (gg_debug_handler_session) + (*gg_debug_handler_session)(sess, level, format, ap); + else if (gg_debug_handler) + (*gg_debug_handler)(level, format, ap); + else if (gg_debug_level & level) + vfprintf(gg_debug_file ? gg_debug_file : stderr, format, ap); +} + + +/** + * \internal Przekazuje informacjÄ™ odpluskawiania. * - * - level - poziom wiadomo¶ci - * - format... - tre¶ć wiadomo¶ci (kompatybilna z printf()) + * \param level Poziom wiadomoĹ›ci + * \param format Format wiadomoĹ›ci (zgodny z \c printf) + * + * \ingroup debug */ void gg_debug(int level, const char *format, ...) { va_list ap; int old_errno = errno; - - if (gg_debug_handler) { - va_start(ap, format); - (*gg_debug_handler)(level, format, ap); - va_end(ap); + va_start(ap, format); + gg_debug_common(NULL, level, format, ap); + va_end(ap); + errno = old_errno; +} - goto cleanup; - } - - if ((gg_debug_level & level)) { - va_start(ap, format); - vfprintf((gg_debug_file) ? gg_debug_file : stderr, format, ap); - va_end(ap); - } - -cleanup: +/** + * \internal Przekazuje informacjÄ™ odpluskwiania zwiÄ…zanÄ… z sesjÄ…. + * + * \param sess Struktura sesji + * \param level Poziom wiadomoĹ›ci + * \param format Format wiadomoĹ›ci (zgodny z \c printf) + * + * \ingroup debug + */ +void gg_debug_session(struct gg_session *sess, int level, const char *format, ...) +{ + va_list ap; + int old_errno = errno; + va_start(ap, format); + gg_debug_common(sess, level, format, ap); + va_end(ap); errno = old_errno; } #endif -/* - * gg_vsaprintf() // funkcja pomocnicza +/** + * \internal Odpowiednik funkcji \c vsprintf alokujÄ…cy miejsce na wynik. + * + * Funkcja korzysta z funkcji \c vsnprintf, sprawdzajÄ…c czy dostÄ™pna funkcja + * systemowa jest zgodna ze standardem C99 czy wczeĹ›niejszymi. * - * robi dokładnie to samo, co vsprintf(), tyle że alokuje sobie wcze¶niej - * miejsce na dane. powinno działać na tych maszynach, które maj± funkcję - * vsnprintf() zgodn± z C99, jak i na wcze¶niejszych. + * \param format Format wiadomoĹ›ci (zgodny z \c printf) + * \param ap Lista argumentĂłw (zgodna z \c printf) * - * - format - opis wy¶wietlanego tekstu jak dla printf() - * - ap - lista argumentów dla printf() + * \return Zaalokowany bufor lub NULL, jeĹ›li zabrakĹ‚o pamiÄ™ci. * - * zaalokowany bufor, który należy póĽniej zwolnić, lub NULL - * je¶li nie udało się wykonać zadania. + * \ingroup helper */ char *gg_vsaprintf(const char *format, va_list ap) { int size = 0; const char *start; char *buf = NULL; - -#ifdef __GG_LIBGADU_HAVE_VA_COPY + +#ifdef GG_CONFIG_HAVE_VA_COPY va_list aq; va_copy(aq, ap); #else -# ifdef __GG_LIBGADU_HAVE___VA_COPY +# ifdef GG_CONFIG_HAVE___VA_COPY va_list aq; __va_copy(aq, ap); # endif #endif - start = format; + start = format; -#ifndef __GG_LIBGADU_HAVE_C99_VSNPRINTF +#ifndef GG_CONFIG_HAVE_C99_VSNPRINTF { int res; char *tmp; - + size = 128; do { size *= 2; @@ -132,9 +196,9 @@ #else { char tmp[2]; - - /* libce Solarisa przy buforze NULL zawsze zwracaj± -1, więc - * musimy podać co¶ istniej±cego jako cel printf()owania. */ + + /* libce Solarisa przy buforze NULL zawsze zwracajÄ… -1, wiÄ™c + * musimy podać coĹ› istniejÄ…cego jako cel printf()owania. */ size = vsnprintf(tmp, sizeof(tmp), format, ap); if (!(buf = malloc(size + 1))) return NULL; @@ -142,33 +206,33 @@ #endif format = start; - -#ifdef __GG_LIBGADU_HAVE_VA_COPY + +#ifdef GG_CONFIG_HAVE_VA_COPY vsnprintf(buf, size + 1, format, aq); va_end(aq); #else -# ifdef __GG_LIBGADU_HAVE___VA_COPY +# ifdef GG_CONFIG_HAVE___VA_COPY vsnprintf(buf, size + 1, format, aq); va_end(aq); # else vsnprintf(buf, size + 1, format, ap); # endif #endif - + return buf; } -/* - * gg_saprintf() // funkcja pomocnicza +/** + * \internal Odpowiednik funkcji \c sprintf alokujÄ…cy miejsce na wynik. + * + * Funkcja korzysta z funkcji \c vsnprintf, sprawdzajÄ…c czy dostÄ™pna funkcja + * systemowa jest zgodna ze standardem C99 czy wczeĹ›niejszymi. * - * robi dokładnie to samo, co sprintf(), tyle że alokuje sobie wcze¶niej - * miejsce na dane. powinno działać na tych maszynach, które maj± funkcję - * vsnprintf() zgodn± z C99, jak i na wcze¶niejszych. + * \param format Format wiadomoĹ›ci (zgodny z \c printf) * - * - format... - tre¶ć taka sama jak w funkcji printf() + * \return Zaalokowany bufor lub NULL, jeĹ›li zabrakĹ‚o pamiÄ™ci. * - * zaalokowany bufor, który należy póĽniej zwolnić, lub NULL - * je¶li nie udało się wykonać zadania. + * \ingroup helper */ char *gg_saprintf(const char *format, ...) { @@ -182,18 +246,17 @@ return res; } -/* - * gg_get_line() // funkcja pomocnicza - * - * podaje kolejn± linię z bufora tekstowego. niszczy go bezpowrotnie, dziel±c - * na kolejne stringi. zdarza się, nie ma potrzeby pisania funkcji dubluj±cej - * bufor żeby tylko mieć nieruszone dane wej¶ciowe, skoro i tak nie będ± nam - * poĽniej potrzebne. obcina `\r\n'. - * - * - ptr - wskaĽnik do zmiennej, która przechowuje aktualn± pozycję - * w przemiatanym buforze - * - * wskaĽnik do kolejnej linii tekstu lub NULL, je¶li to już koniec bufora. +/** + * \internal Pobiera liniÄ™ tekstu z bufora. + * + * Funkcja niszczy bufor ĹşrĂłdĹ‚owy bezpowrotnie, dzielÄ…c go na kolejne ciÄ…gi + * znakĂłw i obcina znaki koĹ„ca linii. + * + * \param ptr WskaĹşnik do zmiennej, ktĂłra przechowuje aktualne poĹ‚oĹĽenie + * w analizowanym buforze + * + * \return WskaĹşnik do kolejnej linii tekstu lub NULL, jeĹ›li to juĹĽ koniec + * bufora. */ char *gg_get_line(char **ptr) { @@ -207,99 +270,30 @@ if (!(foo = strchr(*ptr, '\n'))) *ptr += strlen(*ptr); else { + size_t len; *ptr = foo + 1; *foo = 0; - if (strlen(res) > 1 && res[strlen(res) - 1] == '\r') - res[strlen(res) - 1] = 0; + + len = strlen(res); + + if (len > 1 && res[len - 1] == '\r') + res[len - 1] = 0; } return res; } -/* - * gg_connect() // funkcja pomocnicza +/** + * \internal Czyta liniÄ™ tekstu z gniazda. * - * ł±czy się z serwerem. pierwszy argument jest typu (void *), żeby nie - * musieć niczego inkludować w libgadu.h i nie psuć jaki¶ głupich zależno¶ci - * na dziwnych systemach. - * - * - addr - adres serwera (struct in_addr *) - * - port - port serwera - * - async - asynchroniczne poł±czenie + * Funkcja czyta tekst znak po znaku, wiÄ™c nie jest efektywna, ale dziÄ™ki + * brakowi buforowania, nie koliduje z innymi funkcjami odczytu. * - * deskryptor gniazda lub -1 w przypadku błędu (kod błędu w zmiennej errno). - */ -int gg_connect(void *addr, int port, int async) -{ - int sock, one = 1, errno2; - struct sockaddr_in sin; - struct in_addr *a = addr; - struct sockaddr_in myaddr; - - gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async); - - if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() socket() failed (errno=%d, %s)\n", errno, strerror(errno)); - return -1; - } - - memset(&myaddr, 0, sizeof(myaddr)); - myaddr.sin_family = AF_INET; - - myaddr.sin_addr.s_addr = gg_local_ip; - - if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() bind() failed (errno=%d, %s)\n", errno, strerror(errno)); - return -1; - } - -#ifdef ASSIGN_SOCKETS_TO_THREADS - gg_win32_thread_socket(0, sock); -#endif - - if (async) { -#ifdef FIONBIO - if (ioctl(sock, FIONBIO, &one) == -1) { -#else - if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) { -#endif - gg_debug(GG_DEBUG_MISC, "// gg_connect() ioctl() failed (errno=%d, %s)\n", errno, strerror(errno)); - errno2 = errno; - close(sock); - errno = errno2; - return -1; - } - } - - sin.sin_port = htons(port); - sin.sin_family = AF_INET; - sin.sin_addr.s_addr = a->s_addr; - - if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) { - if (errno && (!async || errno != EINPROGRESS)) { - gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() failed (errno=%d, %s)\n", errno, strerror(errno)); - errno2 = errno; - close(sock); - errno = errno2; - return -1; - } - gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() in progress\n"); - } - - return sock; -} - -/* - * gg_read_line() // funkcja pomocnicza + * \param sock Deskryptor gniazda + * \param buf WskaĹşnik do bufora + * \param length DĹ‚ugość bufora * - * czyta jedn± linię tekstu z gniazda. - * - * - sock - deskryptor gniazda - * - buf - wskaĽnik do bufora - * - length - długo¶ć bufora - * - * je¶li trafi na bł±d odczytu lub podano nieprawidłowe parametry, zwraca NULL. - * inaczej zwraca buf. + * \return Zwraca \c buf jeĹ›li siÄ™ powiodĹ‚o, lub \c NULL w przypadku bĹ‚Ä™du. */ char *gg_read_line(int sock, char *buf, int length) { @@ -331,38 +325,116 @@ return buf; } -/* - * gg_chomp() // funkcja pomocnicza +/** + * \internal NawiÄ…zuje poĹ‚Ä…czenie TCP. + * + * \param addr WskaĹşnik na strukturÄ™ \c in_addr z adresem serwera + * \param port Port serwera + * \param async Flaga asynchronicznego poĹ‚Ä…czenia + * + * \return Deskryptor gniazda lub -1 w przypadku bĹ‚Ä™du * - * ucina "\r\n" lub "\n" z końca linii. + * \ingroup helper + */ +int gg_connect(void *addr, int port, int async) +{ + int sock, one = 1, errno2; + struct sockaddr_in sin; + struct in_addr *a = addr; + struct sockaddr_in myaddr; + + gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async); + + if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { + gg_debug(GG_DEBUG_MISC, "// gg_connect() socket() failed (errno=%d, %s)\n", errno, strerror(errno)); + return -1; + } + + memset(&myaddr, 0, sizeof(myaddr)); + myaddr.sin_family = AF_INET; + + myaddr.sin_addr.s_addr = gg_local_ip; + + if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) { + gg_debug(GG_DEBUG_MISC, "// gg_connect() bind() failed (errno=%d, %s)\n", errno, strerror(errno)); + errno2 = errno; + close(sock); + errno = errno2; + return -1; + } + +#ifdef ASSIGN_SOCKETS_TO_THREADS + gg_win32_thread_socket(0, sock); +#endif + + if (async) { +#ifdef FIONBIO + if (ioctl(sock, FIONBIO, &one) == -1) { +#else + if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) { +#endif + gg_debug(GG_DEBUG_MISC, "// gg_connect() ioctl() failed (errno=%d, %s)\n", errno, strerror(errno)); + errno2 = errno; + close(sock); + errno = errno2; + return -1; + } + } + + sin.sin_port = htons(port); + sin.sin_family = AF_INET; + sin.sin_addr.s_addr = a->s_addr; + + if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) { + if (errno && (!async || errno != EINPROGRESS)) { + gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() failed (errno=%d, %s)\n", errno, strerror(errno)); + errno2 = errno; + close(sock); + errno = errno2; + return -1; + } + gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() in progress\n"); + } + + return sock; +} + +/** + * \internal Usuwa znaki koĹ„ca linii. * - * - line - linia do przycięcia + * Funkcja dziaĹ‚a bezpoĹ›rednio na buforze. + * + * \param line Bufor z tekstem + * + * \ingroup helper */ void gg_chomp(char *line) { int len; - + if (!line) return; len = strlen(line); - + if (len > 0 && line[len - 1] == '\n') line[--len] = 0; if (len > 0 && line[len - 1] == '\r') line[--len] = 0; } -/* - * gg_urlencode() // funkcja wewnętrzna +/** + * \internal Koduje ciÄ…g znakĂłw do postacji adresu HTTP. * - * zamienia podany tekst na ci±g znaków do formularza http. przydaje się - * przy różnych usługach katalogu publicznego. + * Zamienia znaki niedrukowalne, spoza ASCII i majÄ…ce specjalne znaczenie + * dla protokoĹ‚u HTTP na encje postaci \c %XX, gdzie \c XX jest szesnastkowÄ… + * wartoĹ›ciÄ… znaku. + * + * \param str CiÄ…g znakĂłw do zakodowania * - * - str - ci±g znaków do zakodowania + * \return Zaalokowany bufor lub \c NULL w przypadku bĹ‚Ä™du. * - * zaalokowany bufor, który należy póĽniej zwolnić albo NULL - * w przypadku błędu. + * \ingroup helper */ char *gg_urlencode(const char *str) { @@ -400,16 +472,19 @@ return buf; } -/* - * gg_http_hash() // funkcja wewnętrzna +/** + * \internal Wyznacza skrĂłt dla usĹ‚ug HTTP. * - * funkcja licz±ca hash dla adresu e-mail, hasła i paru innych. + * Funkcja jest wykorzystywana do wyznaczania skrĂłtu adresu e-mail, hasĹ‚a + * i innych wartoĹ›ci przekazywanych jako parametry usĹ‚ug HTTP. * - * - format... - format kolejnych parametrów ('s' je¶li dany parametr jest - * ci±giem znaków lub 'u' je¶li numerem GG) + * W parametrze \c format naleĹĽy umieĹ›cić znaki okreĹ›lajÄ…ce postać kolejnych + * parametrĂłw: \c 's' jeĹ›li parametr jest ciÄ…giem znakĂłw, \c 'u' jeĹ›li jest + * liczbÄ…. * - * hash wykorzystywany przy rejestracji i wszelkich manipulacjach własnego - * wpisu w katalogu publicznym. + * \param format Format kolejnych parametrĂłw (niezgodny z \c printf) + * + * \return Wartość skrĂłtu */ int gg_http_hash(const char *format, ...) { @@ -428,7 +503,7 @@ } else { if (!(arg = va_arg(ap, char*))) arg = ""; - } + } i = 0; while ((c = (unsigned char) arg[i++]) != 0) { @@ -442,95 +517,6 @@ return (b < 0 ? -b : b); } -/* - * gg_gethostbyname() // funkcja pomocnicza - * - * odpowiednik gethostbyname() troszcz±cy się o współbieżno¶ć, gdy mamy do - * dyspozycji funkcję gethostbyname_r(). - * - * - hostname - nazwa serwera - * - * zwraca wskaĽnik na strukturę in_addr, któr± należy zwolnić. - */ -struct in_addr *gg_gethostbyname(const char *hostname) -{ - struct in_addr *addr = NULL; - -#ifdef HAVE_GETHOSTBYNAME_R - char *tmpbuf = NULL, *buf = NULL; - struct hostent *hp = NULL, *hp2 = NULL; - int h_errnop, ret; - size_t buflen = 1024; - int new_errno; - - new_errno = ENOMEM; - - if (!(addr = malloc(sizeof(struct in_addr)))) - goto cleanup; - - if (!(hp = calloc(1, sizeof(*hp)))) - goto cleanup; - - if (!(buf = malloc(buflen))) - goto cleanup; - - tmpbuf = buf; - - while ((ret = gethostbyname_r(hostname, hp, buf, buflen, &hp2, &h_errnop)) == ERANGE) { - buflen *= 2; - - if (!(tmpbuf = realloc(buf, buflen))) - break; - - buf = tmpbuf; - } - - if (ret) - new_errno = h_errnop; - - if (ret || !hp2 || !tmpbuf) - goto cleanup; - - memcpy(addr, hp->h_addr, sizeof(struct in_addr)); - - free(buf); - free(hp); - - return addr; - -cleanup: - errno = new_errno; - - if (addr) - free(addr); - if (hp) - free(hp); - if (buf) - free(buf); - - return NULL; -#else - struct hostent *hp; - - if (!(addr = malloc(sizeof(struct in_addr)))) { - goto cleanup; - } - - if (!(hp = gethostbyname(hostname))) - goto cleanup; - - memcpy(addr, hp->h_addr, sizeof(struct in_addr)); - - return addr; - -cleanup: - if (addr) - free(addr); - - return NULL; -#endif -} - #ifdef ASSIGN_SOCKETS_TO_THREADS typedef struct gg_win32_thread { @@ -541,23 +527,22 @@ struct gg_win32_thread *gg_win32_threads = 0; -/* - * gg_win32_thread_socket() // funkcja pomocnicza, tylko dla win32 +/** + * \internal Zwraca deskryptor gniazda, ktĂłre byĹ‚o ostatnio tworzone dla wÄ…tku. * - * zwraca deskryptor gniazda, które było ostatnio tworzone dla w±tku - * o podanym identyfikatorze. + * JeĹ›li na win32 przy poĹ‚Ä…czeniach synchronicznych zapamiÄ™tamy w jakim + * wÄ…tku uruchomiliĹ›my funkcjÄ™, ktĂłra siÄ™ z czymkolwiek Ĺ‚Ä…czy, to z osobnego + * wÄ…tku moĹĽemy anulować poĹ‚Ä…czenie poprzez \c gg_win32_thread_socket(watek,-1) * - * je¶li na win32 przy poł±czeniach synchronicznych zapamiętamy w jakim - * w±tku uruchomili¶my funkcję, która się z czymkolwiek ł±czy, to z osobnego - * w±tku możemy anulować poł±czenie poprzez gg_win32_thread_socket(watek, -1); - * - * - thread_id - id w±tku. je¶li jest równe 0, brany jest aktualny w±tek, - * je¶li równe -1, usuwa wpis o podanym sockecie. - * - socket - deskryptor gniazda. je¶li równe 0, zwraca deskryptor gniazda - * dla podanego w±tku, je¶li równe -1, usuwa wpis, je¶li co¶ - * innego, ustawia dla podanego w±tku dany numer deskryptora. + * \param thread_id Identyfikator wÄ…tku (jeĹ›li jest rĂłwne 0, brany jest + * aktualny wÄ…tek, jeĹ›li rĂłwne -1, usuwa wpis dotyczÄ…cy + * danego gniazda sockecie) + * \param socket Deskryptor gniazda (jeĹ›li rĂłwne 0, zwraca deskryptor gniazda + * dla podanego wÄ…tku, jeĹ›li rĂłwne -1, usuwa wpis, jeĹ›li coĹ› + * innego, ustawia dla podanego wÄ…tku dany numer deskryptora) * - * je¶li socket jest równe 0, zwraca deskryptor gniazda dla podanego w±tku. + * \return JeĹ›li socket jest rĂłwne 0, zwraca deskryptor gniazda dla podanego + * wÄ…tku. */ int gg_win32_thread_socket(int thread_id, int socket) { @@ -567,7 +552,7 @@ if (!thread_id) thread_id = GetCurrentThreadId(); - + while (wsk) { if ((thread_id == -1 && wsk->socket == socket) || wsk->id == thread_id) { if (close) { @@ -593,7 +578,7 @@ closesocket(socket); if (close || !socket) return 0; - + /* Dodaje nowy element */ wsk = malloc(sizeof(gg_win32_thread)); wsk->id = thread_id; @@ -606,28 +591,33 @@ #endif /* ASSIGN_SOCKETS_TO_THREADS */ +/** + * \internal Zestaw znakĂłw kodowania base64. + */ static char gg_base64_charset[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; -/* - * gg_base64_encode() +/** + * \internal Koduje ciÄ…g znakĂłw do base64. + * + * Wynik funkcji naleĹĽy zwolnić za pomocÄ… \c free. * - * zapisuje ci±g znaków w base64. + * \param buf Bufor z danami do zakodowania * - * - buf - ci±g znaków. + * \return Zaalokowany bufor z zakodowanymi danymi * - * zaalokowany bufor. + * \ingroup helper */ char *gg_base64_encode(const char *buf) { char *out, *res; unsigned int i = 0, j = 0, k = 0, len = strlen(buf); - + res = out = malloc((len / 3 + 1) * 4 + 2); if (!res) return NULL; - + while (j <= len) { switch (i % 4) { case 0: @@ -660,20 +650,22 @@ if (i % 4) for (j = 0; j < 4 - (i % 4); j++, out++) *out = '='; - + *out = 0; - + return res; } -/* - * gg_base64_decode() +/** + * \internal Dekoduje ciÄ…g znakĂłw zapisany w base64. + * + * Wynik funkcji naleĹĽy zwolnić za pomocÄ… \c free. * - * dekoduje ci±g znaków z base64. + * \param buf Bufor ĹşrĂłdĹ‚owy z danymi do zdekodowania * - * - buf - ci±g znaków. + * \return Zaalokowany bufor ze zdekodowanymi danymi * - * zaalokowany bufor. + * \ingroup helper */ char *gg_base64_decode(const char *buf) { @@ -683,7 +675,7 @@ if (!buf) return NULL; - + save = res = calloc(1, (strlen(buf) / 4 + 1) * 3 + 2); if (!save) @@ -720,23 +712,24 @@ index %= 4; } *res = 0; - + return save; } -/* - * gg_proxy_auth() // funkcja wewnętrzna +/** + * \internal Tworzy nagĹ‚Ăłwek autoryzacji serwera poĹ›redniczÄ…cego. * - * tworzy nagłówek autoryzacji dla proxy. - * - * zaalokowany tekst lub NULL, je¶li proxy nie jest wł±czone lub nie wymaga - * autoryzacji. + * Dane pobiera ze zmiennych globalnych \c gg_proxy_username i + * \c gg_proxy_password. + * + * \return Zaalokowany bufor z tekstem lub NULL, jeĹ›li serwer poĹ›redniczÄ…cy + * nie jest uĹĽywany lub nie wymaga autoryzacji. */ char *gg_proxy_auth() { char *tmp, *enc, *out; unsigned int tmp_size; - + if (!gg_proxy_enabled || !gg_proxy_username || !gg_proxy_password) return NULL; @@ -749,14 +742,14 @@ free(tmp); return NULL; } - + free(tmp); if (!(out = malloc(strlen(enc) + 40))) { free(enc); return NULL; } - + snprintf(out, strlen(enc) + 40, "Proxy-Authorization: Basic %s\r\n", enc); free(enc); @@ -764,13 +757,21 @@ return out; } +/** + * \internal Tablica pomocnicza do wyznaczania sumy kontrolnej. + */ static uint32_t gg_crc32_table[256]; + +/** + * \internal Flaga wypeĹ‚nienia tablicy pomocniczej do wyznaczania sumy + * kontrolnej. + */ static int gg_crc32_initialized = 0; -/* - * gg_crc32_make_table() // funkcja wewnętrzna +/** + * \internal Tworzy tablicÄ™ pomocniczÄ… do wyznaczania sumy kontrolnej. */ -static void gg_crc32_make_table() +static void gg_crc32_make_table(void) { uint32_t h = 1; unsigned int i, j; @@ -787,16 +788,15 @@ gg_crc32_initialized = 1; } -/* - * gg_crc32() - * - * wyznacza sumę kontroln± CRC32 danego bloku danych. +/** + * Wyznacza sumÄ™ kontrolnÄ… CRC32. * - * - crc - suma kontrola poprzedniego bloku danych lub 0 je¶li pierwszy - * - buf - bufor danych - * - size - ilo¶ć danych + * \param crc Suma kontrola poprzedniego bloku danych lub 0 jeĹ›li liczona + * jest suma kontrolna pierwszego bloku + * \param buf Bufor danych + * \param len DĹ‚ugość bufora danych * - * suma kontrolna CRC32. + * \return Suma kontrolna. */ uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len) { @@ -814,6 +814,186 @@ return crc ^ 0xffffffffL; } +/** + * \internal Tablica konwersji miÄ™dzy CP1250 a UTF-8. + */ +static const uint16_t table_cp1250[] = { + 0x20ac, '?', 0x201a, '?', 0x201e, 0x2026, 0x2020, 0x2021, + '?', 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179, + '?', 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, + '?', 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a, + 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7, + 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b, + 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7, + 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c, + 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, + 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, + 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, + 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, + 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, + 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, + 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, + 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, +}; + +/** + * \internal Zamienia tekst kodowany CP1250 na UTF-8. + * + * \param b Tekst ĹşrĂłdĹ‚owy w CP1250. + * + * \return Zaalokowany bufor z tekstem w UTF-8. + */ +char *gg_cp_to_utf8(const char *b) +{ + unsigned char *buf = (unsigned char *) b; + char *newbuf; + int newlen = 0; + int i, j; + + for (i = 0; buf[i]; i++) { + uint16_t znak = (buf[i] < 0x80) ? buf[i] : table_cp1250[buf[i]-0x80]; + + if (znak < 0x80) newlen += 1; + else if (znak < 0x800) newlen += 2; + else newlen += 3; + } + + if (!(newbuf = malloc(newlen+1))) { + gg_debug(GG_DEBUG_MISC, "// gg_cp_to_utf8() not enough memory\n"); + return NULL; + } + + for (i = 0, j = 0; buf[i]; i++) { + uint16_t znak = (buf[i] < 0x80) ? buf[i] : table_cp1250[buf[i]-0x80]; + int count; + + if (znak < 0x80) count = 1; + else if (znak < 0x800) count = 2; + else count = 3; + + switch (count) { + case 3: newbuf[j+2] = 0x80 | (znak & 0x3f); znak = znak >> 6; znak |= 0x800; + case 2: newbuf[j+1] = 0x80 | (znak & 0x3f); znak = znak >> 6; znak |= 0xc0; + case 1: newbuf[j] = znak; + } + j += count; + } + newbuf[j] = '\0'; + + return newbuf; +} + +/** + * \internal Dekoduje jeden znak UTF-8. + * + * \note Funkcja nie jest kompletnÄ… implementacjÄ… UTF-8, a wersjÄ… uproszczonÄ… + * do potrzeb kodowania CP1250. + * + * \param s Tekst ĹşrĂłdĹ‚owy. + * \param n DĹ‚ugość tekstu ĹşrĂłdĹ‚owego. + * \param ch WskaĹşnik na wynik dekodowania. + * + * \return DĹ‚ugość zdekodowanej sekwencji w bajtach lub wartość mniejsza + * od zera w przypadku bĹ‚Ä™du. + */ +static int gg_utf8_helper(unsigned char *s, int n, uint16_t *ch) +{ + unsigned char c = s[0]; + + if (c < 0x80) { + *ch = c; + return 1; + } + + if (c < 0xc2) + return -1; + + if (c < 0xe0) { + if (n < 2) + return -2; + if (!((s[1] ^ 0x80) < 0x40)) + return -1; + *ch = ((uint16_t) (c & 0x1f) << 6) | (uint16_t) (s[1] ^ 0x80); + return 2; + } + + if (c < 0xf0) { + if (n < 3) + return -2; + if (!((s[1] ^ 0x80) < 0x40 && (s[2] ^ 0x80) < 0x40 && (c >= 0xe1 || s[1] >= 0xa0))) + return -1; + *ch = ((uint16_t) (c & 0x0f) << 12) | ((uint16_t) (s[1] ^ 0x80) << 6) | (uint16_t) (s[2] ^ 0x80); + return 3; + } + + return -1; +} + +/** + * \internal Zamienia tekst kodowany UTF-8 na CP1250. + * + * \param b Tekst ĹşrĂłdĹ‚owy w UTF-8. + * + * \return Zaalokowany bufor z tekstem w CP1250. + */ +char *gg_utf8_to_cp(const char *b) +{ + unsigned char *buf = (unsigned char *) b; + char *newbuf; + int newlen = 0; + int len; + int i, j; + + len = strlen(b); + + for (i = 0; i < len; newlen++) { + uint16_t discard; + int ret; + + ret = gg_utf8_helper(&buf[i], len - i, &discard); + + if (ret > 0) + i += ret; + else + i++; + } + + if (!(newbuf = malloc(newlen+1))) { + gg_debug(GG_DEBUG_MISC, "// gg_utf8_to_cp() not enough memory\n"); + return NULL; + } + + for (i = 0, j = 0; buf[i]; j++) { + uint16_t znak; + int ret, k; + + ret = gg_utf8_helper(&buf[i], len - i, &znak); + + if (ret > 0) { + i += ret; + } else { + znak = '?'; + i++; + } + + if (znak < 0x80) { + newbuf[j] = znak; + continue; + } + + newbuf[j] = '?'; + + for (k = 0; k < (sizeof(table_cp1250)/sizeof(table_cp1250[0])); k++) { + if (table_cp1250[k] == znak) { + newbuf[j] = (0x80 | k); + break; + } + } + } + newbuf[j] = '\0'; + + return newbuf; +} /* * Local variables: