| |
1 /* $Id: common.c 2859 2001-12-05 09:48:56Z warmenhoven $ */ |
| |
2 |
| |
3 /* |
| |
4 * (C) Copyright 2001 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 General Public License Version 2 as |
| |
9 * 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 General Public License for more details. |
| |
15 * |
| |
16 * You should have received a copy of the GNU General Public License |
| |
17 * along with this program; if not, write to the Free Software |
| |
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| |
19 */ |
| |
20 |
| |
21 #include <stdio.h> |
| |
22 #include <stdlib.h> |
| |
23 #include <unistd.h> |
| |
24 #include <stdio.h> |
| |
25 #include <sys/socket.h> |
| |
26 #include <netinet/in.h> |
| |
27 #include <arpa/inet.h> |
| |
28 #include <sys/ioctl.h> |
| |
29 #include <sys/wait.h> |
| |
30 #include <sys/time.h> |
| |
31 #include <netdb.h> |
| |
32 #include <errno.h> |
| |
33 #ifndef _AIX |
| |
34 # include <string.h> |
| |
35 #endif |
| |
36 #include <stdarg.h> |
| |
37 #include <pwd.h> |
| |
38 #include <time.h> |
| |
39 #ifdef sun |
| |
40 #include <sys/filio.h> |
| |
41 #endif |
| |
42 #include "libgg.h" |
| |
43 #include "config.h" |
| |
44 |
| |
45 /* |
| |
46 * gg_debug() |
| |
47 * |
| |
48 * wyrzuca komunikat o danym poziomie, o ile użytkownik sobie tego życzy. |
| |
49 * |
| |
50 * - level - poziom wiadomości, |
| |
51 * - format... - treść wiadomości (printf-alike.) |
| |
52 * |
| |
53 * niczego nie zwraca. |
| |
54 */ |
| |
55 void gg_debug(int level, char *format, ...) |
| |
56 { |
| |
57 va_list ap; |
| |
58 |
| |
59 if ((gg_debug_level & level)) { |
| |
60 va_start(ap, format); |
| |
61 vprintf(format, ap); |
| |
62 va_end(ap); |
| |
63 } |
| |
64 } |
| |
65 |
| |
66 /* |
| |
67 * gg_alloc_sprintf() |
| |
68 * |
| |
69 * robi dokładnie to samo, co sprintf(), tyle że alokuje sobie wcześniej |
| |
70 * miejsce na dane. powinno działać na tych maszynach, które mają funkcję |
| |
71 * vsnprintf() zgodną z C99, jak i na wcześniejszych. |
| |
72 * |
| |
73 * - format, ... - parametry takie same jak w innych funkcjach *printf() |
| |
74 * |
| |
75 * zwraca zaalokowany buforek, który wypadałoby później zwolnić, lub NULL |
| |
76 * jeśli nie udało się wykonać zadania. |
| |
77 */ |
| |
78 char *gg_alloc_sprintf(char *format, ...) |
| |
79 { |
| |
80 va_list ap; |
| |
81 char *buf = NULL, *tmp; |
| |
82 int size = 0, res; |
| |
83 |
| |
84 va_start(ap, format); |
| |
85 |
| |
86 if ((size = vsnprintf(buf, 0, format, ap)) < 1) { |
| |
87 size = 128; |
| |
88 do { |
| |
89 size *= 2; |
| |
90 if (!(tmp = realloc(buf, size))) { |
| |
91 free(buf); |
| |
92 return NULL; |
| |
93 } |
| |
94 buf = tmp; |
| |
95 res = vsnprintf(buf, size, format, ap); |
| |
96 } while (res == size - 1); |
| |
97 } else { |
| |
98 if (!(buf = malloc(size + 1))) |
| |
99 return NULL; |
| |
100 } |
| |
101 |
| |
102 vsnprintf(buf, size + 1, format, ap); |
| |
103 |
| |
104 va_end(ap); |
| |
105 |
| |
106 return buf; |
| |
107 } |
| |
108 |
| |
109 /* |
| |
110 * gg_get_line() |
| |
111 * |
| |
112 * podaje kolejną linię z bufora tekstowego. psuje co bezpowrotnie, dzieląc |
| |
113 * na kolejne stringi. zdarza się, nie ma potrzeby pisania funkcji dublującej |
| |
114 * bufor żeby tylko mieć nieruszone dane wejściowe, skoro i tak nie będą nam |
| |
115 * poźniej potrzebne. obcina `\r\n'. |
| |
116 * |
| |
117 * - ptr - wskaźnik do zmiennej, która przechowuje aktualną pozycję |
| |
118 * w przemiatanym buforze. |
| |
119 * |
| |
120 * wskaźnik do kolejnej linii tekstu lub NULL, jeśli to już koniec bufora. |
| |
121 */ |
| |
122 char *gg_get_line(char **ptr) |
| |
123 { |
| |
124 char *foo, *res; |
| |
125 |
| |
126 if (!ptr || !*ptr || !strcmp(*ptr, "")) |
| |
127 return NULL; |
| |
128 |
| |
129 res = *ptr; |
| |
130 |
| |
131 if (!(foo = strchr(*ptr, '\n'))) |
| |
132 *ptr += strlen(*ptr); |
| |
133 else { |
| |
134 *ptr = foo + 1; |
| |
135 *foo = 0; |
| |
136 if (res[strlen(res) - 1] == '\r') |
| |
137 res[strlen(res) - 1] = 0; |
| |
138 } |
| |
139 |
| |
140 return res; |
| |
141 } |
| |
142 |
| |
143 /* |
| |
144 * gg_connect() |
| |
145 * |
| |
146 * łączy się z serwerem. pierwszy argument jest typu (void *), żeby nie |
| |
147 * musieć niczego inkludować w libgg.h i nie psuć jakiś głupich zależności |
| |
148 * na dziwnych systemach. |
| |
149 * |
| |
150 * - addr - adres serwera (struct in_addr *), |
| |
151 * - port - port serwera, |
| |
152 * - async - ma być asynchroniczne połączenie? |
| |
153 * |
| |
154 * zwraca połączonego socketa lub -1 w przypadku błędu. zobacz errno. |
| |
155 */ |
| |
156 int gg_connect(void *addr, int port, int async) |
| |
157 { |
| |
158 int sock, one = 1; |
| |
159 struct sockaddr_in sin; |
| |
160 struct in_addr *a = addr; |
| |
161 |
| |
162 gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async); |
| |
163 |
| |
164 if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) { |
| |
165 gg_debug(GG_DEBUG_MISC, "-- socket() failed. errno = %d (%s)\n", errno, strerror(errno)); |
| |
166 return -1; |
| |
167 } |
| |
168 |
| |
169 if (async) { |
| |
170 if (ioctl(sock, FIONBIO, &one) == -1) { |
| |
171 gg_debug(GG_DEBUG_MISC, "-- ioctl() failed. errno = %d (%s)\n", errno, strerror(errno)); |
| |
172 return -1; |
| |
173 } |
| |
174 } |
| |
175 |
| |
176 sin.sin_port = htons(port); |
| |
177 sin.sin_family = AF_INET; |
| |
178 sin.sin_addr.s_addr = a->s_addr; |
| |
179 |
| |
180 if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) { |
| |
181 if (errno && (!async || errno != EINPROGRESS)) { |
| |
182 gg_debug(GG_DEBUG_MISC, "-- connect() failed. errno = %d (%s)\n", errno, strerror(errno)); |
| |
183 return -1; |
| |
184 } |
| |
185 gg_debug(GG_DEBUG_MISC, "-- connect() in progress\n"); |
| |
186 } |
| |
187 |
| |
188 return sock; |
| |
189 } |
| |
190 |
| |
191 /* |
| |
192 * gg_read_line() |
| |
193 * |
| |
194 * czyta jedną linię tekstu z socketa. |
| |
195 * |
| |
196 * - sock - socket, |
| |
197 * - buf - wskaźnik bufora, |
| |
198 * - length - długość bufora. |
| |
199 * |
| |
200 * olewa błędy. jeśli na jakiś trafi, potraktuje go jako koniec linii. |
| |
201 */ |
| |
202 void gg_read_line(int sock, char *buf, int length) |
| |
203 { |
| |
204 int ret; |
| |
205 |
| |
206 gg_debug(GG_DEBUG_FUNCTION, "** gg_read_line(...);\n"); |
| |
207 |
| |
208 for (; length > 1; buf++, length--) { |
| |
209 do { |
| |
210 if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR) { |
| |
211 *buf = 0; |
| |
212 return; |
| |
213 } |
| |
214 } while (ret == -1 && errno == EINTR); |
| |
215 |
| |
216 if (*buf == '\n') { |
| |
217 buf++; |
| |
218 break; |
| |
219 } |
| |
220 } |
| |
221 |
| |
222 *buf = 0; |
| |
223 return; |
| |
224 } |
| |
225 |
| |
226 /* |
| |
227 * gg_chomp() |
| |
228 * |
| |
229 * ucina "\r\n" lub "\n" z końca linii. |
| |
230 * |
| |
231 * - line - ofiara operacji plastycznej. |
| |
232 * |
| |
233 * niczego nie zwraca. |
| |
234 */ |
| |
235 void gg_chomp(char *line) |
| |
236 { |
| |
237 if (!line || strlen(line) < 1) |
| |
238 return; |
| |
239 |
| |
240 if (line[strlen(line) - 1] == '\n') |
| |
241 line[strlen(line) - 1] = 0; |
| |
242 if (line[strlen(line) - 1] == '\r') |
| |
243 line[strlen(line) - 1] = 0; |
| |
244 } |
| |
245 |
| |
246 |
| |
247 /* |
| |
248 * gg_urlencode() // funkcja wewnętrzna |
| |
249 * |
| |
250 * zamienia podany tekst na ciąg znaków do formularza http. przydaje się |
| |
251 * przy szukaniu userów z dziwnymi znaczkami. |
| |
252 * |
| |
253 * - str - ciąg znaków do poprawki. |
| |
254 * |
| |
255 * zwraca zaalokowany bufor, który wypadałoby kiedyś zwolnić albo NULL |
| |
256 * w przypadku błędu. |
| |
257 */ |
| |
258 char *gg_urlencode(char *str) |
| |
259 { |
| |
260 char *p, *q, *buf, hex[] = "0123456789abcdef"; |
| |
261 int size = 0; |
| |
262 |
| |
263 if (!str) |
| |
264 str = strdup(""); |
| |
265 |
| |
266 for (p = str; *p; p++, size++) { |
| |
267 if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9'))) |
| |
268 size += 2; |
| |
269 } |
| |
270 |
| |
271 if (!(buf = malloc(size + 1))) |
| |
272 return NULL; |
| |
273 |
| |
274 for (p = str, q = buf; *p; p++, q++) { |
| |
275 if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9')) |
| |
276 *q = *p; |
| |
277 else { |
| |
278 *q++ = '%'; |
| |
279 *q++ = hex[*p >> 4 & 15]; |
| |
280 *q = hex[*p & 15]; |
| |
281 } |
| |
282 } |
| |
283 |
| |
284 *q = 0; |
| |
285 |
| |
286 return buf; |
| |
287 } |
| |
288 |
| |
289 /* |
| |
290 * gg_http_hash() |
| |
291 * |
| |
292 * funkcja, która liczy hash dla adresu e-mail i hasła. |
| |
293 * |
| |
294 * - email - adres email, |
| |
295 * - password - hasło. |
| |
296 * |
| |
297 * zwraca hash wykorzystywany przy rejestracji i wszelkich |
| |
298 * manipulacjach własnego wpisu w katalogu publicznym. |
| |
299 */ |
| |
300 |
| |
301 int gg_http_hash(unsigned char *email, unsigned char *password) |
| |
302 { |
| |
303 unsigned int a, c; |
| |
304 int b, i; |
| |
305 b = (-1); |
| |
306 |
| |
307 i = 0; |
| |
308 while ((c = (int) email[i++]) != 0) { |
| |
309 a = (c ^ b) + (c << 8); |
| |
310 b = (a >> 24) | (a << 8); |
| |
311 } |
| |
312 |
| |
313 i = 0; |
| |
314 while ((c = (int) password[i++]) != 0) { |
| |
315 a = (c ^ b) + (c << 8); |
| |
316 b = (a >> 24) | (a << 8); |
| |
317 } |
| |
318 |
| |
319 return (b < 0 ? -b : b); |
| |
320 } |
| |
321 |
| |
322 /* |
| |
323 * Local variables: |
| |
324 * c-indentation-style: k&r |
| |
325 * c-basic-offset: 8 |
| |
326 * indent-tabs-mode: notnil |
| |
327 * End: |
| |
328 * |
| |
329 * vim: shiftwidth=8: |
| |
330 */ |