Mercurial > hg > nnchat
comparison 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 |
comparison
equal
deleted
inserted
replaced
61:b802a799c31a | 62:ff5d74f0d428 |
---|---|
1 /* | |
2 * NNChat - Custom chat client for NewbieNudes.com chatrooms | |
3 * Written by Matti 'ccr' Hämäläinen | |
4 * (C) Copyright 2008 Tecnic Software productions (TNSP) | |
5 */ | |
6 #include "libnnchat.h" | |
7 | |
8 | |
9 typedef struct { | |
10 char c; | |
11 char *ent; | |
12 } html_entity_t; | |
13 | |
14 | |
15 html_entity_t HTMLEntities[] = { | |
16 { '<', "<" }, | |
17 { '>', ">" }, | |
18 }; | |
19 | |
20 const int numHTMLEntities = (sizeof(HTMLEntities) / sizeof(HTMLEntities[0])); | |
21 | |
22 | |
23 int openConnection(struct in_addr *addr, const int port) | |
24 { | |
25 struct sockaddr_in tmpAddr; | |
26 int sock = -1; | |
27 | |
28 tmpAddr.sin_family = AF_INET; | |
29 tmpAddr.sin_port = htons(port); | |
30 tmpAddr.sin_addr = *addr; | |
31 | |
32 THMSG(1, "Connecting to %s:%d ...\n", | |
33 inet_ntoa(tmpAddr.sin_addr), port); | |
34 | |
35 if ((sock = socket(PF_INET, SOCK_STREAM, 0)) == -1) { | |
36 THERR("Could not open socket: %s\n", strerror(errno)); | |
37 return -2; | |
38 } | |
39 | |
40 THMSG(2, "Using socket %d.\n", sock); | |
41 | |
42 if (connect(sock, (struct sockaddr *) &tmpAddr, sizeof(tmpAddr)) == -1) { | |
43 THERR("Could not connect: %s\n", strerror(errno)); | |
44 return -5; | |
45 } | |
46 | |
47 return sock; | |
48 } | |
49 | |
50 | |
51 void closeConnection(const int sock) | |
52 { | |
53 if (sock >= 0) { | |
54 close(sock); | |
55 } | |
56 } | |
57 | |
58 | |
59 BOOL sendToSocket(const int sock, char *buf, const size_t bufLen) | |
60 { | |
61 size_t bufLeft = bufLen; | |
62 char *bufPtr = buf; | |
63 | |
64 while (bufLeft > 0) { | |
65 ssize_t bufSent; | |
66 bufSent = send(sock, bufPtr, bufLeft, 0); | |
67 if (bufSent < 0) return FALSE; | |
68 bufLeft -= bufSent; | |
69 bufPtr += bufSent; | |
70 } | |
71 return TRUE; | |
72 } | |
73 | |
74 | |
75 BOOL bufRealloc(char **buf, size_t *size, size_t add) | |
76 { | |
77 return ((*buf = th_realloc(*buf, *size + add)) != NULL); | |
78 } | |
79 | |
80 #define PUSHCHAR(x) bufPushChar(&result, &resSize, &resPos, x) | |
81 BOOL bufPushChar(char **buf, size_t *size, size_t *pos, char ch) | |
82 { | |
83 if (*pos >= *size && !bufRealloc(buf, size, SET_ALLOC_SIZE)) | |
84 return FALSE; | |
85 | |
86 (*buf)[*pos] = ch; | |
87 (*pos)++; | |
88 return TRUE; | |
89 } | |
90 | |
91 #define PUSHSTR(x) bufPushStr(&result, &resSize, &resPos, x) | |
92 BOOL bufPushStr(char **buf, size_t *size, size_t *pos, char *str) | |
93 { | |
94 size_t tmpLen; | |
95 | |
96 if (!str) return FALSE; | |
97 tmpLen = strlen(str); | |
98 | |
99 if ((*pos + tmpLen) >= *size && !bufRealloc(buf, size, tmpLen + SET_ALLOC_SIZE)) | |
100 return FALSE; | |
101 | |
102 strcpy(*buf + *pos, str); | |
103 (*pos) += tmpLen; | |
104 return TRUE; | |
105 } | |
106 | |
107 | |
108 char *encodeStr1(const char *str) | |
109 { | |
110 const char *s = str; | |
111 char *result; | |
112 size_t resSize, resPos = 0; | |
113 | |
114 if (!str) return NULL; | |
115 | |
116 resSize = strlen(str) + SET_ALLOC_SIZE; | |
117 if ((result = th_malloc(resSize)) == NULL) | |
118 return NULL; | |
119 | |
120 while (*s) { | |
121 switch (*s) { | |
122 case 32: | |
123 PUSHCHAR('+'); | |
124 break; | |
125 | |
126 default: | |
127 if (th_isalnum(*s)) | |
128 PUSHCHAR(*s); | |
129 else { | |
130 char tmpStr[4]; | |
131 sprintf(tmpStr, "%2X", (unsigned char) *s); | |
132 PUSHCHAR('%'); | |
133 PUSHSTR(tmpStr); | |
134 } | |
135 break; | |
136 } | |
137 s++; | |
138 } | |
139 PUSHCHAR(0); | |
140 | |
141 return result; | |
142 } | |
143 | |
144 | |
145 static int getHexDigit(const int c, const int shift) | |
146 { | |
147 int i; | |
148 | |
149 if (c >= 'A' && c <= 'F') | |
150 i = c - 'A' + 10; | |
151 else if (c >= 'a' && c <= 'f') | |
152 i = c - 'a' + 10; | |
153 else if (c >= '0' && c <= '9') | |
154 i = c - '0'; | |
155 else | |
156 return -1; | |
157 | |
158 return i << shift; | |
159 } | |
160 | |
161 | |
162 char *decodeStr1(const char *str) | |
163 { | |
164 const char *s = str; | |
165 char *result; | |
166 size_t resSize, resPos = 0; | |
167 int c; | |
168 | |
169 if (!str) return NULL; | |
170 | |
171 resSize = strlen(str) + SET_ALLOC_SIZE; | |
172 if ((result = th_malloc(resSize)) == NULL) | |
173 return NULL; | |
174 | |
175 while (*s) { | |
176 switch (*s) { | |
177 case '+': | |
178 PUSHCHAR(' '); | |
179 s++; | |
180 break; | |
181 | |
182 case '½': | |
183 /* Escape these .. */ | |
184 PUSHCHAR('½'); | |
185 PUSHCHAR('½'); | |
186 s++; | |
187 break; | |
188 | |
189 case '\r': | |
190 PUSHCHAR(' '); | |
191 s++; | |
192 break; | |
193 | |
194 case '%': | |
195 s++; | |
196 if (*s == '%') | |
197 PUSHCHAR('%'); | |
198 else if ((c = getHexDigit(*s, 4)) >= 0) { | |
199 int i = getHexDigit(*(++s), 0); | |
200 if (i >= 0) { | |
201 PUSHCHAR(c | i); | |
202 } else { | |
203 PUSHCHAR('§'); | |
204 PUSHCHAR(*s); | |
205 } | |
206 } else { | |
207 PUSHCHAR('§'); | |
208 PUSHCHAR(*s); | |
209 } | |
210 s++; | |
211 break; | |
212 | |
213 default: | |
214 PUSHCHAR(*s); | |
215 s++; | |
216 } | |
217 } | |
218 PUSHCHAR(0); | |
219 | |
220 return result; | |
221 } | |
222 | |
223 | |
224 char *stripXMLTags(const char *str) | |
225 { | |
226 const char *s = str; | |
227 char *result; | |
228 size_t resSize, resPos = 0; | |
229 | |
230 if (!str) return NULL; | |
231 | |
232 resSize = strlen(str) + SET_ALLOC_SIZE; | |
233 if ((result = th_malloc(resSize)) == NULL) | |
234 return NULL; | |
235 | |
236 while (*s) { | |
237 if (*s == '<') { | |
238 while (*s && *s != '>') s++; | |
239 if (*s == '>') s++; | |
240 } else | |
241 PUSHCHAR(*s++); | |
242 } | |
243 PUSHCHAR(0); | |
244 | |
245 return result; | |
246 } | |
247 | |
248 | |
249 char *encodeStr2(const char *str) | |
250 { | |
251 const char *s = str; | |
252 char *result; | |
253 size_t resSize, resPos = 0; | |
254 | |
255 if (!str) return NULL; | |
256 | |
257 resSize = strlen(str) + SET_ALLOC_SIZE; | |
258 if ((result = th_malloc(resSize)) == NULL) | |
259 return NULL; | |
260 | |
261 while (*s) { | |
262 int i; | |
263 BOOL found = FALSE; | |
264 for (i = 0; i < numHTMLEntities; i++) | |
265 if (HTMLEntities[i].c == *s) { | |
266 PUSHSTR(HTMLEntities[i].ent); | |
267 found = TRUE; | |
268 break; | |
269 } | |
270 if (!found) PUSHCHAR(*s); | |
271 | |
272 s++; | |
273 } | |
274 PUSHCHAR(0); | |
275 | |
276 return result; | |
277 } | |
278 | |
279 | |
280 char *decodeStr2(const char *str) | |
281 { | |
282 const char *s = str; | |
283 char *result; | |
284 size_t resSize, resPos = 0; | |
285 | |
286 if (!str) return NULL; | |
287 | |
288 resSize = strlen(str); | |
289 if ((result = th_malloc(resSize)) == NULL) | |
290 return NULL; | |
291 | |
292 while (*s) { | |
293 if (*s == '&') { | |
294 int i; | |
295 BOOL found = FALSE; | |
296 for (i = 0; i < numHTMLEntities; i++) { | |
297 html_entity_t *ent = &HTMLEntities[i]; | |
298 int len = strlen(ent->ent); | |
299 if (!strncmp(s, ent->ent, len)) { | |
300 PUSHCHAR(ent->c); | |
301 s += len; | |
302 found = TRUE; | |
303 break; | |
304 } | |
305 } | |
306 if (!found) PUSHCHAR(*s++); | |
307 } else | |
308 PUSHCHAR(*s++); | |
309 } | |
310 PUSHCHAR(0); | |
311 | |
312 return result; | |
313 } | |
314 | |
315 | |
316 BOOL sendUserMsg(const int sock, const char *user, const char *fmt, ...) | |
317 { | |
318 char tmpBuf[SET_BUFSIZE], tmpBuf2[SET_BUFSIZE + 256]; | |
319 int n; | |
320 va_list ap; | |
321 | |
322 va_start(ap, fmt); | |
323 n = vsnprintf(tmpBuf, sizeof(tmpBuf), fmt, ap); | |
324 va_end(ap); | |
325 | |
326 if (n < 0) return FALSE; | |
327 | |
328 snprintf(tmpBuf2, sizeof(tmpBuf2), | |
329 "<USER>%s</USER><MESSAGE>%s</MESSAGE>", | |
330 user, tmpBuf); | |
331 | |
332 return sendToSocket(sock, tmpBuf2, strlen(tmpBuf2) + 1); | |
333 } | |
334 |