Mercurial > hg > nnchat
comparison libnnchat.c @ 386:4523fc0941e8
Cosmetics.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Thu, 29 Dec 2011 00:39:20 +0200 |
parents | 812af6823eb7 |
children | acea18a741e3 |
comparison
equal
deleted
inserted
replaced
385:bbd5edbf1143 | 386:4523fc0941e8 |
---|---|
20 } | 20 } |
21 | 21 |
22 const char *nn_get_socket_errstr(int err) | 22 const char *nn_get_socket_errstr(int err) |
23 { | 23 { |
24 static char buf[64]; | 24 static char buf[64]; |
25 switch (err) { | 25 switch (err) |
26 { | |
26 case WSAEADDRINUSE: return "Address already in use"; | 27 case WSAEADDRINUSE: return "Address already in use"; |
27 case WSAECONNABORTED: return "Software caused connection abort"; | 28 case WSAECONNABORTED: return "Software caused connection abort"; |
28 case WSAECONNREFUSED: return "Connection refused"; | 29 case WSAECONNREFUSED: return "Connection refused"; |
29 case WSAECONNRESET: return "Connection reset by peer"; | 30 case WSAECONNRESET: return "Connection reset by peer"; |
30 case WSAEHOSTUNREACH: return "No route to host"; | 31 case WSAEHOSTUNREACH: return "No route to host"; |
51 #endif | 52 #endif |
52 | 53 |
53 | 54 |
54 void nn_conn_err(nn_conn_t *conn, const char *fmt, ...) | 55 void nn_conn_err(nn_conn_t *conn, const char *fmt, ...) |
55 { | 56 { |
56 if (conn->errfunc) { | 57 if (conn->errfunc != NULL) |
58 { | |
57 va_list ap; | 59 va_list ap; |
58 va_start(ap, fmt); | 60 va_start(ap, fmt); |
59 conn->errfunc(conn, fmt, ap); | 61 conn->errfunc(conn, fmt, ap); |
60 va_end(ap); | 62 va_end(ap); |
61 } | 63 } |
62 } | 64 } |
63 | 65 |
64 | 66 |
65 static void nn_conn_msg(nn_conn_t *conn, const char *fmt, ...) | 67 static void nn_conn_msg(nn_conn_t *conn, const char *fmt, ...) |
66 { | 68 { |
67 if (conn->msgfunc) { | 69 if (conn->msgfunc != NULL) |
70 { | |
68 va_list ap; | 71 va_list ap; |
69 va_start(ap, fmt); | 72 va_start(ap, fmt); |
70 conn->msgfunc(conn, fmt, ap); | 73 conn->msgfunc(conn, fmt, ap); |
71 va_end(ap); | 74 va_end(ap); |
72 } | 75 } |
81 nn_conn_msg(conn, "True hostname for %s is %s\n", name, res->h_name); | 84 nn_conn_msg(conn, "True hostname for %s is %s\n", name, res->h_name); |
82 | 85 |
83 return res; | 86 return res; |
84 } | 87 } |
85 | 88 |
86 static const char *nn_proxy_types[] = { | 89 static const char *nn_proxy_types[] = |
90 { | |
87 "none", | 91 "none", |
88 "SOCKS 4", | 92 "SOCKS 4", |
89 "SOCKS 4a", | 93 "SOCKS 4a", |
90 NULL | 94 NULL |
91 }; | 95 }; |
106 return conn; | 110 return conn; |
107 } | 111 } |
108 | 112 |
109 static BOOL nn_get_addr(struct in_addr *addr, struct hostent *hst) | 113 static BOOL nn_get_addr(struct in_addr *addr, struct hostent *hst) |
110 { | 114 { |
111 if (hst != NULL) { | 115 if (hst != NULL) |
116 { | |
112 *addr = *(struct in_addr *) (hst->h_addr); | 117 *addr = *(struct in_addr *) (hst->h_addr); |
113 return TRUE; | 118 return TRUE; |
114 } else { | 119 } |
120 else | |
121 { | |
115 addr->s_addr = 0; | 122 addr->s_addr = 0; |
116 return FALSE; | 123 return FALSE; |
117 } | 124 } |
118 } | 125 } |
119 | 126 |
124 | 131 |
125 conn->proxy.type = type; | 132 conn->proxy.type = type; |
126 conn->proxy.port = port; | 133 conn->proxy.port = port; |
127 conn->proxy.host = th_strdup(host); | 134 conn->proxy.host = th_strdup(host); |
128 | 135 |
129 if (host != NULL) { | 136 if (host != NULL) |
137 { | |
130 conn->proxy.hst = nn_resolve_host(conn, host); | 138 conn->proxy.hst = nn_resolve_host(conn, host); |
131 nn_get_addr(&(conn->proxy.addr), conn->proxy.hst); | 139 nn_get_addr(&(conn->proxy.addr), conn->proxy.hst); |
132 } else | 140 } else |
133 return -2; | 141 return -2; |
134 | 142 |
142 | 150 |
143 if (conn == NULL) | 151 if (conn == NULL) |
144 return -1; | 152 return -1; |
145 | 153 |
146 conn->port = port; | 154 conn->port = port; |
147 if (host != NULL) { | 155 if (host != NULL) |
156 { | |
148 conn->host = th_strdup(host); | 157 conn->host = th_strdup(host); |
149 conn->hst = nn_resolve_host(conn, host); | 158 conn->hst = nn_resolve_host(conn, host); |
150 } | 159 } |
151 | 160 |
152 nn_get_addr(&(conn->addr), conn->hst); | 161 nn_get_addr(&(conn->addr), conn->hst); |
153 | 162 |
154 /* Prepare for connection */ | 163 /* Prepare for connection */ |
155 dest.sin_family = AF_INET; | 164 dest.sin_family = AF_INET; |
156 | 165 |
157 if (conn->proxy.type > NN_PROXY_NONE && conn->proxy.type < NN_PROXY_LAST) { | 166 if (conn->proxy.type > NN_PROXY_NONE && conn->proxy.type < NN_PROXY_LAST) |
167 { | |
158 dest.sin_port = htons(conn->proxy.port); | 168 dest.sin_port = htons(conn->proxy.port); |
159 dest.sin_addr = conn->proxy.addr; | 169 dest.sin_addr = conn->proxy.addr; |
160 | 170 |
161 nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n", | 171 nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n", |
162 nn_proxy_types[conn->proxy.type], | 172 nn_proxy_types[conn->proxy.type], |
163 inet_ntoa(conn->proxy.addr), conn->proxy.port); | 173 inet_ntoa(conn->proxy.addr), conn->proxy.port); |
164 } else { | 174 } |
175 else | |
176 { | |
165 dest.sin_port = htons(conn->port); | 177 dest.sin_port = htons(conn->port); |
166 dest.sin_addr = conn->addr; | 178 dest.sin_addr = conn->addr; |
167 | 179 |
168 nn_conn_msg(conn, "Connecting to %s:%d ...\n", | 180 nn_conn_msg(conn, "Connecting to %s:%d ...\n", |
169 inet_ntoa(conn->addr), conn->port); | 181 inet_ntoa(conn->addr), conn->port); |
170 } | 182 } |
171 | 183 |
172 if ((conn->socket = socket(PF_INET, SOCK_STREAM, 0)) == -1) { | 184 if ((conn->socket = socket(PF_INET, SOCK_STREAM, 0)) == -1) |
185 { | |
173 conn->err = nn_get_socket_errno(); | 186 conn->err = nn_get_socket_errno(); |
174 nn_conn_err(conn, "Could not open socket: %s\n", nn_get_socket_errstr(conn->err)); | 187 nn_conn_err(conn, "Could not open socket: %s\n", nn_get_socket_errstr(conn->err)); |
175 goto error; | 188 goto error; |
176 } | 189 } |
177 | 190 |
178 nn_conn_msg(conn, "Using socket %d.\n", conn->socket); | 191 nn_conn_msg(conn, "Using socket %d.\n", conn->socket); |
179 | 192 |
180 if (connect(conn->socket, (struct sockaddr *) &dest, sizeof(dest)) == -1) { | 193 if (connect(conn->socket, (struct sockaddr *) &dest, sizeof(dest)) == -1) |
194 { | |
181 conn->err = nn_get_socket_errno(); | 195 conn->err = nn_get_socket_errno(); |
182 nn_conn_err(conn, "Could not connect: %s\n", nn_get_socket_errstr(conn->err)); | 196 nn_conn_err(conn, "Could not connect: %s\n", nn_get_socket_errstr(conn->err)); |
183 goto error; | 197 goto error; |
184 } | 198 } |
185 | 199 |
186 FD_ZERO(&(conn->sockfds)); | 200 FD_ZERO(&(conn->sockfds)); |
187 FD_SET(conn->socket, &(conn->sockfds)); | 201 FD_SET(conn->socket, &(conn->sockfds)); |
188 | 202 |
189 /* Proxy-specific setup */ | 203 /* Proxy-specific setup */ |
190 if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A) { | 204 if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A) |
205 { | |
191 struct nn_socks_t *socksh; | 206 struct nn_socks_t *socksh; |
192 size_t bufsiz = sizeof(struct nn_socks_t) + strlen(userid) + 1; | 207 size_t bufsiz = sizeof(struct nn_socks_t) + strlen(userid) + 1; |
193 char *ptr, *buf; | 208 char *ptr, *buf; |
194 int tries, status = -1; | 209 int tries, status = -1; |
195 | 210 |
196 if (conn->proxy.type == NN_PROXY_SOCKS4A) | 211 if (conn->proxy.type == NN_PROXY_SOCKS4A) |
197 bufsiz += strlen(conn->host) + 1; | 212 bufsiz += strlen(conn->host) + 1; |
198 | 213 |
199 ptr = buf = th_malloc(bufsiz); | 214 ptr = buf = th_malloc(bufsiz); |
200 if (buf == NULL) { | 215 if (buf == NULL) |
216 { | |
201 conn->err = -1; | 217 conn->err = -1; |
202 nn_conn_err(conn, "Could not allocate memory for SOCKS negotiation buffer, %d bytes.\n", bufsiz); | 218 nn_conn_err(conn, "Could not allocate memory for SOCKS negotiation buffer, %d bytes.\n", bufsiz); |
203 goto error; | 219 goto error; |
204 } | 220 } |
205 | 221 |
215 socksh->addr = conn->addr.s_addr; | 231 socksh->addr = conn->addr.s_addr; |
216 ptr += sizeof(struct nn_socks_t); | 232 ptr += sizeof(struct nn_socks_t); |
217 | 233 |
218 strcpy(ptr, userid); | 234 strcpy(ptr, userid); |
219 | 235 |
220 if (conn->proxy.type == NN_PROXY_SOCKS4A) { | 236 if (conn->proxy.type == NN_PROXY_SOCKS4A) |
237 { | |
221 ptr += strlen(userid) + 1; | 238 ptr += strlen(userid) + 1; |
222 strcpy(ptr, conn->host); | 239 strcpy(ptr, conn->host); |
223 } | 240 } |
224 | 241 |
225 /* Send request */ | 242 /* Send request */ |
226 nn_conn_reset(conn); | 243 nn_conn_reset(conn); |
227 if (!nn_conn_send_buf(conn, buf, bufsiz)) { | 244 if (!nn_conn_send_buf(conn, buf, bufsiz)) |
245 { | |
228 th_free(buf); | 246 th_free(buf); |
229 nn_conn_err(conn, "Error sending SOCKS proxy request.\n"); | 247 nn_conn_err(conn, "Error sending SOCKS proxy request.\n"); |
230 goto error; | 248 goto error; |
231 } | 249 } |
232 th_free(buf); | 250 th_free(buf); |
233 | 251 |
234 /* Wait for SOCKS server to reply */ | 252 /* Wait for SOCKS server to reply */ |
235 for (status = tries = 1; tries <= 20 && status > 0; tries++) { | 253 for (status = tries = 1; tries <= 20 && status > 0; tries++) |
254 { | |
236 #ifdef __WIN32 | 255 #ifdef __WIN32 |
237 Sleep(50); | 256 Sleep(50); |
238 #else | 257 #else |
239 usleep(50000); | 258 usleep(50000); |
240 #endif | 259 #endif |
241 nn_conn_reset(conn); | 260 nn_conn_reset(conn); |
242 status = nn_conn_pull(conn); | 261 status = nn_conn_pull(conn); |
243 } | 262 } |
244 | 263 |
245 /* Check results */ | 264 /* Check results */ |
246 if (status == 0) { | 265 if (status == 0) |
266 { | |
247 struct nn_socks_res_t *res = (struct nn_socks_res_t *) &(conn->buf); | 267 struct nn_socks_res_t *res = (struct nn_socks_res_t *) &(conn->buf); |
248 if (res->nb != 0) { | 268 if (res->nb != 0) |
269 { | |
249 nn_conn_err(conn, "Invalid SOCKS server reply, does not begin with NUL byte (%d).\n", res->nb); | 270 nn_conn_err(conn, "Invalid SOCKS server reply, does not begin with NUL byte (%d).\n", res->nb); |
250 goto error; | 271 goto error; |
251 } | 272 } |
252 if (res->result != 0x5a) { | 273 if (res->result != 0x5a) |
274 { | |
253 char *s = NULL; | 275 char *s = NULL; |
254 switch (res->result) { | 276 switch (res->result) |
277 { | |
255 case 0x5b: s = "Request rejected or failed"; break; | 278 case 0x5b: s = "Request rejected or failed"; break; |
256 case 0x5c: s = "Request failed because client is not running identd (or not reachable from the server)"; break; | 279 case 0x5c: s = "Request failed because client is not running identd (or not reachable from the server)"; break; |
257 case 0x5d: s = "Request failed because client's identd could not confirm the user ID string in the request"; break; | 280 case 0x5d: s = "Request failed because client's identd could not confirm the user ID string in the request"; break; |
258 default: s = "Unknown SOCKS error response"; break; | 281 default: s = "Unknown SOCKS error response"; break; |
259 } | 282 } |
260 nn_conn_err(conn, "SOCKS setup failed, 0x%02x: %s.\n", res->result, s); | 283 nn_conn_err(conn, "SOCKS setup failed, 0x%02x: %s.\n", res->result, s); |
261 goto error; | 284 goto error; |
262 } | 285 } |
263 nn_conn_msg(conn, "SOCKS connection established!\n"); | 286 nn_conn_msg(conn, "SOCKS connection established!\n"); |
264 } | 287 } |
265 else if (status < 0) { | 288 else if (status < 0) |
289 { | |
266 nn_conn_err(conn, "Proxy negotiation failed at try %d with network error: %d\n", tries, status); | 290 nn_conn_err(conn, "Proxy negotiation failed at try %d with network error: %d\n", tries, status); |
267 goto error; | 291 goto error; |
268 } | 292 } |
269 else { | 293 else |
294 { | |
270 nn_conn_err(conn, "Proxy negotiation timed out.\n"); | 295 nn_conn_err(conn, "Proxy negotiation timed out.\n"); |
271 goto error; | 296 goto error; |
272 } | 297 } |
273 } | 298 } |
274 | 299 |
285 void nn_conn_close(nn_conn_t *conn) | 310 void nn_conn_close(nn_conn_t *conn) |
286 { | 311 { |
287 if (conn == NULL) | 312 if (conn == NULL) |
288 return; | 313 return; |
289 | 314 |
290 if (conn->socket >= 0) { | 315 if (conn->socket >= 0) |
316 { | |
291 #ifdef __WIN32 | 317 #ifdef __WIN32 |
292 closesocket(conn->socket); | 318 closesocket(conn->socket); |
293 #else | 319 #else |
294 close(conn->socket); | 320 close(conn->socket); |
295 #endif | 321 #endif |
308 BOOL nn_conn_send_buf(nn_conn_t *conn, const char *buf, const size_t len) | 334 BOOL nn_conn_send_buf(nn_conn_t *conn, const char *buf, const size_t len) |
309 { | 335 { |
310 size_t bufLeft = len; | 336 size_t bufLeft = len; |
311 const char *bufPtr = buf; | 337 const char *bufPtr = buf; |
312 | 338 |
313 while (bufLeft > 0) { | 339 while (bufLeft > 0) |
340 { | |
314 ssize_t bufSent; | 341 ssize_t bufSent; |
315 bufSent = send(conn->socket, bufPtr, bufLeft, 0); | 342 bufSent = send(conn->socket, bufPtr, bufLeft, 0); |
316 if (bufSent < 0) { | 343 if (bufSent < 0) |
344 { | |
317 conn->err = nn_get_socket_errno(); | 345 conn->err = nn_get_socket_errno(); |
318 nn_conn_err(conn, "nn_conn_send_buf() failed: %s", nn_get_socket_errstr(conn->err)); | 346 nn_conn_err(conn, "nn_conn_send_buf() failed: %s", nn_get_socket_errstr(conn->err)); |
319 return FALSE; | 347 return FALSE; |
320 } | 348 } |
321 bufLeft -= bufSent; | 349 bufLeft -= bufSent; |
325 return TRUE; | 353 return TRUE; |
326 } | 354 } |
327 | 355 |
328 void nn_conn_reset(nn_conn_t *conn) | 356 void nn_conn_reset(nn_conn_t *conn) |
329 { | 357 { |
330 if (conn != NULL) { | 358 if (conn != NULL) |
359 { | |
331 conn->ptr = conn->buf; | 360 conn->ptr = conn->buf; |
332 conn->got = conn->total = 0; | 361 conn->got = conn->total = 0; |
333 } | 362 } |
334 } | 363 } |
335 | 364 |
345 /* Check for incoming data */ | 374 /* Check for incoming data */ |
346 socktv.tv_sec = 0; | 375 socktv.tv_sec = 0; |
347 socktv.tv_usec = NN_DELAY_USEC; | 376 socktv.tv_usec = NN_DELAY_USEC; |
348 tmpfds = conn->sockfds; | 377 tmpfds = conn->sockfds; |
349 | 378 |
350 if ((result = select(conn->socket + 1, &tmpfds, NULL, NULL, &socktv)) == -1) { | 379 if ((result = select(conn->socket + 1, &tmpfds, NULL, NULL, &socktv)) == -1) |
380 { | |
351 conn->err = nn_get_socket_errno(); | 381 conn->err = nn_get_socket_errno(); |
352 if (conn->err != EINTR) { | 382 if (conn->err != EINTR) |
383 { | |
353 nn_conn_err(conn, "Error occured in select(%d, sockfds): %d, %s\n", | 384 nn_conn_err(conn, "Error occured in select(%d, sockfds): %d, %s\n", |
354 socket, conn->err, nn_get_socket_errstr(conn->err)); | 385 socket, conn->err, nn_get_socket_errstr(conn->err)); |
355 return -1; | 386 return -1; |
356 } | 387 } |
357 } else | 388 } else |
358 if (FD_ISSET(conn->socket, &tmpfds)) { | 389 if (FD_ISSET(conn->socket, &tmpfds)) |
390 { | |
359 conn->got = recv(conn->socket, conn->ptr, NN_CONNBUF_SIZE - conn->total, 0); | 391 conn->got = recv(conn->socket, conn->ptr, NN_CONNBUF_SIZE - conn->total, 0); |
360 if (conn->got < 0) { | 392 if (conn->got < 0) |
393 { | |
361 conn->err = nn_get_socket_errno(); | 394 conn->err = nn_get_socket_errno(); |
362 nn_conn_err(conn, "Error in recv: %d, %s\n", conn->err, nn_get_socket_errstr(conn->err)); | 395 nn_conn_err(conn, "Error in recv: %d, %s\n", conn->err, nn_get_socket_errstr(conn->err)); |
363 return -2; | 396 return -2; |
364 } else if (conn->got == 0) { | 397 } else if (conn->got == 0) |
398 { | |
365 nn_conn_err(conn, "Server closed connection.\n"); | 399 nn_conn_err(conn, "Server closed connection.\n"); |
366 conn->status = NN_CONN_CLOSED; | 400 conn->status = NN_CONN_CLOSED; |
367 return -3; | 401 return -3; |
368 } else { | 402 } |
403 else | |
404 { | |
369 /* Handle protocol data */ | 405 /* Handle protocol data */ |
370 conn->total += conn->got; | 406 conn->total += conn->got; |
371 conn->ptr += conn->got; | 407 conn->ptr += conn->got; |
372 return 0; | 408 return 0; |
373 } | 409 } |
390 { | 426 { |
391 #ifdef __WIN32 | 427 #ifdef __WIN32 |
392 /* Initialize WinSock, if needed */ | 428 /* Initialize WinSock, if needed */ |
393 WSADATA wsaData; | 429 WSADATA wsaData; |
394 int err = WSAStartup(0x0101, &wsaData); | 430 int err = WSAStartup(0x0101, &wsaData); |
395 if (err != 0) { | 431 if (err != 0) |
432 { | |
396 THERR("Could not initialize WinSock library (err=%d).\n", err); | 433 THERR("Could not initialize WinSock library (err=%d).\n", err); |
397 return FALSE; | 434 return FALSE; |
398 } | 435 } |
399 #endif | 436 #endif |
400 return TRUE; | 437 return TRUE; |
422 | 459 |
423 resSize = strlen(str) + NN_ALLOC_SIZE; | 460 resSize = strlen(str) + NN_ALLOC_SIZE; |
424 if ((result = th_malloc(resSize)) == NULL) | 461 if ((result = th_malloc(resSize)) == NULL) |
425 return NULL; | 462 return NULL; |
426 | 463 |
427 while (*s) { | 464 while (*s) |
428 switch (*s) { | 465 { |
466 switch (*s) | |
467 { | |
429 case 32: | 468 case 32: |
430 PUSHCHAR('+'); | 469 PUSHCHAR('+'); |
431 break; | 470 break; |
432 | 471 |
433 default: | 472 default: |
434 if (th_isalnum(*s)) | 473 if (th_isalnum(*s)) |
435 PUSHCHAR(*s); | 474 PUSHCHAR(*s); |
436 else { | 475 else |
476 { | |
437 char tmpStr[4]; | 477 char tmpStr[4]; |
438 snprintf(tmpStr, sizeof(tmpStr), "%2X", (unsigned char) *s); | 478 snprintf(tmpStr, sizeof(tmpStr), "%2X", (unsigned char) *s); |
439 PUSHCHAR('%'); | 479 PUSHCHAR('%'); |
440 PUSHSTR(tmpStr); | 480 PUSHSTR(tmpStr); |
441 } | 481 } |
477 | 517 |
478 resSize = strlen(str) + NN_ALLOC_SIZE; | 518 resSize = strlen(str) + NN_ALLOC_SIZE; |
479 if ((result = th_malloc(resSize)) == NULL) | 519 if ((result = th_malloc(resSize)) == NULL) |
480 return NULL; | 520 return NULL; |
481 | 521 |
482 while (*s) { | 522 while (*s) |
483 switch (*s) { | 523 { |
524 switch (*s) | |
525 { | |
484 case '+': | 526 case '+': |
485 PUSHCHAR(' '); | 527 PUSHCHAR(' '); |
486 s++; | 528 s++; |
487 break; | 529 break; |
488 | 530 |
502 s++; | 544 s++; |
503 if (*s == '%') | 545 if (*s == '%') |
504 PUSHCHAR('%'); | 546 PUSHCHAR('%'); |
505 else if ((c = getHexDigit(*s, 4)) >= 0) { | 547 else if ((c = getHexDigit(*s, 4)) >= 0) { |
506 int i = getHexDigit(*(++s), 0); | 548 int i = getHexDigit(*(++s), 0); |
507 if (i >= 0) { | 549 if (i >= 0) |
550 { | |
508 PUSHCHAR(c | i); | 551 PUSHCHAR(c | i); |
509 } else { | 552 } |
553 else | |
554 { | |
510 PUSHCHAR('§'); | 555 PUSHCHAR('§'); |
511 PUSHCHAR(*s); | 556 PUSHCHAR(*s); |
512 } | 557 } |
513 } else { | 558 } |
559 else | |
560 { | |
514 PUSHCHAR('§'); | 561 PUSHCHAR('§'); |
515 PUSHCHAR(*s); | 562 PUSHCHAR(*s); |
516 } | 563 } |
517 s++; | 564 s++; |
518 break; | 565 break; |
538 | 585 |
539 resSize = strlen(str) + NN_ALLOC_SIZE; | 586 resSize = strlen(str) + NN_ALLOC_SIZE; |
540 if ((result = th_malloc(resSize)) == NULL) | 587 if ((result = th_malloc(resSize)) == NULL) |
541 return NULL; | 588 return NULL; |
542 | 589 |
543 while (*s) { | 590 while (*s) |
544 if (*s == '<') { | 591 { |
592 if (*s == '<') | |
593 { | |
545 while (*s && *s != '>') s++; | 594 while (*s && *s != '>') s++; |
546 if (*s == '>') s++; | 595 if (*s == '>') s++; |
547 } else | 596 } else |
548 PUSHCHAR(*s++); | 597 PUSHCHAR(*s++); |
549 } | 598 } |
551 | 600 |
552 return result; | 601 return result; |
553 } | 602 } |
554 | 603 |
555 | 604 |
556 typedef struct { | 605 typedef struct |
606 { | |
557 char c; | 607 char c; |
558 char *ent; | 608 char *ent; |
559 } html_entity_t; | 609 } html_entity_t; |
560 | 610 |
561 | 611 |
562 static const html_entity_t HTMLEntities[] = { | 612 static const html_entity_t HTMLEntities[] = |
613 { | |
563 { '<', "<" }, | 614 { '<', "<" }, |
564 { '>', ">" }, | 615 { '>', ">" }, |
565 }; | 616 }; |
566 | 617 |
567 static const int numHTMLEntities = sizeof(HTMLEntities) / sizeof(HTMLEntities[0]); | 618 static const int numHTMLEntities = sizeof(HTMLEntities) / sizeof(HTMLEntities[0]); |
577 | 628 |
578 resSize = strlen(str) + NN_ALLOC_SIZE; | 629 resSize = strlen(str) + NN_ALLOC_SIZE; |
579 if ((result = th_malloc(resSize)) == NULL) | 630 if ((result = th_malloc(resSize)) == NULL) |
580 return NULL; | 631 return NULL; |
581 | 632 |
582 while (*s) { | 633 while (*s) |
634 { | |
583 int i; | 635 int i; |
584 BOOL found = FALSE; | 636 BOOL found = FALSE; |
585 for (i = 0; i < numHTMLEntities; i++) | 637 for (i = 0; i < numHTMLEntities; i++) |
586 if (HTMLEntities[i].c == *s) { | 638 if (HTMLEntities[i].c == *s) |
639 { | |
587 PUSHSTR(HTMLEntities[i].ent); | 640 PUSHSTR(HTMLEntities[i].ent); |
588 found = TRUE; | 641 found = TRUE; |
589 break; | 642 break; |
590 } | 643 } |
591 if (!found) PUSHCHAR(*s); | 644 if (!found) PUSHCHAR(*s); |
608 | 661 |
609 resSize = strlen(str); | 662 resSize = strlen(str); |
610 if ((result = th_malloc(resSize)) == NULL) | 663 if ((result = th_malloc(resSize)) == NULL) |
611 return NULL; | 664 return NULL; |
612 | 665 |
613 while (*s) { | 666 while (*s) |
614 if (*s == '&') { | 667 { |
668 if (*s == '&') | |
669 { | |
615 int i; | 670 int i; |
616 BOOL found = FALSE; | 671 BOOL found = FALSE; |
617 for (i = 0; i < numHTMLEntities; i++) { | 672 for (i = 0; i < numHTMLEntities; i++) |
673 { | |
618 const html_entity_t *ent = &HTMLEntities[i]; | 674 const html_entity_t *ent = &HTMLEntities[i]; |
619 int len = strlen(ent->ent); | 675 int len = strlen(ent->ent); |
620 if (!strncmp(s, ent->ent, len)) { | 676 if (!strncmp(s, ent->ent, len)) |
677 { | |
621 PUSHCHAR(ent->c); | 678 PUSHCHAR(ent->c); |
622 s += len; | 679 s += len; |
623 found = TRUE; | 680 found = TRUE; |
624 break; | 681 break; |
625 } | 682 } |
675 return FALSE; | 732 return FALSE; |
676 | 733 |
677 msg = th_strdup_printf("<USER>%s</USER><MESSAGE>%s</MESSAGE>", user, tmp); | 734 msg = th_strdup_printf("<USER>%s</USER><MESSAGE>%s</MESSAGE>", user, tmp); |
678 th_free(tmp); | 735 th_free(tmp); |
679 | 736 |
680 if (msg != NULL) { | 737 if (msg != NULL) |
738 { | |
681 BOOL ret = nn_conn_send_buf(conn, msg, strlen(msg) + 1); | 739 BOOL ret = nn_conn_send_buf(conn, msg, strlen(msg) + 1); |
682 th_free(msg); | 740 th_free(msg); |
683 return ret; | 741 return ret; |
684 } else | 742 } else |
685 return FALSE; | 743 return FALSE; |
690 { | 748 { |
691 if (buf->len+1 >= buf->size) return -3; | 749 if (buf->len+1 >= buf->size) return -3; |
692 | 750 |
693 if (pos < 0) | 751 if (pos < 0) |
694 return -1; | 752 return -1; |
695 else if (pos >= buf->len) { | 753 else if (pos >= buf->len) |
696 buf->data[buf->len++] = ch; | 754 buf->data[buf->len++] = ch; |
697 } else { | 755 else |
698 buf->data[pos] = ch; | 756 buf->data[pos] = ch; |
699 } | 757 |
700 return 0; | 758 return 0; |
701 } | 759 } |
702 | 760 |
703 | 761 |
704 int nn_editbuf_insert(nn_editbuf_t *buf, ssize_t pos, int ch) | 762 int nn_editbuf_insert(nn_editbuf_t *buf, ssize_t pos, int ch) |
705 { | 763 { |
706 if (buf->len+1 >= buf->size) return -3; | 764 if (buf->len+1 >= buf->size) return -3; |
707 | 765 |
708 if (pos < 0) | 766 if (pos < 0) |
709 return -1; | 767 return -1; |
710 else if (pos >= buf->len) { | 768 else if (pos >= buf->len) |
769 { | |
711 buf->data[buf->len] = ch; | 770 buf->data[buf->len] = ch; |
712 } else { | 771 } |
772 else | |
773 { | |
713 memmove(&(buf->data[pos+1]), &(buf->data[pos]), buf->len - pos + 1); | 774 memmove(&(buf->data[pos+1]), &(buf->data[pos]), buf->len - pos + 1); |
714 buf->data[pos] = ch; | 775 buf->data[pos] = ch; |
715 } | 776 } |
716 buf->len++; | 777 buf->len++; |
717 return 0; | 778 return 0; |
720 | 781 |
721 int nn_editbuf_delete(nn_editbuf_t *buf, ssize_t pos) | 782 int nn_editbuf_delete(nn_editbuf_t *buf, ssize_t pos) |
722 { | 783 { |
723 if (pos < 0) | 784 if (pos < 0) |
724 return -1; | 785 return -1; |
725 else if (pos < buf->len) { | 786 else if (pos < buf->len) |
787 { | |
726 memmove(&(buf->data[pos]), &(buf->data[pos+1]), buf->len - pos); | 788 memmove(&(buf->data[pos]), &(buf->data[pos+1]), buf->len - pos); |
727 buf->len--; | 789 buf->len--; |
728 return 0; | 790 return 0; |
729 } else | 791 } else |
730 return -2; | 792 return -2; |
749 } | 811 } |
750 | 812 |
751 | 813 |
752 void nn_editbuf_free(nn_editbuf_t *buf) | 814 void nn_editbuf_free(nn_editbuf_t *buf) |
753 { | 815 { |
754 if (buf != NULL) { | 816 if (buf != NULL) |
817 { | |
755 th_free(buf->data); | 818 th_free(buf->data); |
756 th_free(buf); | 819 th_free(buf); |
757 } | 820 } |
758 } | 821 } |
759 | 822 |
785 return NULL; | 848 return NULL; |
786 | 849 |
787 if (start < 0 || end > buf->len || start >= buf->len) | 850 if (start < 0 || end > buf->len || start >= buf->len) |
788 return NULL; | 851 return NULL; |
789 | 852 |
790 if (end < 0) { | 853 if (end < 0) |
854 { | |
791 siz = buf->len - start + 1; | 855 siz = buf->len - start + 1; |
792 } else if (start <= end) { | 856 } |
857 else if (start <= end) | |
858 { | |
793 siz = end - start + 1; | 859 siz = end - start + 1; |
794 } else | 860 } else |
795 return NULL; | 861 return NULL; |
796 | 862 |
797 if ((str = th_malloc(siz + 1)) == NULL) | 863 if ((str = th_malloc(siz + 1)) == NULL) |
822 /* | 888 /* |
823 int n = 0; | 889 int n = 0; |
824 const uint8_t *c = (uint8_t *)name; | 890 const uint8_t *c = (uint8_t *)name; |
825 uint8_t hash = 0xff; | 891 uint8_t hash = 0xff; |
826 | 892 |
827 while (*c && n < 4) { | 893 while (*c && n < 4) |
894 { | |
828 hash = (hash << 1) ^ tolower(*c); | 895 hash = (hash << 1) ^ tolower(*c); |
829 c++; n++; | 896 c++; n++; |
830 } | 897 } |
831 | 898 |
832 return (hash & 0xff); | 899 return (hash & 0xff); |
847 int i; | 914 int i; |
848 | 915 |
849 if (list == NULL) return NULL; | 916 if (list == NULL) return NULL; |
850 | 917 |
851 for (i = 0; i < NN_NUM_BUCKETS; i++) | 918 for (i = 0; i < NN_NUM_BUCKETS; i++) |
852 if (list->buckets[i] != NULL) { | 919 if (list->buckets[i] != NULL) |
920 { | |
853 nn_user_t *curr = list->buckets[i]; | 921 nn_user_t *curr = list->buckets[i]; |
854 while (curr != NULL) { | 922 while (curr != NULL) |
923 { | |
855 if (func(curr) != 0) | 924 if (func(curr) != 0) |
856 return curr; | 925 return curr; |
857 curr = curr->next; | 926 curr = curr->next; |
858 } | 927 } |
859 } | 928 } |
867 uint8_t hash; | 936 uint8_t hash; |
868 | 937 |
869 if (list == NULL) return NULL; | 938 if (list == NULL) return NULL; |
870 | 939 |
871 hash = nn_hash_user(name); | 940 hash = nn_hash_user(name); |
872 if (list->buckets[hash] != NULL) { | 941 if (list->buckets[hash] != NULL) |
942 { | |
873 nn_user_t *curr = list->buckets[hash]; | 943 nn_user_t *curr = list->buckets[hash]; |
874 while (curr != NULL) { | 944 while (curr != NULL) |
945 { | |
875 if (th_strcasecmp(curr->name, name) == 0) | 946 if (th_strcasecmp(curr->name, name) == 0) |
876 return curr; | 947 return curr; |
877 curr = curr->next; | 948 curr = curr->next; |
878 } | 949 } |
879 } | 950 } |
883 | 954 |
884 | 955 |
885 static nn_user_t *nn_user_match_do(nn_user_t *list, const char *pattern, size_t len) | 956 static nn_user_t *nn_user_match_do(nn_user_t *list, const char *pattern, size_t len) |
886 { | 957 { |
887 nn_user_t *curr = list; | 958 nn_user_t *curr = list; |
888 while (curr != NULL) { | 959 |
960 while (curr != NULL) | |
961 { | |
889 if (len <= strlen(curr->name) && th_strncasecmp(curr->name, pattern, len) == 0) | 962 if (len <= strlen(curr->name) && th_strncasecmp(curr->name, pattern, len) == 0) |
890 return curr; | 963 return curr; |
891 curr = curr->next; | 964 curr = curr->next; |
892 } | 965 } |
893 return NULL; | 966 return NULL; |
899 uint8_t hash; | 972 uint8_t hash; |
900 | 973 |
901 if (list == NULL || pattern == NULL) return NULL; | 974 if (list == NULL || pattern == NULL) return NULL; |
902 | 975 |
903 hash = nn_hash_user(pattern); | 976 hash = nn_hash_user(pattern); |
904 if (list->buckets[hash] != NULL) { | 977 if (list->buckets[hash] != NULL) |
978 { | |
905 nn_user_t *curr = list->buckets[hash]; | 979 nn_user_t *curr = list->buckets[hash]; |
906 size_t len = strlen(pattern); | 980 size_t len = strlen(pattern); |
907 | 981 |
908 if (current != NULL) { | 982 if (current != NULL) |
983 { | |
909 nn_user_t *found = NULL; | 984 nn_user_t *found = NULL; |
910 while (curr != NULL) { | 985 while (curr != NULL) |
911 if (th_strcasecmp(curr->name, current) == 0) { | 986 { |
987 if (th_strcasecmp(curr->name, current) == 0) | |
988 { | |
912 if (again) | 989 if (again) |
913 return curr; | 990 return curr; |
914 found = curr->next; | 991 found = curr->next; |
915 break; | 992 break; |
916 } | 993 } |
971 if (list == NULL || name == NULL) | 1048 if (list == NULL || name == NULL) |
972 return -1; | 1049 return -1; |
973 | 1050 |
974 /* Check if username is already there */ | 1051 /* Check if username is already there */ |
975 hash = nn_hash_user(name); | 1052 hash = nn_hash_user(name); |
976 if (list->buckets[hash] != NULL) { | 1053 if (list->buckets[hash] != NULL) |
1054 { | |
977 nn_user_t *curr, *prev; | 1055 nn_user_t *curr, *prev; |
978 curr = list->buckets[hash]; | 1056 curr = list->buckets[hash]; |
979 prev = NULL; | 1057 prev = NULL; |
980 while (curr != NULL) { | 1058 while (curr != NULL) |
981 if (th_strcasecmp(curr->name, name) == 0) { | 1059 { |
1060 if (th_strcasecmp(curr->name, name) == 0) | |
1061 { | |
982 if (prev) | 1062 if (prev) |
983 prev->next = curr->next; | 1063 prev->next = curr->next; |
984 else | 1064 else |
985 list->buckets[hash] = curr->next; | 1065 list->buckets[hash] = curr->next; |
986 | 1066 |
987 nn_user_free(curr); | 1067 nn_user_free(curr); |
988 | 1068 |
989 return 0; | 1069 return 0; |
990 } else { | 1070 } |
1071 else | |
1072 { | |
991 prev = curr; | 1073 prev = curr; |
992 curr = curr->next; | 1074 curr = curr->next; |
993 } | 1075 } |
994 } | 1076 } |
995 } | 1077 } |
1024 | 1106 |
1025 | 1107 |
1026 void nn_user_free_list(nn_user_t *list) | 1108 void nn_user_free_list(nn_user_t *list) |
1027 { | 1109 { |
1028 nn_user_t *next, *curr = list; | 1110 nn_user_t *next, *curr = list; |
1029 while (curr != NULL) { | 1111 |
1112 while (curr != NULL) | |
1113 { | |
1030 next = curr->next; | 1114 next = curr->next; |
1031 nn_user_free(curr); | 1115 nn_user_free(curr); |
1032 curr = next; | 1116 curr = next; |
1033 } | 1117 } |
1034 } | 1118 } |
1037 { | 1121 { |
1038 int i; | 1122 int i; |
1039 if (hash == NULL) | 1123 if (hash == NULL) |
1040 return; | 1124 return; |
1041 | 1125 |
1042 for (i = 0; i < NN_NUM_BUCKETS; i++) { | 1126 for (i = 0; i < NN_NUM_BUCKETS; i++) |
1127 { | |
1043 nn_user_free_list(hash->buckets[i]); | 1128 nn_user_free_list(hash->buckets[i]); |
1044 hash->buckets[i] = NULL; | 1129 hash->buckets[i] = NULL; |
1045 } | 1130 } |
1046 | 1131 |
1047 th_free(hash); | 1132 th_free(hash); |
1073 nn_window_t *res = th_calloc(1, sizeof(nn_window_t)); | 1158 nn_window_t *res = th_calloc(1, sizeof(nn_window_t)); |
1074 | 1159 |
1075 if (res == NULL) return NULL; | 1160 if (res == NULL) return NULL; |
1076 | 1161 |
1077 res->data = th_ringbuf_new(NN_BACKBUF_LEN, th_free); | 1162 res->data = th_ringbuf_new(NN_BACKBUF_LEN, th_free); |
1078 if (res->data == NULL) { | 1163 if (res->data == NULL) |
1164 { | |
1079 th_free(res); | 1165 th_free(res); |
1080 return NULL; | 1166 return NULL; |
1081 } | 1167 } |
1082 | 1168 |
1083 res->id = th_strdup(id); | 1169 res->id = th_strdup(id); |
1086 } | 1172 } |
1087 | 1173 |
1088 | 1174 |
1089 void nn_window_free(nn_window_t *win) | 1175 void nn_window_free(nn_window_t *win) |
1090 { | 1176 { |
1091 if (win != NULL) { | 1177 if (win != NULL) |
1178 { | |
1092 th_ringbuf_free(win->data); | 1179 th_ringbuf_free(win->data); |
1093 th_free(win->id); | 1180 th_free(win->id); |
1094 th_free(win); | 1181 th_free(win); |
1095 } | 1182 } |
1096 } | 1183 } |