Mercurial > hg > nnchat
diff libnnchat.c @ 62:ff5d74f0d428
Moved some functions to "libnnchat".
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Tue, 11 Nov 2008 21:57:51 +0200 |
parents | |
children | 6a3a917303e4 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libnnchat.c Tue Nov 11 21:57:51 2008 +0200 @@ -0,0 +1,334 @@ +/* + * NNChat - Custom chat client for NewbieNudes.com chatrooms + * Written by Matti 'ccr' Hämäläinen + * (C) Copyright 2008 Tecnic Software productions (TNSP) + */ +#include "libnnchat.h" + + +typedef struct { + char c; + char *ent; +} html_entity_t; + + +html_entity_t HTMLEntities[] = { + { '<', "<" }, + { '>', ">" }, +}; + +const int numHTMLEntities = (sizeof(HTMLEntities) / sizeof(HTMLEntities[0])); + + +int openConnection(struct in_addr *addr, const int port) +{ + struct sockaddr_in tmpAddr; + int sock = -1; + + tmpAddr.sin_family = AF_INET; + tmpAddr.sin_port = htons(port); + tmpAddr.sin_addr = *addr; + + THMSG(1, "Connecting to %s:%d ...\n", + inet_ntoa(tmpAddr.sin_addr), port); + + if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { + THERR("Could not open socket: %s\n", strerror(errno)); + return -2; + } + + THMSG(2, "Using socket %d.\n", sock); + + if (connect(sock, (struct sockaddr *) &tmpAddr, sizeof(tmpAddr)) == -1) { + THERR("Could not connect: %s\n", strerror(errno)); + return -5; + } + + return sock; +} + + +void closeConnection(const int sock) +{ + if (sock >= 0) { + close(sock); + } +} + + +BOOL sendToSocket(const int sock, char *buf, const size_t bufLen) +{ + size_t bufLeft = bufLen; + char *bufPtr = buf; + + while (bufLeft > 0) { + ssize_t bufSent; + bufSent = send(sock, bufPtr, bufLeft, 0); + if (bufSent < 0) return FALSE; + bufLeft -= bufSent; + bufPtr += bufSent; + } + return TRUE; +} + + +BOOL bufRealloc(char **buf, size_t *size, size_t add) +{ + return ((*buf = th_realloc(*buf, *size + add)) != NULL); +} + +#define PUSHCHAR(x) bufPushChar(&result, &resSize, &resPos, x) +BOOL bufPushChar(char **buf, size_t *size, size_t *pos, char ch) +{ + if (*pos >= *size && !bufRealloc(buf, size, SET_ALLOC_SIZE)) + return FALSE; + + (*buf)[*pos] = ch; + (*pos)++; + return TRUE; +} + +#define PUSHSTR(x) bufPushStr(&result, &resSize, &resPos, x) +BOOL bufPushStr(char **buf, size_t *size, size_t *pos, char *str) +{ + size_t tmpLen; + + if (!str) return FALSE; + tmpLen = strlen(str); + + if ((*pos + tmpLen) >= *size && !bufRealloc(buf, size, tmpLen + SET_ALLOC_SIZE)) + return FALSE; + + strcpy(*buf + *pos, str); + (*pos) += tmpLen; + return TRUE; +} + + +char *encodeStr1(const char *str) +{ + const char *s = str; + char *result; + size_t resSize, resPos = 0; + + if (!str) return NULL; + + resSize = strlen(str) + SET_ALLOC_SIZE; + if ((result = th_malloc(resSize)) == NULL) + return NULL; + + while (*s) { + switch (*s) { + case 32: + PUSHCHAR('+'); + break; + + default: + if (th_isalnum(*s)) + PUSHCHAR(*s); + else { + char tmpStr[4]; + sprintf(tmpStr, "%2X", (unsigned char) *s); + PUSHCHAR('%'); + PUSHSTR(tmpStr); + } + break; + } + s++; + } + PUSHCHAR(0); + + return result; +} + + +static int getHexDigit(const int c, const int shift) +{ + int i; + + if (c >= 'A' && c <= 'F') + i = c - 'A' + 10; + else if (c >= 'a' && c <= 'f') + i = c - 'a' + 10; + else if (c >= '0' && c <= '9') + i = c - '0'; + else + return -1; + + return i << shift; +} + + +char *decodeStr1(const char *str) +{ + const char *s = str; + char *result; + size_t resSize, resPos = 0; + int c; + + if (!str) return NULL; + + resSize = strlen(str) + SET_ALLOC_SIZE; + if ((result = th_malloc(resSize)) == NULL) + return NULL; + + while (*s) { + switch (*s) { + case '+': + PUSHCHAR(' '); + s++; + break; + + case '½': + /* Escape these .. */ + PUSHCHAR('½'); + PUSHCHAR('½'); + s++; + break; + + case '\r': + PUSHCHAR(' '); + s++; + break; + + case '%': + s++; + if (*s == '%') + PUSHCHAR('%'); + else if ((c = getHexDigit(*s, 4)) >= 0) { + int i = getHexDigit(*(++s), 0); + if (i >= 0) { + PUSHCHAR(c | i); + } else { + PUSHCHAR('§'); + PUSHCHAR(*s); + } + } else { + PUSHCHAR('§'); + PUSHCHAR(*s); + } + s++; + break; + + default: + PUSHCHAR(*s); + s++; + } + } + PUSHCHAR(0); + + return result; +} + + +char *stripXMLTags(const char *str) +{ + const char *s = str; + char *result; + size_t resSize, resPos = 0; + + if (!str) return NULL; + + resSize = strlen(str) + SET_ALLOC_SIZE; + if ((result = th_malloc(resSize)) == NULL) + return NULL; + + while (*s) { + if (*s == '<') { + while (*s && *s != '>') s++; + if (*s == '>') s++; + } else + PUSHCHAR(*s++); + } + PUSHCHAR(0); + + return result; +} + + +char *encodeStr2(const char *str) +{ + const char *s = str; + char *result; + size_t resSize, resPos = 0; + + if (!str) return NULL; + + resSize = strlen(str) + SET_ALLOC_SIZE; + if ((result = th_malloc(resSize)) == NULL) + return NULL; + + while (*s) { + int i; + BOOL found = FALSE; + for (i = 0; i < numHTMLEntities; i++) + if (HTMLEntities[i].c == *s) { + PUSHSTR(HTMLEntities[i].ent); + found = TRUE; + break; + } + if (!found) PUSHCHAR(*s); + + s++; + } + PUSHCHAR(0); + + return result; +} + + +char *decodeStr2(const char *str) +{ + const char *s = str; + char *result; + size_t resSize, resPos = 0; + + if (!str) return NULL; + + resSize = strlen(str); + if ((result = th_malloc(resSize)) == NULL) + return NULL; + + while (*s) { + if (*s == '&') { + int i; + BOOL found = FALSE; + for (i = 0; i < numHTMLEntities; i++) { + html_entity_t *ent = &HTMLEntities[i]; + int len = strlen(ent->ent); + if (!strncmp(s, ent->ent, len)) { + PUSHCHAR(ent->c); + s += len; + found = TRUE; + break; + } + } + if (!found) PUSHCHAR(*s++); + } else + PUSHCHAR(*s++); + } + PUSHCHAR(0); + + return result; +} + + +BOOL sendUserMsg(const int sock, const char *user, const char *fmt, ...) +{ + char tmpBuf[SET_BUFSIZE], tmpBuf2[SET_BUFSIZE + 256]; + int n; + va_list ap; + + va_start(ap, fmt); + n = vsnprintf(tmpBuf, sizeof(tmpBuf), fmt, ap); + va_end(ap); + + if (n < 0) return FALSE; + + snprintf(tmpBuf2, sizeof(tmpBuf2), + "<USER>%s</USER><MESSAGE>%s</MESSAGE>", + user, tmpBuf); + + return sendToSocket(sock, tmpBuf2, strlen(tmpBuf2) + 1); +} +