Mercurial > pidgin
view src/protocols/gg/common.c @ 3630:9682c0e022c6
[gaim-migrate @ 3753]
Yeah this will probably break a lot of shit knowing my luck. But hey, I really don't care what people thnk.
committer: Tailor Script <tailor@pidgin.im>
author | Rob Flynn <gaim@robflynn.com> |
---|---|
date | Fri, 11 Oct 2002 03:14:01 +0000 |
parents | 7a3f16a375a5 |
children | 988485669631 |
line wrap: on
line source
/* $Id: common.c 3753 2002-10-11 03:14:01Z robflynn $ */ /* * (C) Copyright 2001 Wojtek Kaniewski <wojtekka@irc.pl>, * 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 General Public License Version 2 as * published by the Free Software Foundation. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <stdio.h> #include <stdlib.h> #ifndef _WIN32 #include <unistd.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> #include <sys/ioctl.h> #include <pwd.h> #include <sys/wait.h> #else #include <winsock.h> #endif #include <sys/time.h> #include <errno.h> #ifndef _AIX # include <string.h> #endif #include <stdarg.h> #include <time.h> #ifdef sun #include <sys/filio.h> #endif #include "libgg.h" #include "config.h" #include <glib.h> /* * gg_debug() * * wyrzuca komunikat o danym poziomie, o ile użytkownik sobie tego życzy. * * - level - poziom wiadomości, * - format... - treść wiadomości (printf-alike.) * * niczego nie zwraca. */ void gg_debug(int level, char *format, ...) { va_list ap; if ((gg_debug_level & level)) { va_start(ap, format); vprintf(format, ap); va_end(ap); } } /* * gg_alloc_sprintf() * * 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. * * - format, ... - parametry takie same jak w innych funkcjach *printf() * * zwraca zaalokowany buforek, który wypadałoby później zwolnić, lub NULL * jeśli nie udało się wykonać zadania. */ char *gg_alloc_sprintf(char *format, ...) { va_list ap; char *buf = NULL, *tmp; int size = 0, res; va_start(ap, format); if ((size = g_vsnprintf(buf, 0, format, ap)) < 1) { size = 128; do { size *= 2; if (!(tmp = realloc(buf, size))) { free(buf); return NULL; } buf = tmp; res = g_vsnprintf(buf, size, format, ap); } while (res == size - 1); } else { if (!(buf = malloc(size + 1))) return NULL; } g_vsnprintf(buf, size + 1, format, ap); va_end(ap); return buf; } /* * gg_get_line() * * podaje kolejną linię z bufora tekstowego. psuje co 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. */ char *gg_get_line(char **ptr) { char *foo, *res; if (!ptr || !*ptr || !strcmp(*ptr, "")) return NULL; res = *ptr; if (!(foo = strchr(*ptr, '\n'))) *ptr += strlen(*ptr); else { *ptr = foo + 1; *foo = 0; if (res[strlen(res) - 1] == '\r') res[strlen(res) - 1] = 0; } return res; } /* * gg_connect() * * łączy się z serwerem. pierwszy argument jest typu (void *), żeby nie * musieć niczego inkludować w libgg.h i nie psuć jakiś głupich zależności * na dziwnych systemach. * * - addr - adres serwera (struct in_addr *), * - port - port serwera, * - async - ma być asynchroniczne połączenie? * * zwraca połączonego socketa lub -1 w przypadku błędu. zobacz errno. */ int gg_connect(void *addr, int port, int async) { int sock, ret, one = 1; struct sockaddr_in sin; struct in_addr *a = addr; 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, "-- socket() failed. errno = %d" #ifndef _WIN32 " (%s)\n", errno, strerror(errno) #else "\n", WSAGetLastError() #endif ); return -1; } if (async) { #ifndef _WIN32 if (ioctl(sock, FIONBIO, &one) == -1) { gg_debug(GG_DEBUG_MISC, "-- ioctl() failed. errno = %d (%s)\n", errno, strerror(errno)); #else if (ioctlsocket(sock, FIONBIO, (unsigned long *)&one) == SOCKET_ERROR) { gg_debug(GG_DEBUG_MISC, "-- ioctlsocket() failed. errno = %d\n", WSAGetLastError()); #endif return -1; } } sin.sin_port = htons(port); sin.sin_family = AF_INET; sin.sin_addr.s_addr = a->s_addr; if ((ret = connect(sock, (struct sockaddr*) &sin, sizeof(sin))) == -1) { #ifndef _WIN32 if (errno && (!async || errno != EINPROGRESS)) { gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno)); return -1; } #else if (ret == SOCKET_ERROR) { gg_debug(GG_DEBUG_MISC, "-- connect() SOCKET_ERROR: %d\n", WSAGetLastError()); if((WSAGetLastError() != WSAEWOULDBLOCK) && (!async || WSAGetLastError() != WSAEINPROGRESS)) { gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d\n", WSAGetLastError()); return -1; } } #endif gg_debug(GG_DEBUG_MISC, "-- connect() in progress\n"); } return sock; } /* * gg_read_line() * * czyta jedną linię tekstu z socketa. * * - sock - socket, * - buf - wskaźnik bufora, * - length - długość bufora. * * olewa błędy. jeśli na jakiś trafi, potraktuje go jako koniec linii. */ void gg_read_line(int sock, char *buf, int length) { int ret; gg_debug(GG_DEBUG_FUNCTION, "** gg_read_line(...);\n"); for (; length > 1; buf++, length--) { do { #ifndef _WIN32 if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) { #else if ((ret = recv(sock, buf, 1, 0)) == SOCKET_ERROR && (WSAGetLastError() != WSAEINTR)) { #endif *buf = 0; return; } #ifndef _WIN32 } while (ret == -1 && errno == EINTR); #else } while (ret == SOCKET_ERROR && WSAGetLastError() == WSAEINTR); #endif if (*buf == '\n') { buf++; break; } } *buf = 0; return; } /* * gg_chomp() * * ucina "\r\n" lub "\n" z końca linii. * * - line - ofiara operacji plastycznej. * * niczego nie zwraca. */ void gg_chomp(char *line) { if (!line || strlen(line) < 1) return; if (line[strlen(line) - 1] == '\n') line[strlen(line) - 1] = 0; if (line[strlen(line) - 1] == '\r') line[strlen(line) - 1] = 0; } /* * gg_urlencode() // funkcja wewnętrzna * * zamienia podany tekst na ciąg znaków do formularza http. przydaje się * przy szukaniu userów z dziwnymi znaczkami. * * - str - ciąg znaków do poprawki. * * zwraca zaalokowany bufor, który wypadałoby kiedyś zwolnić albo NULL * w przypadku błędu. */ char *gg_urlencode(const char *str) { const char *p, hex[] = "0123456789abcdef"; char *q, *buf; int size = 0; if (!str) str = ""; for (p = str; *p; p++, size++) { if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9'))) size += 2; } buf = g_new(char, size + 1); for (p = str, q = buf; *p; p++, q++) { if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9')) *q = *p; else { *q++ = '%'; *q++ = hex[*p >> 4 & 15]; *q = hex[*p & 15]; } } *q = 0; return buf; } /* * gg_http_hash() * * funkcja, która liczy hash dla adresu e-mail i hasła. * * - email - adres email, * - password - hasło. * * zwraca hash wykorzystywany przy rejestracji i wszelkich * manipulacjach własnego wpisu w katalogu publicznym. */ int gg_http_hash(const unsigned char *email, const unsigned char *password) { unsigned int a, c; int b, i; b = (-1); i = 0; while ((c = (int) email[i++]) != 0) { a = (c ^ b) + (c << 8); b = (a >> 24) | (a << 8); } i = 0; while ((c = (int) password[i++]) != 0) { a = (c ^ b) + (c << 8); b = (a >> 24) | (a << 8); } return (b < 0 ? -b : b); } /* * Local variables: * c-indentation-style: k&r * c-basic-offset: 8 * indent-tabs-mode: notnil * End: * * vim: shiftwidth=8: */