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[] = {
+	{ '<', "&lt;" },
+	{ '>', "&gt;" },
+};
+
+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);
+}
+