comparison nnchat.c @ 62:ff5d74f0d428

Moved some functions to "libnnchat".
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 11 Nov 2008 21:57:51 +0200
parents b802a799c31a
children afd90bbb3af6
comparison
equal deleted inserted replaced
61:b802a799c31a 62:ff5d74f0d428
1 /* 1 /*
2 * NNChat - Custom chat client for NewbieNudes.com chatrooms 2 * NNChat - Custom chat client for NewbieNudes.com chatrooms
3 * Written by Matti 'ccr' Hämäläinen 3 * Written by Matti 'ccr' Hämäläinen
4 * (C) Copyright 2008 Tecnic Software productions (TNSP) 4 * (C) Copyright 2008 Tecnic Software productions (TNSP)
5 */ 5 */
6 #include <sys/socket.h> 6 #include "libnnchat.h"
7 #include <sys/types.h>
8 #include <arpa/inet.h>
9 #include <sys/time.h>
10 #include <netdb.h>
11
12 #include <unistd.h>
13 #include <stdlib.h> 7 #include <stdlib.h>
14 #include <stdio.h>
15 #include "th_args.h" 8 #include "th_args.h"
16 #include "th_string.h"
17 #include <string.h> 9 #include <string.h>
18 #include <errno.h> 10 #include <errno.h>
19 #include <time.h> 11 #include <time.h>
20 #include <ncurses.h> 12 #include <ncurses.h>
21 13
22 14
23 #define SET_MAX_BACKBUF (1024) 15 #define SET_MAX_BACKBUF (1024)
24 #define SET_MAX_HISTORY (16) 16 #define SET_MAX_HISTORY (16)
25 #define SET_BUFSIZE (4096)
26 #define SET_ALLOC_SIZE (128)
27 #define SET_DELAY (15) 17 #define SET_DELAY (15)
28 #define SET_DELAY_USEC (SET_DELAY * 1000) 18 #define SET_DELAY_USEC (SET_DELAY * 1000)
29
30
31 typedef struct {
32 char c;
33 char *ent;
34 } html_entity_t;
35
36
37 html_entity_t HTMLEntities[] = {
38 { '<', "&lt;" },
39 { '>', "&gt;" },
40 };
41
42 const int numHTMLEntities = (sizeof(HTMLEntities) / sizeof(HTMLEntities[0]));
43 19
44 20
45 /* Options 21 /* Options
46 */ 22 */
47 int optPort = 8005; 23 int optPort = 8005;
382 wattrset(editWin, A_NORMAL); 358 wattrset(editWin, A_NORMAL);
383 } 359 }
384 wrefresh(editWin); 360 wrefresh(editWin);
385 } 361 }
386 362
387 int openConnection(struct in_addr *addr, const int port)
388 {
389 struct sockaddr_in tmpAddr;
390 int sock = -1;
391
392 tmpAddr.sin_family = AF_INET;
393 tmpAddr.sin_port = htons(port);
394 tmpAddr.sin_addr = *addr;
395
396 THMSG(1, "Connecting to %s:%d ...\n",
397 inet_ntoa(tmpAddr.sin_addr), port);
398
399 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) {
400 THERR("Could not open socket: %s\n", strerror(errno));
401 return -2;
402 }
403
404 THMSG(2, "Using socket %d.\n", sock);
405
406 if (connect(sock, (struct sockaddr *) &tmpAddr, sizeof(tmpAddr)) == -1) {
407 THERR("Could not connect: %s\n", strerror(errno));
408 return -5;
409 }
410
411 return sock;
412 }
413
414
415 void closeConnection(const int sock)
416 {
417 if (sock >= 0) {
418 close(sock);
419 }
420 }
421
422
423 BOOL sendToSocket(const int sock, char *buf, const size_t bufLen)
424 {
425 size_t bufLeft = bufLen;
426 char *bufPtr = buf;
427
428 while (bufLeft > 0) {
429 ssize_t bufSent;
430 bufSent = send(sock, bufPtr, bufLeft, 0);
431 if (bufSent < 0) return FALSE;
432 bufLeft -= bufSent;
433 bufPtr += bufSent;
434 }
435 return TRUE;
436 }
437
438 int printWin(WINDOW *win, const char *fmt) 363 int printWin(WINDOW *win, const char *fmt)
439 { 364 {
440 const char *s = fmt; 365 const char *s = fmt;
441 int col = 0; 366 int col = 0;
442 367
468 } 393 }
469 } 394 }
470 return 0; 395 return 0;
471 } 396 }
472 397
398
473 int printFile(FILE *outFile, const char *fmt) 399 int printFile(FILE *outFile, const char *fmt)
474 { 400 {
475 const char *s = fmt; 401 const char *s = fmt;
476 402
477 while (*s) { 403 while (*s) {
492 } 418 }
493 419
494 return 0; 420 return 0;
495 } 421 }
496 422
423
497 void printMsg(char *fmt, ...) 424 void printMsg(char *fmt, ...)
498 { 425 {
499 char tmpStr[128] = "", buf[8192]; 426 char tmpStr[128] = "", buf[8192];
500 va_list ap; 427 va_list ap;
501 time_t timeStamp; 428 time_t timeStamp;
522 wrefresh(mainWin); 449 wrefresh(mainWin);
523 } 450 }
524 } 451 }
525 452
526 453
527 BOOL bufRealloc(char **buf, size_t *size, size_t add)
528 {
529 return ((*buf = th_realloc(*buf, *size + add)) != NULL);
530 }
531
532 #define PUSHCHAR(x) bufPushChar(&result, &resSize, &resPos, x)
533 BOOL bufPushChar(char **buf, size_t *size, size_t *pos, char ch)
534 {
535 if (*pos >= *size && !bufRealloc(buf, size, SET_ALLOC_SIZE))
536 return FALSE;
537
538 (*buf)[*pos] = ch;
539 (*pos)++;
540 return TRUE;
541 }
542
543 #define PUSHSTR(x) bufPushStr(&result, &resSize, &resPos, x)
544 BOOL bufPushStr(char **buf, size_t *size, size_t *pos, char *str)
545 {
546 size_t tmpLen;
547
548 if (!str) return FALSE;
549 tmpLen = strlen(str);
550
551 if ((*pos + tmpLen) >= *size && !bufRealloc(buf, size, tmpLen + SET_ALLOC_SIZE))
552 return FALSE;
553
554 strcpy(*buf + *pos, str);
555 (*pos) += tmpLen;
556 return TRUE;
557 }
558
559
560 char *encodeStr1(char *str)
561 {
562 char *result, *s = str;
563 size_t resSize, resPos = 0;
564
565 if (!str) return NULL;
566
567 resSize = strlen(str) + SET_ALLOC_SIZE;
568 if ((result = th_malloc(resSize)) == NULL)
569 return NULL;
570
571 while (*s) {
572 switch (*s) {
573 case 32:
574 PUSHCHAR('+');
575 break;
576
577 default:
578 if (th_isalnum(*s))
579 PUSHCHAR(*s);
580 else {
581 char tmpStr[4];
582 sprintf(tmpStr, "%2X", (unsigned char) *s);
583 PUSHCHAR('%');
584 PUSHSTR(tmpStr);
585 }
586 break;
587 }
588 s++;
589 }
590 PUSHCHAR(0);
591
592 return result;
593 }
594
595
596 int getxdigit(int c, int shift)
597 {
598 int i;
599
600 if (c >= 'A' && c <= 'F')
601 i = c - 'A' + 10;
602 else if (c >= 'a' && c <= 'f')
603 i = c - 'a' + 10;
604 else if (c >= '0' && c <= '9')
605 i = c - '0';
606 else
607 return -1;
608
609 return i << shift;
610 }
611
612
613 char *decodeStr1(char *str)
614 {
615 char *result, *s = str;
616 size_t resSize, resPos = 0;
617 int c;
618
619 if (!str) return NULL;
620
621 resSize = strlen(str) + SET_ALLOC_SIZE;
622 if ((result = th_malloc(resSize)) == NULL)
623 return NULL;
624
625 while (*s) {
626 switch (*s) {
627 case '+':
628 PUSHCHAR(' ');
629 s++;
630 break;
631
632 case '½':
633 /* Escape these .. */
634 PUSHCHAR('½');
635 PUSHCHAR('½');
636 s++;
637 break;
638
639 case '\r':
640 PUSHCHAR(' ');
641 s++;
642 break;
643
644 case '%':
645 s++;
646 if (*s == '%')
647 PUSHCHAR('%');
648 else if ((c = getxdigit(*s, 4)) >= 0) {
649 int i = getxdigit(*(++s), 0);
650 if (i >= 0) {
651 PUSHCHAR(c | i);
652 } else {
653 PUSHCHAR('§');
654 PUSHCHAR(*s);
655 }
656 } else {
657 PUSHCHAR('§');
658 PUSHCHAR(*s);
659 }
660 s++;
661 break;
662
663 default:
664 PUSHCHAR(*s);
665 s++;
666 }
667 }
668 PUSHCHAR(0);
669
670 return result;
671 }
672
673
674 char *stripTags(char *str)
675 {
676 char *result, *s = str;
677 size_t resSize, resPos = 0;
678
679 if (!str) return NULL;
680
681 resSize = strlen(str) + SET_ALLOC_SIZE;
682 if ((result = th_malloc(resSize)) == NULL)
683 return NULL;
684
685 while (*s) {
686 if (*s == '<') {
687 while (*s && *s != '>') s++;
688 if (*s == '>') s++;
689 } else
690 PUSHCHAR(*s++);
691 }
692 PUSHCHAR(0);
693
694 return result;
695 }
696
697
698 char *encodeStr2(char *str)
699 {
700 char *result, *s = str;
701 size_t resSize, resPos = 0;
702
703 if (!str) return NULL;
704
705 resSize = strlen(str) + SET_ALLOC_SIZE;
706 if ((result = th_malloc(resSize)) == NULL)
707 return NULL;
708
709 while (*s) {
710 int i;
711 BOOL found = FALSE;
712 for (i = 0; i < numHTMLEntities; i++)
713 if (HTMLEntities[i].c == *s) {
714 PUSHSTR(HTMLEntities[i].ent);
715 found = TRUE;
716 break;
717 }
718 if (!found) PUSHCHAR(*s);
719
720 s++;
721 }
722 PUSHCHAR(0);
723
724 return result;
725 }
726
727
728 char *decodeStr2(char *str)
729 {
730 char *result, *s = str;
731 size_t resSize, resPos = 0;
732
733 if (!str) return NULL;
734
735 resSize = strlen(str);
736 if ((result = th_malloc(resSize)) == NULL)
737 return NULL;
738
739 while (*s) {
740 if (*s == '&') {
741 int i;
742 BOOL found = FALSE;
743 for (i = 0; i < numHTMLEntities; i++) {
744 html_entity_t *ent = &HTMLEntities[i];
745 int len = strlen(ent->ent);
746 if (!strncmp(s, ent->ent, len)) {
747 PUSHCHAR(ent->c);
748 s += len;
749 found = TRUE;
750 break;
751 }
752 }
753 if (!found) PUSHCHAR(*s++);
754 } else
755 PUSHCHAR(*s++);
756 }
757 PUSHCHAR(0);
758
759 return result;
760 }
761
762
763 BOOL sendUserMsg(int sock, char *user, char *fmt, ...)
764 {
765 char tmpBuf[4096], tmpBuf2[4096+256];
766 int n;
767 va_list ap;
768
769 va_start(ap, fmt);
770 n = vsnprintf(tmpBuf, sizeof(tmpBuf), fmt, ap);
771 va_end(ap);
772
773 if (n < 0) return FALSE;
774
775 snprintf(tmpBuf2, sizeof(tmpBuf2),
776 "<USER>%s</USER><MESSAGE>%s</MESSAGE>",
777 user, tmpBuf);
778
779 return sendToSocket(sock, tmpBuf2, strlen(tmpBuf2) + 1);
780 }
781
782
783 int handleUser(int sock, char *str) 454 int handleUser(int sock, char *str)
784 { 455 {
785 const char *msg = "</USER><MESSAGE>"; 456 const char *msg = "</USER><MESSAGE>";
786 char *p = str, *q, *s, *t, *h; 457 char *p = str, *q, *s, *t, *h;
787 458
805 return -2; 476 return -2;
806 } 477 }
807 478
808 479
809 if (*s == '/') { 480 if (*s == '/') {
810 t = stripTags(s + 1); 481 t = stripXMLTags(s + 1);
811 if (!strncmp(t, "BPRV", 4)) { 482 if (!strncmp(t, "BPRV", 4)) {
812 h = decodeStr2(t + 1); 483 h = decodeStr2(t + 1);
813 printMsg("½11½%s½0½\n", h); 484 printMsg("½11½%s½0½\n", h);
814 } else { 485 } else {
815 h = decodeStr2(t); 486 h = decodeStr2(t);
816 printMsg("½9½* %s½0½\n", h); 487 printMsg("½9½* %s½0½\n", h);
817 } 488 }
818 th_free(h); 489 th_free(h);
819 th_free(t); 490 th_free(t);
820 } else { 491 } else {
821 t = stripTags(s); 492 t = stripXMLTags(s);
822 h = decodeStr2(t); 493 h = decodeStr2(t);
823 printMsg("½5½<½%d½%s½5½>½0½ %s\n", strcmp(p, optUserName) ? 15 : 14, p, h); 494 printMsg("½5½<½%d½%s½5½>½0½ %s\n", strcmp(p, optUserName) ? 15 : 14, p, h);
824 th_free(h); 495 th_free(h);
825 th_free(t); 496 th_free(t);
826 } 497 }
1088 return -3; 759 return -3;
1089 } 760 }
1090 THMSG(2, "True hostname: %s\n", tmpHost->h_name); 761 THMSG(2, "True hostname: %s\n", tmpHost->h_name);
1091 762
1092 #if 0 763 #if 0
1093 /* To emulate the official client, we first make a fake connection ... */ 764 /* To emulate the official client, we first make a request for
765 * policy file, even though we don't use it for anything...
766 */
1094 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { 767 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) {
1095 THERR("Fakeprobe connection setup failed!\n"); 768 THERR("Policy file request connection setup failed!\n");
1096 goto err_exit; 769 goto err_exit;
1097 } 770 }
1098 771
1099 tmpStr = "<policy-file-request/>"; 772 tmpStr = "<policy-file-request/>";
1100 if (sendToSocket(tmpSocket, tmpStr, strlen(tmpStr) + 1) == FALSE) { 773 if (sendToSocket(tmpSocket, tmpStr, strlen(tmpStr) + 1) == FALSE) {