Mercurial > hg > nnchat
comparison nnchat.c @ 70:5228ad7b4f57
Remove tabs from indentation.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Fri, 14 Nov 2008 08:48:12 +0200 |
parents | 79982b0aad97 |
children | c56e766acce1 |
comparison
equal
deleted
inserted
replaced
69:79982b0aad97 | 70:5228ad7b4f57 |
---|---|
26 /* Options | 26 /* Options |
27 */ | 27 */ |
28 int optPort = 8005; | 28 int optPort = 8005; |
29 int optUserColor = 0x006080; | 29 int optUserColor = 0x006080; |
30 char *optServer = "www11.servemedata.com", | 30 char *optServer = "www11.servemedata.com", |
31 *optUserName = NULL, | 31 *optUserName = NULL, |
32 *optUserName2 = NULL, | 32 *optUserName2 = NULL, |
33 *optPassword = NULL, | 33 *optPassword = NULL, |
34 *optLogFilename = NULL, | 34 *optLogFilename = NULL, |
35 *setTarget = NULL, | 35 *setTarget = NULL, |
36 *optSite = "NN"; | 36 *optSite = "NN"; |
37 BOOL optDaemon = FALSE; | 37 BOOL optDaemon = FALSE; |
38 FILE *optLogFile = NULL; | 38 FILE *optLogFile = NULL; |
39 WINDOW *mainWin = NULL, | 39 WINDOW *mainWin = NULL, |
40 *statusWin = NULL, | 40 *statusWin = NULL, |
41 *editWin = NULL; | 41 *editWin = NULL; |
42 BOOL setPrvMode = FALSE; | 42 BOOL setPrvMode = FALSE; |
43 | 43 |
44 /* Arguments | 44 /* Arguments |
45 */ | 45 */ |
46 optarg_t optList[] = { | 46 optarg_t optList[] = { |
47 { 0, '?', "help", "Show this help", OPT_NONE }, | 47 { 0, '?', "help", "Show this help", OPT_NONE }, |
48 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, | 48 { 1, 'v', "verbose", "Be more verbose", OPT_NONE }, |
49 { 2, 'p', "port", "Connect to port", OPT_ARGREQ }, | 49 { 2, 'p', "port", "Connect to port", OPT_ARGREQ }, |
50 { 3, 's', "server", "Server to connect to", OPT_ARGREQ }, | 50 { 3, 's', "server", "Server to connect to", OPT_ARGREQ }, |
51 { 4, 'C', "color", "Initial color in RGB hex 000000", OPT_ARGREQ }, | 51 { 4, 'C', "color", "Initial color in RGB hex 000000", OPT_ARGREQ }, |
52 { 5, 'l', "logfile", "Log filename", OPT_ARGREQ }, | 52 { 5, 'l', "logfile", "Log filename", OPT_ARGREQ }, |
53 { 6, 'D', "daemon", "A pseudo-daemon mode for logging", OPT_NONE }, | 53 { 6, 'D', "daemon", "A pseudo-daemon mode for logging", OPT_NONE }, |
54 { 7, 'S', "site", "Site (default: NN)", OPT_ARGREQ }, | 54 { 7, 'S', "site", "Site (default: NN)", OPT_ARGREQ }, |
55 }; | 55 }; |
56 | 56 |
57 const int optListN = (sizeof(optList) / sizeof(optList[0])); | 57 const int optListN = (sizeof(optList) / sizeof(optList[0])); |
58 | 58 |
59 | 59 |
60 int getColor(char *str) | 60 int getColor(char *str) |
61 { | 61 { |
62 char *p = str; | 62 char *p = str; |
63 int len, val = 0; | 63 int len, val = 0; |
64 | 64 |
65 for (len = 0; *p && len < 6; p++, len++) { | 65 for (len = 0; *p && len < 6; p++, len++) { |
66 if (*p >= '0' && *p <= '9') { | 66 if (*p >= '0' && *p <= '9') { |
67 val *= 16; val += (*p - '0'); | 67 val *= 16; val += (*p - '0'); |
68 } else if (*p >= 'A' && *p <= 'F') { | 68 } else if (*p >= 'A' && *p <= 'F') { |
69 val *= 16; val += (*p - 'A') + 10; | 69 val *= 16; val += (*p - 'A') + 10; |
70 } else if (*p >= 'a' && *p <= 'f') { | 70 } else if (*p >= 'a' && *p <= 'f') { |
71 val *= 16; val += (*p - 'a') + 10; | 71 val *= 16; val += (*p - 'a') + 10; |
72 } else | 72 } else |
73 return -1; | 73 return -1; |
74 } | 74 } |
75 | 75 |
76 return (len == 6) ? val : -1; | 76 return (len == 6) ? val : -1; |
77 } | 77 } |
78 | 78 |
79 | 79 |
80 void argShowHelp() | 80 void argShowHelp() |
81 { | 81 { |
82 th_args_help(stdout, optList, optListN, th_prog_name, | 82 th_args_help(stdout, optList, optListN, th_prog_name, |
83 "[options] <username> <password>"); | 83 "[options] <username> <password>"); |
84 } | 84 } |
85 | 85 |
86 | 86 |
87 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) | 87 BOOL argHandleOpt(const int optN, char *optArg, char *currArg) |
88 { | 88 { |
89 switch (optN) { | 89 switch (optN) { |
90 case 0: | 90 case 0: |
91 argShowHelp(); | 91 argShowHelp(); |
92 exit(0); | 92 exit(0); |
93 break; | 93 break; |
94 | 94 |
95 case 1: | 95 case 1: |
96 th_verbosityLevel++; | 96 th_verbosityLevel++; |
97 break; | 97 break; |
98 | 98 |
99 case 2: | 99 case 2: |
100 optPort = atoi(optArg); | 100 optPort = atoi(optArg); |
101 break; | 101 break; |
102 | 102 |
103 case 3: | 103 case 3: |
104 optServer = optArg; | 104 optServer = optArg; |
105 break; | 105 break; |
106 | 106 |
107 case 4: | 107 case 4: |
108 if ((optUserColor = getColor(optArg)) < 0) { | 108 if ((optUserColor = getColor(optArg)) < 0) { |
109 THERR("Invalid color argument '%s', should be a RGB hex triplet '000000'.\n", | 109 THERR("Invalid color argument '%s', should be a RGB hex triplet '000000'.\n", |
110 optArg); | 110 optArg); |
111 return FALSE; | 111 return FALSE; |
112 } | 112 } |
113 THMSG(1, "Using color #%06x\n", optUserColor); | 113 THMSG(1, "Using color #%06x\n", optUserColor); |
114 break; | 114 break; |
115 | 115 |
116 case 5: | 116 case 5: |
117 optLogFilename = optArg; | 117 optLogFilename = optArg; |
118 break; | 118 break; |
119 | 119 |
120 case 7: | 120 case 7: |
121 optSite = optArg; | 121 optSite = optArg; |
122 break; | 122 break; |
123 | 123 |
124 case 6: | 124 case 6: |
125 optDaemon = TRUE; | 125 optDaemon = TRUE; |
126 THMSG(1, "Running in pseudo-daemon mode.\n"); | 126 THMSG(1, "Running in pseudo-daemon mode.\n"); |
127 break; | 127 break; |
128 | 128 |
129 default: | 129 default: |
130 THERR("Unknown option '%s'.\n", currArg); | 130 THERR("Unknown option '%s'.\n", currArg); |
131 return FALSE; | 131 return FALSE; |
132 } | 132 } |
133 | 133 |
134 return TRUE; | 134 return TRUE; |
135 } | 135 } |
136 | 136 |
137 | 137 |
138 BOOL argHandleFile(char *currArg) | 138 BOOL argHandleFile(char *currArg) |
139 { | 139 { |
140 if (!optUserName) | 140 if (!optUserName) |
141 optUserName = currArg; | 141 optUserName = currArg; |
142 else if (!optPassword) | 142 else if (!optPassword) |
143 optPassword = currArg; | 143 optPassword = currArg; |
144 else { | 144 else { |
145 THERR("Username '%s' already specified on commandline!\n", optUserName); | 145 THERR("Username '%s' already specified on commandline!\n", optUserName); |
146 return FALSE; | 146 return FALSE; |
147 } | 147 } |
148 | 148 |
149 return TRUE; | 149 return TRUE; |
150 } | 150 } |
151 | 151 |
152 #ifdef __WIN32 | 152 #ifdef __WIN32 |
153 const char *hstrerror(int err) | 153 const char *hstrerror(int err) |
154 { | 154 { |
155 static char buf[64]; | 155 static char buf[64]; |
156 snprintf(buf, sizeof(buf), "Error #%d", err); | 156 snprintf(buf, sizeof(buf), "Error #%d", err); |
157 return buf; | 157 return buf; |
158 } | 158 } |
159 | 159 |
160 int getSocketErrno(void) | 160 int getSocketErrno(void) |
161 { | 161 { |
162 return WSAGetLastError(); | 162 return WSAGetLastError(); |
163 } | 163 } |
164 | 164 |
165 const char *getSocketErrStr(int err) | 165 const char *getSocketErrStr(int err) |
166 { | 166 { |
167 static char buf[64]; | 167 static char buf[64]; |
168 snprintf(buf, sizeof(buf), "Error #%d", err); | 168 snprintf(buf, sizeof(buf), "Error #%d", err); |
169 return buf; | 169 return buf; |
170 } | 170 } |
171 #else | 171 #else |
172 int getSocketErrno(void) | 172 int getSocketErrno(void) |
173 { | 173 { |
174 return errno; | 174 return errno; |
175 } | 175 } |
176 | 176 |
177 const char *getSocketErrStr(int err) | 177 const char *getSocketErrStr(int err) |
178 { | 178 { |
179 return strerror(err); | 179 return strerror(err); |
180 } | 180 } |
181 #endif | 181 #endif |
182 | 182 |
183 void updateStatus(BOOL insertMode) | 183 void updateStatus(BOOL insertMode) |
184 { | 184 { |
185 char tmpStr[128] = ""; | 185 char tmpStr[128] = ""; |
186 time_t timeStamp; | 186 time_t timeStamp; |
187 struct tm *tmpTime;; | 187 struct tm *tmpTime;; |
188 | 188 |
189 if (statusWin == NULL) return; | 189 if (statusWin == NULL) return; |
190 | 190 |
191 timeStamp = time(NULL); | 191 timeStamp = time(NULL); |
192 if ((tmpTime = localtime(&timeStamp)) != NULL) { | 192 if ((tmpTime = localtime(&timeStamp)) != NULL) { |
193 strftime(tmpStr, sizeof(tmpStr), "%H:%M:%S", tmpTime); | 193 strftime(tmpStr, sizeof(tmpStr), "%H:%M:%S", tmpTime); |
194 } | 194 } |
195 | 195 |
196 wbkgdset(statusWin, 0x0d00); | 196 wbkgdset(statusWin, 0x0d00); |
197 werase(statusWin); | 197 werase(statusWin); |
198 | 198 |
199 wattrset(statusWin, A_BOLD); | 199 wattrset(statusWin, A_BOLD); |
200 mvwaddstr(statusWin, 0, 1, tmpStr); | 200 mvwaddstr(statusWin, 0, 1, tmpStr); |
201 | 201 |
202 waddstr(statusWin, " | "); | 202 waddstr(statusWin, " | "); |
203 wattrset(statusWin, A_BOLD | COLOR_PAIR(16)); | 203 wattrset(statusWin, A_BOLD | COLOR_PAIR(16)); |
204 waddstr(statusWin, optUserName); | 204 waddstr(statusWin, optUserName); |
205 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); | 205 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); |
206 | 206 |
207 waddstr(statusWin, " | "); | 207 waddstr(statusWin, " | "); |
208 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); | 208 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); |
209 waddstr(statusWin, insertMode ? "INS" : "DEL"); | 209 waddstr(statusWin, insertMode ? "INS" : "DEL"); |
210 | 210 |
211 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); | 211 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); |
212 waddstr(statusWin, " | Prv: "); | 212 waddstr(statusWin, " | Prv: "); |
213 | 213 |
214 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); | 214 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); |
215 waddstr(statusWin, setTarget != NULL ? setTarget : "-"); | 215 waddstr(statusWin, setTarget != NULL ? setTarget : "-"); |
216 | 216 |
217 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); | 217 wattrset(statusWin, A_BOLD | COLOR_PAIR(13)); |
218 waddstr(statusWin, " | P/C: "); | 218 waddstr(statusWin, " | P/C: "); |
219 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); | 219 wattrset(statusWin, A_BOLD | COLOR_PAIR(11)); |
220 snprintf(tmpStr, sizeof(tmpStr), "%d / #%06x", optPort, optUserColor); | 220 snprintf(tmpStr, sizeof(tmpStr), "%d / #%06x", optPort, optUserColor); |
221 waddstr(statusWin, tmpStr); | 221 waddstr(statusWin, tmpStr); |
222 | 222 |
223 wrefresh(statusWin); | 223 wrefresh(statusWin); |
224 } | 224 } |
225 | 225 |
226 void printEditBuf(char *str, editbuf_t *buf) | 226 void printEditBuf(char *str, editbuf_t *buf) |
227 { | 227 { |
228 if (statusWin == NULL || buf == NULL) return; | 228 if (statusWin == NULL || buf == NULL) return; |
229 | 229 |
230 buf->data[buf->len] = 0; | 230 buf->data[buf->len] = 0; |
231 werase(editWin); | 231 werase(editWin); |
232 | 232 |
233 wattrset(editWin, A_BOLD); | 233 wattrset(editWin, A_BOLD); |
234 mvwaddstr(editWin, 0, 0, str); | 234 mvwaddstr(editWin, 0, 0, str); |
235 waddstr(editWin, "> "); | 235 waddstr(editWin, "> "); |
236 wattrset(editWin, A_NORMAL); | 236 wattrset(editWin, A_NORMAL); |
237 | 237 |
238 if (buf->pos < buf->len) { | 238 if (buf->pos < buf->len) { |
239 waddnstr(editWin, buf->data, buf->pos); | 239 waddnstr(editWin, buf->data, buf->pos); |
240 wattrset(editWin, A_REVERSE); | 240 wattrset(editWin, A_REVERSE); |
241 waddch(editWin, buf->data[buf->pos]); | 241 waddch(editWin, buf->data[buf->pos]); |
242 wattrset(editWin, A_NORMAL); | 242 wattrset(editWin, A_NORMAL); |
243 waddnstr(editWin, buf->data + buf->pos + 1, buf->len - buf->pos - 1); | 243 waddnstr(editWin, buf->data + buf->pos + 1, buf->len - buf->pos - 1); |
244 } else { | 244 } else { |
245 waddnstr(editWin, buf->data, buf->len); | 245 waddnstr(editWin, buf->data, buf->len); |
246 wattrset(editWin, A_REVERSE); | 246 wattrset(editWin, A_REVERSE); |
247 waddch(editWin, ' '); | 247 waddch(editWin, ' '); |
248 wattrset(editWin, A_NORMAL); | 248 wattrset(editWin, A_NORMAL); |
249 } | 249 } |
250 wrefresh(editWin); | 250 wrefresh(editWin); |
251 } | 251 } |
252 | 252 |
253 int printWin(WINDOW *win, const char *fmt) | 253 int printWin(WINDOW *win, const char *fmt) |
254 { | 254 { |
255 const char *s = fmt; | 255 const char *s = fmt; |
256 int col = 0; | 256 int col = 0; |
257 | 257 |
258 while (*s) { | 258 while (*s) { |
259 if (*s == '½') { | 259 if (*s == '½') { |
260 int val = 0; | 260 int val = 0; |
261 s++; | 261 s++; |
262 if (*s == '½') { | 262 if (*s == '½') { |
263 waddch(win, ((unsigned char) *s) | col); | 263 waddch(win, ((unsigned char) *s) | col); |
264 s++; | 264 s++; |
265 } else { | 265 } else { |
266 while (*s && isdigit(*s)) { | 266 while (*s && isdigit(*s)) { |
267 val *= 10; | 267 val *= 10; |
268 val += (*s - '0'); | 268 val += (*s - '0'); |
269 s++; | 269 s++; |
270 } | 270 } |
271 if (*s != '½') return -1; | 271 if (*s != '½') return -1; |
272 s++; | 272 s++; |
273 | 273 |
274 if (val < 9) { | 274 if (val < 9) { |
275 col = A_DIM | COLOR_PAIR(val); | 275 col = A_DIM | COLOR_PAIR(val); |
276 } else if (val < 30) { | 276 } else if (val < 30) { |
277 col = A_BOLD | COLOR_PAIR(val - 9); | 277 col = A_BOLD | COLOR_PAIR(val - 9); |
278 } | 278 } |
279 } | 279 } |
280 } else { | 280 } else { |
281 waddch(win, ((unsigned char) *s) | col); | 281 waddch(win, ((unsigned char) *s) | col); |
282 s++; | 282 s++; |
283 } | 283 } |
284 } | 284 } |
285 return 0; | 285 return 0; |
286 } | 286 } |
287 | 287 |
288 | 288 |
289 int printFile(FILE *outFile, const char *fmt) | 289 int printFile(FILE *outFile, const char *fmt) |
290 { | 290 { |
291 const char *s = fmt; | 291 const char *s = fmt; |
292 | 292 |
293 while (*s) { | 293 while (*s) { |
294 if (*s == '½') { | 294 if (*s == '½') { |
295 s++; | 295 s++; |
296 if (*s == '½') { | 296 if (*s == '½') { |
297 fputc((unsigned char) *s, outFile); | 297 fputc((unsigned char) *s, outFile); |
298 s++; | 298 s++; |
299 } else { | 299 } else { |
300 while (*s && isdigit(*s)) s++; | 300 while (*s && isdigit(*s)) s++; |
301 if (*s != '½') return -1; | 301 if (*s != '½') return -1; |
302 s++; | 302 s++; |
303 } | 303 } |
304 } else { | 304 } else { |
305 fputc((unsigned char) *s, outFile); | 305 fputc((unsigned char) *s, outFile); |
306 s++; | 306 s++; |
307 } | 307 } |
308 } | 308 } |
309 | 309 |
310 return 0; | 310 return 0; |
311 } | 311 } |
312 | 312 |
313 | 313 |
314 void printMsg(char *fmt, ...) | 314 void printMsg(char *fmt, ...) |
315 { | 315 { |
316 char tmpStr[128] = "", buf[8192]; | 316 char tmpStr[128] = "", buf[8192]; |
317 va_list ap; | 317 va_list ap; |
318 time_t timeStamp; | 318 time_t timeStamp; |
319 struct tm *tmpTime;; | 319 struct tm *tmpTime;; |
320 | 320 |
321 timeStamp = time(NULL); | 321 timeStamp = time(NULL); |
322 if ((tmpTime = localtime(&timeStamp)) != NULL) { | 322 if ((tmpTime = localtime(&timeStamp)) != NULL) { |
323 strftime(tmpStr, sizeof(tmpStr), "½17½[½11½%H:%M:%S½17½]½0½ ", tmpTime); | 323 strftime(tmpStr, sizeof(tmpStr), "½17½[½11½%H:%M:%S½17½]½0½ ", tmpTime); |
324 } | 324 } |
325 | 325 |
326 va_start(ap, fmt); | 326 va_start(ap, fmt); |
327 vsnprintf(buf, sizeof(buf), fmt, ap); | 327 vsnprintf(buf, sizeof(buf), fmt, ap); |
328 va_end(ap); | 328 va_end(ap); |
329 | 329 |
330 if (optLogFile) { | 330 if (optLogFile) { |
331 printFile(optLogFile, tmpStr); | 331 printFile(optLogFile, tmpStr); |
332 printFile(optLogFile, buf); | 332 printFile(optLogFile, buf); |
333 fflush(optLogFile); | 333 fflush(optLogFile); |
334 } | 334 } |
335 | 335 |
336 if (!optDaemon) { | 336 if (!optDaemon) { |
337 printWin(mainWin, tmpStr); | 337 printWin(mainWin, tmpStr); |
338 printWin(mainWin, buf); | 338 printWin(mainWin, buf); |
339 wrefresh(mainWin); | 339 wrefresh(mainWin); |
340 } | 340 } |
341 } | 341 } |
342 | 342 |
343 | 343 |
344 int handleUser(int sock, char *str) | 344 int handleUser(int sock, char *str) |
345 { | 345 { |
346 const char *msg = "</USER><MESSAGE>"; | 346 const char *msg = "</USER><MESSAGE>"; |
347 char *p = str, *q, *s, *t, *h; | 347 char *p = str, *q, *s, *t, *h; |
348 | 348 |
349 (void) sock; | 349 (void) sock; |
350 | 350 |
351 s = strstr(str, msg); | 351 s = strstr(str, msg); |
352 if (!s) return 1; | 352 if (!s) return 1; |
353 *s = 0; | 353 *s = 0; |
354 s += strlen(msg); | 354 s += strlen(msg); |
355 | 355 |
356 q = strstr(s, "</MESSAGE>"); | 356 q = strstr(s, "</MESSAGE>"); |
357 if (!q) return 3; | 357 if (!q) return 3; |
358 *q = 0; | 358 *q = 0; |
359 | 359 |
360 s = decodeStr1(s); | 360 s = decodeStr1(s); |
361 if (!s) return -1; | 361 if (!s) return -1; |
362 | 362 |
363 p = decodeStr1(p); | 363 p = decodeStr1(p); |
364 if (!p) { | 364 if (!p) { |
365 th_free(s); | 365 th_free(s); |
366 return -2; | 366 return -2; |
367 } | 367 } |
368 | 368 |
369 | 369 |
370 if (*s == '/') { | 370 if (*s == '/') { |
371 t = stripXMLTags(s + 1); | 371 t = stripXMLTags(s + 1); |
372 if (!strncmp(t, "BPRV", 4)) { | 372 if (!strncmp(t, "BPRV", 4)) { |
373 h = decodeStr2(t + 1); | 373 h = decodeStr2(t + 1); |
374 printMsg("½11½%s½0½\n", h); | 374 printMsg("½11½%s½0½\n", h); |
375 } else { | 375 } else { |
376 h = decodeStr2(t); | 376 h = decodeStr2(t); |
377 printMsg("½9½* %s½0½\n", h); | 377 printMsg("½9½* %s½0½\n", h); |
378 } | 378 } |
379 th_free(h); | 379 th_free(h); |
380 th_free(t); | 380 th_free(t); |
381 } else { | 381 } else { |
382 BOOL isMine = strcmp(p, optUserName) == 0; | 382 BOOL isMine = strcmp(p, optUserName) == 0; |
383 t = stripXMLTags(s); | 383 t = stripXMLTags(s); |
384 h = decodeStr2(t); | 384 h = decodeStr2(t); |
385 printMsg("½5½<½%d½%s½5½>½0½ %s\n", isMine ? 14 : 15, p, h); | 385 printMsg("½5½<½%d½%s½5½>½0½ %s\n", isMine ? 14 : 15, p, h); |
386 th_free(h); | 386 th_free(h); |
387 th_free(t); | 387 th_free(t); |
388 } | 388 } |
389 | 389 |
390 th_free(s); | 390 th_free(s); |
391 th_free(p); | 391 th_free(p); |
392 return 0; | 392 return 0; |
393 } | 393 } |
394 | 394 |
395 | 395 |
396 int handleLogin(int sock, char *str) | 396 int handleLogin(int sock, char *str) |
397 { | 397 { |
398 char tmpStr[256] = ""; | 398 char tmpStr[256] = ""; |
399 time_t timeStamp; | 399 time_t timeStamp; |
400 struct tm *tmpTime;; | 400 struct tm *tmpTime;; |
401 | 401 |
402 timeStamp = time(NULL); | 402 timeStamp = time(NULL); |
403 if ((tmpTime = localtime(&timeStamp)) != NULL) { | 403 if ((tmpTime = localtime(&timeStamp)) != NULL) { |
404 strftime(tmpStr, sizeof(tmpStr), "%c", tmpTime); | 404 strftime(tmpStr, sizeof(tmpStr), "%c", tmpTime); |
405 } | 405 } |
406 | 406 |
407 if (!strncmp(str, "FAILURE", 7)) { | 407 if (!strncmp(str, "FAILURE", 7)) { |
408 printMsg("½1½Login failure½0½ - ½3½%s½0½\n", tmpStr); | 408 printMsg("½1½Login failure½0½ - ½3½%s½0½\n", tmpStr); |
409 return -2; | 409 return -2; |
410 } else if (!strncmp(str, "SUCCESS", 7)) { | 410 } else if (!strncmp(str, "SUCCESS", 7)) { |
411 printMsg("½2½Login success½0½ - ½3½%s½0½\n", tmpStr); | 411 printMsg("½2½Login success½0½ - ½3½%s½0½\n", tmpStr); |
412 sendUserMsg(sock, optUserName2, "%%2FRequestUserList"); | 412 sendUserMsg(sock, optUserName2, "%%2FRequestUserList"); |
413 return 0; | 413 return 0; |
414 } else | 414 } else |
415 return 1; | 415 return 1; |
416 } | 416 } |
417 | 417 |
418 | 418 |
419 int handleAddUser(int sock, char *str) | 419 int handleAddUser(int sock, char *str) |
420 { | 420 { |
421 char *p, *s = strstr(str, "</ADD_USER>"); | 421 char *p, *s = strstr(str, "</ADD_USER>"); |
422 | 422 |
423 (void) sock; | 423 (void) sock; |
424 | 424 |
425 if (!s) return 1; | 425 if (!s) return 1; |
426 *s = 0; | 426 *s = 0; |
427 | 427 |
428 p = decodeStr1(str); | 428 p = decodeStr1(str); |
429 if (!p) return -1; | 429 if (!p) return -1; |
430 | 430 |
431 printMsg("! ½3½%s½0½ ½2½ADDED.½0½\n", p); | 431 printMsg("! ½3½%s½0½ ½2½ADDED.½0½\n", p); |
432 th_free(p); | 432 th_free(p); |
433 return 0; | 433 return 0; |
434 } | 434 } |
435 | 435 |
436 | 436 |
437 int handleDeleteUser(int sock, char *str) | 437 int handleDeleteUser(int sock, char *str) |
438 { | 438 { |
439 char *p, *s = strstr(str, "</DELETE_USER>"); | 439 char *p, *s = strstr(str, "</DELETE_USER>"); |
440 | 440 |
441 (void) sock; | 441 (void) sock; |
442 | 442 |
443 if (!s) return 1; | 443 if (!s) return 1; |
444 *s = 0; | 444 *s = 0; |
445 | 445 |
446 p = decodeStr1(str); | 446 p = decodeStr1(str); |
447 if (!p) return -1; | 447 if (!p) return -1; |
448 | 448 |
449 printMsg("! ½3½%s½0½ ½1½DELETED.½0½\n", p); | 449 printMsg("! ½3½%s½0½ ½1½DELETED.½0½\n", p); |
450 th_free(p); | 450 th_free(p); |
451 return 0; | 451 return 0; |
452 } | 452 } |
453 | 453 |
454 | 454 |
455 int handleFoo(int sock, char *str) | 455 int handleFoo(int sock, char *str) |
456 { | 456 { |
457 (void) sock; (void) str; | 457 (void) sock; (void) str; |
458 | 458 |
459 return 0; | 459 return 0; |
460 } | 460 } |
461 | 461 |
462 | 462 |
463 typedef struct { | 463 typedef struct { |
464 char *cmd; | 464 char *cmd; |
465 int (*handler)(int, char *); | 465 int (*handler)(int, char *); |
466 } protocmd_t; | 466 } protocmd_t; |
467 | 467 |
468 | 468 |
469 protocmd_t protoCmds[] = { | 469 protocmd_t protoCmds[] = { |
470 { "<USER>", handleUser }, | 470 { "<USER>", handleUser }, |
471 { "<LOGIN_", handleLogin }, | 471 { "<LOGIN_", handleLogin }, |
472 { "<DELETE_USER>", handleDeleteUser }, | 472 { "<DELETE_USER>", handleDeleteUser }, |
473 { "<ADD_USER>", handleAddUser }, | 473 { "<ADD_USER>", handleAddUser }, |
474 { "<NUMCLIENTS>", handleFoo }, | 474 { "<NUMCLIENTS>", handleFoo }, |
475 }; | 475 }; |
476 | 476 |
477 const int nprotoCmds = (sizeof(protoCmds) / sizeof(protoCmds[0])); | 477 const int nprotoCmds = (sizeof(protoCmds) / sizeof(protoCmds[0])); |
478 | 478 |
479 | 479 |
480 int handleProtocol(const int sock, char *buf, size_t bufLen) | 480 int handleProtocol(const int sock, char *buf, size_t bufLen) |
481 { | 481 { |
482 int i; | 482 int i; |
483 | 483 |
484 for (i = 0; i < nprotoCmds; i++) { | 484 for (i = 0; i < nprotoCmds; i++) { |
485 size_t cmdLen = strlen(protoCmds[i].cmd); | 485 size_t cmdLen = strlen(protoCmds[i].cmd); |
486 if (cmdLen < bufLen && !strncmp(buf, protoCmds[i].cmd, cmdLen)) { | 486 if (cmdLen < bufLen && !strncmp(buf, protoCmds[i].cmd, cmdLen)) { |
487 return protoCmds[i].handler(sock, buf + cmdLen); | 487 return protoCmds[i].handler(sock, buf + cmdLen); |
488 } | 488 } |
489 } | 489 } |
490 | 490 |
491 return 1; | 491 return 1; |
492 } | 492 } |
493 | 493 |
494 | 494 |
495 int handleUserInput(const int sock, char *buf, size_t bufLen) | 495 int handleUserInput(const int sock, char *buf, size_t bufLen) |
496 { | 496 { |
497 char *tmpStr, *tmpStr2, tmpBuf[4096]; | 497 char *tmpStr, *tmpStr2, tmpBuf[4096]; |
498 BOOL result; | 498 BOOL result; |
499 | 499 |
500 /* Trim right */ | 500 /* Trim right */ |
501 buf[--bufLen] = 0; | 501 buf[--bufLen] = 0; |
502 while (bufLen > 0 && (buf[bufLen] == '\n' || buf[bufLen] == '\r' || th_isspace(buf[bufLen]))) | 502 while (bufLen > 0 && (buf[bufLen] == '\n' || buf[bufLen] == '\r' || th_isspace(buf[bufLen]))) |
503 buf[bufLen--] = 0; | 503 buf[bufLen--] = 0; |
504 | 504 |
505 /* Check command */ | 505 /* Check command */ |
506 if (*buf == 0) { | 506 if (*buf == 0) { |
507 return 1; | 507 return 1; |
508 } else if (!strncmp(buf, "/color ", 7)) { | 508 } else if (!strncmp(buf, "/color ", 7)) { |
509 int tmpInt; | 509 int tmpInt; |
510 if ((tmpInt = getColor(buf+7)) < 0) { | 510 if ((tmpInt = getColor(buf+7)) < 0) { |
511 printMsg("Invalid color value '%s'\n", buf+7); | 511 printMsg("Invalid color value '%s'\n", buf+7); |
512 return 1; | 512 return 1; |
513 } | 513 } |
514 optUserColor = tmpInt; | 514 optUserColor = tmpInt; |
515 printMsg("Setting color to #%06x\n", optUserColor); | 515 printMsg("Setting color to #%06x\n", optUserColor); |
516 sendUserMsg(sock, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); | 516 sendUserMsg(sock, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); |
517 return 0; | 517 return 0; |
518 } else if (!strncmp(buf, "/flood ", 7)) { | 518 } else if (!strncmp(buf, "/flood ", 7)) { |
519 int i; | 519 int i; |
520 | 520 |
521 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg . .", | 521 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg . .", |
522 buf+7); | 522 buf+7); |
523 | 523 |
524 tmpStr = encodeStr2(tmpBuf); | 524 tmpStr = encodeStr2(tmpBuf); |
525 if (!tmpStr) return -2; | 525 if (!tmpStr) return -2; |
526 tmpStr2 = encodeStr1(tmpStr); | 526 tmpStr2 = encodeStr1(tmpStr); |
527 if (!tmpStr2) { | 527 if (!tmpStr2) { |
528 th_free(tmpStr); | 528 th_free(tmpStr); |
529 return -3; | 529 return -3; |
530 } | 530 } |
531 | 531 |
532 result = TRUE; | 532 result = TRUE; |
533 for (i = 0; i < 50 && result; i++) { | 533 for (i = 0; i < 50 && result; i++) { |
534 result = sendUserMsg(sock, optUserName2, "%s", tmpStr2); | 534 result = sendUserMsg(sock, optUserName2, "%s", tmpStr2); |
535 usleep(250); | 535 usleep(250); |
536 } | 536 } |
537 | 537 |
538 th_free(tmpStr); | 538 th_free(tmpStr); |
539 th_free(tmpStr2); | 539 th_free(tmpStr2); |
540 return 0; | 540 return 0; |
541 } else if (!strncmp(buf, "/to ", 4)) { | 541 } else if (!strncmp(buf, "/to ", 4)) { |
542 th_free(setTarget); | 542 th_free(setTarget); |
543 setTarget = strdup(buf + 4); | 543 setTarget = strdup(buf + 4); |
544 printMsg("Set prv target to '%s'\n", setTarget); | 544 printMsg("Set prv target to '%s'\n", setTarget); |
545 return 0; | 545 return 0; |
546 } else if (!strncmp(buf, "/who", 4)) { | 546 } else if (!strncmp(buf, "/who", 4)) { |
547 snprintf(tmpBuf, sizeof(tmpBuf), "/listallusers"); | 547 snprintf(tmpBuf, sizeof(tmpBuf), "/listallusers"); |
548 buf = tmpBuf; | 548 buf = tmpBuf; |
549 } else if (setPrvMode) { | 549 } else if (setPrvMode) { |
550 if (setTarget != NULL) { | 550 if (setTarget != NULL) { |
551 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg %s", setTarget, buf); | 551 snprintf(tmpBuf, sizeof(tmpBuf), "/prv -to %s -msg %s", setTarget, buf); |
552 buf = tmpBuf; | 552 buf = tmpBuf; |
553 } else { | 553 } else { |
554 printMsg("No target set, exiting prv mode.\n"); | 554 printMsg("No target set, exiting prv mode.\n"); |
555 setPrvMode = FALSE; | 555 setPrvMode = FALSE; |
556 return 1; | 556 return 1; |
557 } | 557 } |
558 } | 558 } |
559 | 559 |
560 | 560 |
561 /* Send double-encoded */ | 561 /* Send double-encoded */ |
562 tmpStr = encodeStr2(buf); | 562 tmpStr = encodeStr2(buf); |
563 if (!tmpStr) return -2; | 563 if (!tmpStr) return -2; |
564 tmpStr2 = encodeStr1(tmpStr); | 564 tmpStr2 = encodeStr1(tmpStr); |
565 if (!tmpStr2) { | 565 if (!tmpStr2) { |
566 th_free(tmpStr); | 566 th_free(tmpStr); |
567 return -3; | 567 return -3; |
568 } | 568 } |
569 | 569 |
570 result = sendUserMsg(sock, optUserName2, "%s", tmpStr2); | 570 result = sendUserMsg(sock, optUserName2, "%s", tmpStr2); |
571 th_free(tmpStr); | 571 th_free(tmpStr); |
572 th_free(tmpStr2); | 572 th_free(tmpStr2); |
573 if (result) | 573 if (result) |
574 return 0; | 574 return 0; |
575 else | 575 else |
576 return -1; | 576 return -1; |
577 } | 577 } |
578 | 578 |
579 | 579 |
580 BOOL initializeWindows(void) | 580 BOOL initializeWindows(void) |
581 { | 581 { |
582 if (mainWin) delwin(mainWin); | 582 if (mainWin) delwin(mainWin); |
583 if (statusWin) delwin(statusWin); | 583 if (statusWin) delwin(statusWin); |
584 if (editWin) delwin(editWin); | 584 if (editWin) delwin(editWin); |
585 | 585 |
586 mainWin = newwin(LINES - 4, COLS, 0, 0); | 586 mainWin = newwin(LINES - 4, COLS, 0, 0); |
587 statusWin = newwin(1, COLS, LINES - 4, 0); | 587 statusWin = newwin(1, COLS, LINES - 4, 0); |
588 editWin = newwin(3, COLS, LINES - 3, 0); | 588 editWin = newwin(3, COLS, LINES - 3, 0); |
589 | 589 |
590 if (mainWin == NULL || statusWin == NULL || editWin == NULL) { | 590 if (mainWin == NULL || statusWin == NULL || editWin == NULL) { |
591 THERR("Could not create ncurses windows!\n"); | 591 THERR("Could not create ncurses windows!\n"); |
592 return FALSE; | 592 return FALSE; |
593 } | 593 } |
594 scrollok(mainWin, 1); | 594 scrollok(mainWin, 1); |
595 | 595 |
596 return TRUE; | 596 return TRUE; |
597 } | 597 } |
598 | 598 |
599 | 599 |
600 int main(int argc, char *argv[]) | 600 int main(int argc, char *argv[]) |
601 { | 601 { |
602 int tmpSocket, curVis, updateCount = 0; | 602 int tmpSocket, curVis, updateCount = 0; |
603 struct hostent *tmpHost; | 603 struct hostent *tmpHost; |
604 BOOL argsOK, isError = FALSE, | 604 BOOL argsOK, isError = FALSE, |
605 exitProg = FALSE, | 605 exitProg = FALSE, |
606 colorSet = FALSE, | 606 colorSet = FALSE, |
607 cursesInit = FALSE, | 607 cursesInit = FALSE, |
608 #if __WIN32 | 608 #if __WIN32 |
609 networkInit = FALSE, | 609 networkInit = FALSE, |
610 #endif | 610 #endif |
611 insertMode = TRUE; | 611 insertMode = TRUE; |
612 struct timeval tv; | 612 struct timeval tv; |
613 fd_set sockfds; | 613 fd_set sockfds; |
614 char *tmpStr; | 614 char *tmpStr; |
615 editbuf_t *editBuf = newBuf(SET_BUFSIZE); | 615 editbuf_t *editBuf = newBuf(SET_BUFSIZE); |
616 editbuf_t *histBuf[SET_MAX_HISTORY+2]; | 616 editbuf_t *histBuf[SET_MAX_HISTORY+2]; |
617 int histPos = 0, histMax = 0; | 617 int histPos = 0, histMax = 0; |
618 | 618 |
619 memset(histBuf, 0, sizeof(histBuf)); | 619 memset(histBuf, 0, sizeof(histBuf)); |
620 | 620 |
621 /* Initialize */ | 621 /* Initialize */ |
622 th_init("NNChat", "Newbie Nudes chat client", "0.6.5", | 622 th_init("NNChat", "Newbie Nudes chat client", "0.6.5", |
623 "Written and designed by Anonymous Finnish Guy (C) 2008", | 623 "Written and designed by Anonymous Finnish Guy (C) 2008", |
624 "This software is freeware, use and distribute as you wish."); | 624 "This software is freeware, use and distribute as you wish."); |
625 th_verbosityLevel = 0; | 625 th_verbosityLevel = 0; |
626 | 626 |
627 /* Parse arguments */ | 627 /* Parse arguments */ |
628 argsOK = th_args_process(argc, argv, optList, optListN, | 628 argsOK = th_args_process(argc, argv, optList, optListN, |
629 argHandleOpt, argHandleFile, FALSE); | 629 argHandleOpt, argHandleFile, FALSE); |
630 | 630 |
631 /* Check the mode and arguments */ | 631 /* Check the mode and arguments */ |
632 if (optUserName == NULL || optPassword == NULL) { | 632 if (optUserName == NULL || optPassword == NULL) { |
633 THERR("User/pass not specified, get some --help\n"); | 633 THERR("User/pass not specified, get some --help\n"); |
634 return -1; | 634 return -1; |
635 } | 635 } |
636 | 636 |
637 if (!argsOK) | 637 if (!argsOK) |
638 return -2; | 638 return -2; |
639 | 639 |
640 | 640 |
641 /* Open logfile */ | 641 /* Open logfile */ |
642 if (optLogFilename) { | 642 if (optLogFilename) { |
643 THMSG(1, "Opening logfile '%s'\n", optLogFilename); | 643 THMSG(1, "Opening logfile '%s'\n", optLogFilename); |
644 | 644 |
645 if ((optLogFile = fopen(optLogFilename, "a")) == NULL) { | 645 if ((optLogFile = fopen(optLogFilename, "a")) == NULL) { |
646 THERR("Could not open logfile for appending!\n"); | 646 THERR("Could not open logfile for appending!\n"); |
647 return -9; | 647 return -9; |
648 } | 648 } |
649 } | 649 } |
650 | 650 |
651 #ifdef __WIN32 | 651 #ifdef __WIN32 |
652 { | 652 { |
653 /* Initialize WinSock, if needed */ | 653 /* Initialize WinSock, if needed */ |
654 WSADATA wsaData; | 654 WSADATA wsaData; |
655 int err = WSAStartup(0x0101, &wsaData); | 655 int err = WSAStartup(0x0101, &wsaData); |
656 if (err != 0) { | 656 if (err != 0) { |
657 THERR("Could not initialize WinSock DLL: %d\n", err); | 657 THERR("Could not initialize WinSock DLL: %d\n", err); |
658 goto err_exit; | 658 goto err_exit; |
659 } | 659 } |
660 networkInit = TRUE; | 660 networkInit = TRUE; |
661 } | 661 } |
662 #endif | 662 #endif |
663 | 663 |
664 /* Okay ... */ | 664 /* Okay ... */ |
665 THMSG(1, "Trying to resolve host '%s' ...\n", optServer); | 665 THMSG(1, "Trying to resolve host '%s' ...\n", optServer); |
666 tmpHost = gethostbyname(optServer); | 666 tmpHost = gethostbyname(optServer); |
667 if (tmpHost == NULL) { | 667 if (tmpHost == NULL) { |
668 THERR("Could not resolve hostname: %s.\n", | 668 THERR("Could not resolve hostname: %s.\n", |
669 hstrerror(h_errno)); | 669 hstrerror(h_errno)); |
670 goto err_exit; | 670 goto err_exit; |
671 } | 671 } |
672 THMSG(2, "True hostname: %s\n", tmpHost->h_name); | 672 THMSG(2, "True hostname: %s\n", tmpHost->h_name); |
673 | 673 |
674 | 674 |
675 #if 0 | 675 #if 0 |
676 /* To emulate the official client, we first make a request for | 676 /* To emulate the official client, we first make a request for |
677 * policy file, even though we don't use it for anything... | 677 * policy file, even though we don't use it for anything... |
678 */ | 678 */ |
679 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { | 679 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { |
680 THERR("Policy file request connection setup failed!\n"); | 680 THERR("Policy file request connection setup failed!\n"); |
681 goto err_exit; | 681 goto err_exit; |
682 } | 682 } |
683 | 683 |
684 tmpStr = "<policy-file-request/>"; | 684 tmpStr = "<policy-file-request/>"; |
685 if (sendToSocket(tmpSocket, tmpStr, strlen(tmpStr) + 1) == FALSE) { | 685 if (sendToSocket(tmpSocket, tmpStr, strlen(tmpStr) + 1) == FALSE) { |
686 THERR("Failed to send fakeprobe.\n"); | 686 THERR("Failed to send fakeprobe.\n"); |
687 goto err_exit; | 687 goto err_exit; |
688 } else { | 688 } else { |
689 ssize_t gotBuf; | 689 ssize_t gotBuf; |
690 char tmpBuf[SET_BUFSIZE]; | 690 char tmpBuf[SET_BUFSIZE]; |
691 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0); | 691 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0); |
692 tmpBuf[gotBuf-1] = 0; | 692 tmpBuf[gotBuf-1] = 0; |
693 THMSG(2, "Probe got: %s\n", tmpBuf); | 693 THMSG(2, "Probe got: %s\n", tmpBuf); |
694 closeConnection(tmpSocket); | 694 closeConnection(tmpSocket); |
695 } | 695 } |
696 #endif | 696 #endif |
697 | 697 |
698 /* Okay, now do the proper connection ... */ | 698 /* Okay, now do the proper connection ... */ |
699 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { | 699 if ((tmpSocket = openConnection((struct in_addr *) tmpHost->h_addr, optPort)) < 0) { |
700 THERR("Main connection setup failed!\n"); | 700 THERR("Main connection setup failed!\n"); |
701 goto err_exit; | 701 goto err_exit; |
702 } | 702 } |
703 | 703 |
704 THMSG(1, "Connected, logging in as '%s', site '%s'.\n", optUserName, optSite); | 704 THMSG(1, "Connected, logging in as '%s', site '%s'.\n", optUserName, optSite); |
705 optUserName2 = encodeStr1(optUserName); | 705 optUserName2 = encodeStr1(optUserName); |
706 tmpStr = encodeStr1(optSite); | 706 tmpStr = encodeStr1(optSite); |
707 sendUserMsg(tmpSocket, optUserName2, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword); | 707 sendUserMsg(tmpSocket, optUserName2, "%%2Flogin%%20%%2Dsite%%20%s%%20%%2Dpassword%%20%s", tmpStr, optPassword); |
708 th_free(tmpStr); | 708 th_free(tmpStr); |
709 | 709 |
710 /* Initialize NCurses */ | 710 /* Initialize NCurses */ |
711 if (!optDaemon) { | 711 if (!optDaemon) { |
712 if (LINES < 0 || LINES > 1000) LINES = 24; | 712 if (LINES < 0 || LINES > 1000) LINES = 24; |
713 if (COLS < 0 || COLS > 1000) COLS = 80; | 713 if (COLS < 0 || COLS > 1000) COLS = 80; |
714 LINES=24; | 714 LINES=24; |
715 initscr(); | 715 initscr(); |
716 raw(); | 716 raw(); |
717 keypad(stdscr, TRUE); | 717 keypad(stdscr, TRUE); |
718 noecho(); | 718 noecho(); |
719 meta(stdscr, TRUE); | 719 meta(stdscr, TRUE); |
720 timeout(SET_DELAY); | 720 timeout(SET_DELAY); |
721 curVis = curs_set(0); | 721 curVis = curs_set(0); |
722 if (has_colors()) { | 722 if (has_colors()) { |
723 start_color(); | 723 start_color(); |
724 | 724 |
725 init_pair(1, COLOR_RED, COLOR_BLACK); | 725 init_pair(1, COLOR_RED, COLOR_BLACK); |
726 init_pair(2, COLOR_GREEN, COLOR_BLACK); | 726 init_pair(2, COLOR_GREEN, COLOR_BLACK); |
727 init_pair(3, COLOR_YELLOW, COLOR_BLACK); | 727 init_pair(3, COLOR_YELLOW, COLOR_BLACK); |
728 init_pair(4, COLOR_BLUE, COLOR_BLACK); | 728 init_pair(4, COLOR_BLUE, COLOR_BLACK); |
729 init_pair(5, COLOR_MAGENTA, COLOR_BLACK); | 729 init_pair(5, COLOR_MAGENTA, COLOR_BLACK); |
730 init_pair(6, COLOR_CYAN, COLOR_BLACK); | 730 init_pair(6, COLOR_CYAN, COLOR_BLACK); |
731 init_pair(7, COLOR_WHITE, COLOR_BLACK); | 731 init_pair(7, COLOR_WHITE, COLOR_BLACK); |
732 init_pair(8, COLOR_BLACK, COLOR_BLACK); | 732 init_pair(8, COLOR_BLACK, COLOR_BLACK); |
733 | 733 |
734 init_pair(10, COLOR_BLACK, COLOR_RED); | 734 init_pair(10, COLOR_BLACK, COLOR_RED); |
735 init_pair(11, COLOR_WHITE, COLOR_RED); | 735 init_pair(11, COLOR_WHITE, COLOR_RED); |
736 init_pair(12, COLOR_GREEN, COLOR_RED); | 736 init_pair(12, COLOR_GREEN, COLOR_RED); |
737 init_pair(13, COLOR_YELLOW, COLOR_RED); | 737 init_pair(13, COLOR_YELLOW, COLOR_RED); |
738 init_pair(14, COLOR_BLUE, COLOR_RED); | 738 init_pair(14, COLOR_BLUE, COLOR_RED); |
739 init_pair(15, COLOR_MAGENTA, COLOR_RED); | 739 init_pair(15, COLOR_MAGENTA, COLOR_RED); |
740 init_pair(16, COLOR_CYAN, COLOR_RED); | 740 init_pair(16, COLOR_CYAN, COLOR_RED); |
741 | 741 |
742 } | 742 } |
743 | 743 |
744 cursesInit = TRUE; | 744 cursesInit = TRUE; |
745 | 745 |
746 if (!initializeWindows()) | 746 if (!initializeWindows()) |
747 goto err_exit; | 747 goto err_exit; |
748 | 748 |
749 clearBuf(editBuf); | 749 clearBuf(editBuf); |
750 printEditBuf("", editBuf); | 750 printEditBuf("", editBuf); |
751 updateStatus(insertMode); | 751 updateStatus(insertMode); |
752 } | 752 } |
753 | 753 |
754 /* Enter mainloop */ | 754 /* Enter mainloop */ |
755 FD_ZERO(&sockfds); | 755 FD_ZERO(&sockfds); |
756 FD_SET(tmpSocket, &sockfds); | 756 FD_SET(tmpSocket, &sockfds); |
757 | 757 |
758 while (!isError && !exitProg) { | 758 while (!isError && !exitProg) { |
759 int result; | 759 int result; |
760 fd_set tmpfds; | 760 fd_set tmpfds; |
761 | 761 |
762 /* Check for incoming data from the server */ | 762 /* Check for incoming data from the server */ |
763 tv.tv_sec = 0; | 763 tv.tv_sec = 0; |
764 tv.tv_usec = SET_DELAY_USEC; | 764 tv.tv_usec = SET_DELAY_USEC; |
765 tmpfds = sockfds; | 765 tmpfds = sockfds; |
766 if ((result = select(tmpSocket+1, &tmpfds, NULL, NULL, &tv)) == -1) { | 766 if ((result = select(tmpSocket+1, &tmpfds, NULL, NULL, &tv)) == -1) { |
767 int res = getSocketErrno(); | 767 int res = getSocketErrno(); |
768 if (res != EINTR) { | 768 if (res != EINTR) { |
769 printMsg("Error occured in select(sockfds): %d, %s\n", | 769 printMsg("Error occured in select(sockfds): %d, %s\n", |
770 res, getSocketErrStr(res)); | 770 res, getSocketErrStr(res)); |
771 isError = TRUE; | 771 isError = TRUE; |
772 } | 772 } |
773 } else if (FD_ISSET(tmpSocket, &tmpfds)) { | 773 } else if (FD_ISSET(tmpSocket, &tmpfds)) { |
774 ssize_t gotBuf; | 774 ssize_t gotBuf; |
775 char tmpBuf[8192]; | 775 char tmpBuf[8192]; |
776 char *bufPtr = tmpBuf; | 776 char *bufPtr = tmpBuf; |
777 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0); | 777 gotBuf = recv(tmpSocket, tmpBuf, sizeof(tmpBuf), 0); |
778 | 778 |
779 if (gotBuf < 0) { | 779 if (gotBuf < 0) { |
780 int res = getSocketErrno(); | 780 int res = getSocketErrno(); |
781 printMsg("Error in recv: %d, %s\n", res, getSocketErrStr(res)); | 781 printMsg("Error in recv: %d, %s\n", res, getSocketErrStr(res)); |
782 isError = TRUE; | 782 isError = TRUE; |
783 } else if (gotBuf == 0) { | 783 } else if (gotBuf == 0) { |
784 printMsg("Server closed connection.\n"); | 784 printMsg("Server closed connection.\n"); |
785 isError = TRUE; | 785 isError = TRUE; |
786 } else { | 786 } else { |
787 /* Handle protocol data */ | 787 /* Handle protocol data */ |
788 tmpBuf[gotBuf] = 0; | 788 tmpBuf[gotBuf] = 0; |
789 do { | 789 do { |
790 size_t bufLen = strlen(bufPtr) + 1; | 790 size_t bufLen = strlen(bufPtr) + 1; |
791 result = handleProtocol(tmpSocket, bufPtr, bufLen); | 791 result = handleProtocol(tmpSocket, bufPtr, bufLen); |
792 | 792 |
793 if (result > 0) { | 793 if (result > 0) { |
794 /* Couldn't handle the message for some reason */ | 794 /* Couldn't handle the message for some reason */ |
795 printMsg("Could not handle: %s\n", tmpBuf); | 795 printMsg("Could not handle: %s\n", tmpBuf); |
796 } else if (result < 0) { | 796 } else if (result < 0) { |
797 /* Fatal error, quit */ | 797 /* Fatal error, quit */ |
798 printMsg("Fatal error with message: %s\n", tmpBuf); | 798 printMsg("Fatal error with message: %s\n", tmpBuf); |
799 isError = TRUE; | 799 isError = TRUE; |
800 } | 800 } |
801 | 801 |
802 gotBuf -= bufLen; | 802 gotBuf -= bufLen; |
803 bufPtr += bufLen; | 803 bufPtr += bufLen; |
804 } while (gotBuf > 0 && !isError); | 804 } while (gotBuf > 0 && !isError); |
805 updateStatus(insertMode); | 805 updateStatus(insertMode); |
806 } | 806 } |
807 } | 807 } |
808 | 808 |
809 /* Handle user input */ | 809 /* Handle user input */ |
810 if (!optDaemon) { | 810 if (!optDaemon) { |
811 int c, cnt = 0; | 811 int c, cnt = 0; |
812 BOOL update = FALSE; | 812 BOOL update = FALSE; |
813 | 813 |
814 /* Handle several buffered keypresses at once */ | 814 /* Handle several buffered keypresses at once */ |
815 do { | 815 do { |
816 c = wgetch(stdscr); | 816 c = wgetch(stdscr); |
817 switch (c) { | 817 switch (c) { |
818 case KEY_RESIZE: | 818 case KEY_RESIZE: |
819 if (!initializeWindows()) { | 819 if (!initializeWindows()) { |
820 THERR("Error resizing ncurses windows\n"); | 820 THERR("Error resizing ncurses windows\n"); |
821 isError = TRUE; | 821 isError = TRUE; |
822 } | 822 } |
823 break; | 823 break; |
824 | 824 |
825 case KEY_ENTER: | 825 case KEY_ENTER: |
826 case '\n': | 826 case '\n': |
827 case '\r': | 827 case '\r': |
828 /* Call the user input handler */ | 828 /* Call the user input handler */ |
829 if (editBuf->len > 0) { | 829 if (editBuf->len > 0) { |
830 | 830 |
831 if (histMax > 0) { | 831 if (histMax > 0) { |
832 freeBuf(histBuf[SET_MAX_HISTORY+1]); | 832 freeBuf(histBuf[SET_MAX_HISTORY+1]); |
833 histBuf[SET_MAX_HISTORY+1] = NULL; | 833 histBuf[SET_MAX_HISTORY+1] = NULL; |
834 memmove(&histBuf[2], &histBuf[1], histMax * sizeof(histBuf[0])); | 834 memmove(&histBuf[2], &histBuf[1], histMax * sizeof(histBuf[0])); |
835 } | 835 } |
836 | 836 |
837 histPos = 0; | 837 histPos = 0; |
838 histBuf[1] = copyBuf(editBuf); | 838 histBuf[1] = copyBuf(editBuf); |
839 if (histMax < SET_MAX_HISTORY) histMax++; | 839 if (histMax < SET_MAX_HISTORY) histMax++; |
840 | 840 |
841 insertBuf(editBuf, editBuf->len, 0); | 841 insertBuf(editBuf, editBuf->len, 0); |
842 result = handleUserInput(tmpSocket, editBuf->data, editBuf->len); | 842 result = handleUserInput(tmpSocket, editBuf->data, editBuf->len); |
843 | 843 |
844 clearBuf(editBuf); | 844 clearBuf(editBuf); |
845 | 845 |
846 if (result < 0) { | 846 if (result < 0) { |
847 printMsg("Fatal error handling user input: %s\n", editBuf->data); | 847 printMsg("Fatal error handling user input: %s\n", editBuf->data); |
848 isError = TRUE; | 848 isError = TRUE; |
849 } | 849 } |
850 | 850 |
851 update = TRUE; | 851 update = TRUE; |
852 } | 852 } |
853 break; | 853 break; |
854 | 854 |
855 case 0x09: /* Tab = switch between PRV */ | 855 case 0x09: /* Tab = switch between PRV */ |
856 if (setPrvMode) | 856 if (setPrvMode) |
857 setPrvMode = FALSE; | 857 setPrvMode = FALSE; |
858 else { | 858 else { |
859 if (setTarget != NULL) | 859 if (setTarget != NULL) |
860 setPrvMode = TRUE; | 860 setPrvMode = TRUE; |
861 } | 861 } |
862 update = TRUE; | 862 update = TRUE; |
863 break; | 863 break; |
864 | 864 |
865 case KEY_UP: /* Backwards in input history */ | 865 case KEY_UP: /* Backwards in input history */ |
866 if (histPos == 0) { | 866 if (histPos == 0) { |
867 freeBuf(histBuf[0]); | 867 freeBuf(histBuf[0]); |
868 histBuf[0] = copyBuf(editBuf); | 868 histBuf[0] = copyBuf(editBuf); |
869 } | 869 } |
870 if (histPos < histMax) { | 870 if (histPos < histMax) { |
871 histPos++; | 871 histPos++; |
872 freeBuf(editBuf); | 872 freeBuf(editBuf); |
873 editBuf = copyBuf(histBuf[histPos]); | 873 editBuf = copyBuf(histBuf[histPos]); |
874 update = TRUE; | 874 update = TRUE; |
875 } | 875 } |
876 break; | 876 break; |
877 | 877 |
878 case KEY_DOWN: /* Forwards in input history */ | 878 case KEY_DOWN: /* Forwards in input history */ |
879 if (histPos > 0) { | 879 if (histPos > 0) { |
880 histPos--; | 880 histPos--; |
881 freeBuf(editBuf); | 881 freeBuf(editBuf); |
882 editBuf = copyBuf(histBuf[histPos]); | 882 editBuf = copyBuf(histBuf[histPos]); |
883 update = TRUE; | 883 update = TRUE; |
884 } | 884 } |
885 break; | 885 break; |
886 | 886 |
887 case 0x204: /* ctrl+left = Skip words left */ | 887 case 0x204: /* ctrl+left = Skip words left */ |
888 while (editBuf->pos > 0 && isspace(editBuf->data[editBuf->pos - 1])) | 888 while (editBuf->pos > 0 && isspace(editBuf->data[editBuf->pos - 1])) |
889 editBuf->pos--; | 889 editBuf->pos--; |
890 while (editBuf->pos > 0 && !isspace(editBuf->data[editBuf->pos - 1])) | 890 while (editBuf->pos > 0 && !isspace(editBuf->data[editBuf->pos - 1])) |
891 editBuf->pos--; | 891 editBuf->pos--; |
892 update = TRUE; | 892 update = TRUE; |
893 break; | 893 break; |
894 | 894 |
895 case 0x206: /* ctrl+right = Skip words right */ | 895 case 0x206: /* ctrl+right = Skip words right */ |
896 while (editBuf->pos < editBuf->len && isspace(editBuf->data[editBuf->pos])) | 896 while (editBuf->pos < editBuf->len && isspace(editBuf->data[editBuf->pos])) |
897 editBuf->pos++; | 897 editBuf->pos++; |
898 while (editBuf->pos < editBuf->len && !isspace(editBuf->data[editBuf->pos])) | 898 while (editBuf->pos < editBuf->len && !isspace(editBuf->data[editBuf->pos])) |
899 editBuf->pos++; | 899 editBuf->pos++; |
900 if (editBuf->pos > editBuf->len) | 900 if (editBuf->pos > editBuf->len) |
901 editBuf->pos = editBuf->len; | 901 editBuf->pos = editBuf->len; |
902 update = TRUE; | 902 update = TRUE; |
903 break; | 903 break; |
904 | 904 |
905 case 0x111: /* F9 = Quit */ | 905 case 0x111: /* F9 = Quit */ |
906 printMsg("Quitting per user request.\n"); | 906 printMsg("Quitting per user request.\n"); |
907 exitProg = TRUE; | 907 exitProg = TRUE; |
908 break; | 908 break; |
909 | 909 |
910 case 0x109: /* F1 = Toggle insert / overwrite mode */ | 910 case 0x109: /* F1 = Toggle insert / overwrite mode */ |
911 insertMode = !insertMode; | 911 insertMode = !insertMode; |
912 update = TRUE; | 912 update = TRUE; |
913 break; | 913 break; |
914 | 914 |
915 case 0x10a: /* F2 = Clear editbuffer */ | 915 case 0x10a: /* F2 = Clear editbuffer */ |
916 clearBuf(editBuf); | 916 clearBuf(editBuf); |
917 update = TRUE; | 917 update = TRUE; |
918 break; | 918 break; |
919 | 919 |
920 case KEY_HOME: setBufPos(editBuf, 0); update = TRUE; break; | 920 case KEY_HOME: setBufPos(editBuf, 0); update = TRUE; break; |
921 case KEY_END: setBufPos(editBuf, editBuf->len); update = TRUE; break; | 921 case KEY_END: setBufPos(editBuf, editBuf->len); update = TRUE; break; |
922 case KEY_LEFT: setBufPos(editBuf, editBuf->pos - 1); update = TRUE; break; | 922 case KEY_LEFT: setBufPos(editBuf, editBuf->pos - 1); update = TRUE; break; |
923 case KEY_RIGHT: setBufPos(editBuf, editBuf->pos + 1); update = TRUE; break; | 923 case KEY_RIGHT: setBufPos(editBuf, editBuf->pos + 1); update = TRUE; break; |
924 | 924 |
925 case KEY_BACKSPACE: | 925 case KEY_BACKSPACE: |
926 deleteBuf(editBuf, editBuf->pos - 1); | 926 deleteBuf(editBuf, editBuf->pos - 1); |
927 setBufPos(editBuf, editBuf->pos - 1); | 927 setBufPos(editBuf, editBuf->pos - 1); |
928 update = TRUE; | 928 update = TRUE; |
929 break; | 929 break; |
930 | 930 |
931 case 0x14a: | 931 case 0x14a: |
932 /* Delete */ | 932 /* Delete */ |
933 deleteBuf(editBuf, editBuf->pos); | 933 deleteBuf(editBuf, editBuf->pos); |
934 update = TRUE; | 934 update = TRUE; |
935 break; | 935 break; |
936 | 936 |
937 case 0x0c: | 937 case 0x0c: |
938 /* ctrl+l */ | 938 /* ctrl+l */ |
939 redrawwin(mainWin); | 939 redrawwin(mainWin); |
940 redrawwin(statusWin); | 940 redrawwin(statusWin); |
941 redrawwin(editWin); | 941 redrawwin(editWin); |
942 break; | 942 break; |
943 | 943 |
944 case ERR: | 944 case ERR: |
945 /* Ignore */ | 945 /* Ignore */ |
946 break; | 946 break; |
947 | 947 |
948 default: | 948 default: |
949 if (isprint(c) || c == 0xe4 || c == 0xf6 || c == 0xc4 || c == 0xd6) { | 949 if (isprint(c) || c == 0xe4 || c == 0xf6 || c == 0xc4 || c == 0xd6) { |
950 if (insertMode) | 950 if (insertMode) |
951 insertBuf(editBuf, editBuf->pos, c); | 951 insertBuf(editBuf, editBuf->pos, c); |
952 else | 952 else |
953 writeBuf(editBuf, editBuf->pos, c); | 953 writeBuf(editBuf, editBuf->pos, c); |
954 setBufPos(editBuf, editBuf->pos + 1); | 954 setBufPos(editBuf, editBuf->pos + 1); |
955 update = TRUE; | 955 update = TRUE; |
956 } else { | 956 } else { |
957 printMsg("Unhandled key: %02x\n", c); | 957 printMsg("Unhandled key: %02x\n", c); |
958 } | 958 } |
959 break; | 959 break; |
960 } | 960 } |
961 } while (c != ERR && !exitProg && ++cnt < 10); | 961 } while (c != ERR && !exitProg && ++cnt < 10); |
962 | 962 |
963 if (update) { | 963 if (update) { |
964 /* Update edit line */ | 964 /* Update edit line */ |
965 printEditBuf(setPrvMode ? setTarget : "", editBuf); | 965 printEditBuf(setPrvMode ? setTarget : "", editBuf); |
966 updateStatus(insertMode); | 966 updateStatus(insertMode); |
967 } | 967 } |
968 } /* !optDaemon */ | 968 } /* !optDaemon */ |
969 | 969 |
970 if (++updateCount > 10) { | 970 if (++updateCount > 10) { |
971 updateStatus(insertMode); | 971 updateStatus(insertMode); |
972 updateCount = 0; | 972 updateCount = 0; |
973 } | 973 } |
974 | 974 |
975 if (!colorSet) { | 975 if (!colorSet) { |
976 colorSet = TRUE; | 976 colorSet = TRUE; |
977 printMsg("%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname); | 977 printMsg("%s v%s - %s\n", th_prog_name, th_prog_version, th_prog_fullname); |
978 printMsg("%s\n", th_prog_author); | 978 printMsg("%s\n", th_prog_author); |
979 printMsg("%s\n", th_prog_license); | 979 printMsg("%s\n", th_prog_license); |
980 sendUserMsg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); | 980 sendUserMsg(tmpSocket, optUserName2, "%%2FSetFontColor%%20%%2Dcolor%%20%06X", optUserColor); |
981 } | 981 } |
982 } | 982 } |
983 | 983 |
984 /* Shutdown */ | 984 /* Shutdown */ |
985 err_exit: | 985 err_exit: |
986 if (cursesInit) { | 986 if (cursesInit) { |
987 if (curVis != ERR) | 987 if (curVis != ERR) |
988 curs_set(curVis); | 988 curs_set(curVis); |
989 endwin(); | 989 endwin(); |
990 THMSG(1, "NCurses deinitialized.\n"); | 990 THMSG(1, "NCurses deinitialized.\n"); |
991 } | 991 } |
992 | 992 |
993 if (isError) { | 993 if (isError) { |
994 THMSG(1, "Error exit.\n"); | 994 THMSG(1, "Error exit.\n"); |
995 } | 995 } |
996 | 996 |
997 th_free(optUserName2); | 997 th_free(optUserName2); |
998 | 998 |
999 closeConnection(tmpSocket); | 999 closeConnection(tmpSocket); |
1000 | 1000 |
1001 #ifdef __WIN32 | 1001 #ifdef __WIN32 |
1002 if (networkInit) | 1002 if (networkInit) |
1003 WSACleanup(); | 1003 WSACleanup(); |
1004 #endif | 1004 #endif |
1005 | 1005 |
1006 THMSG(1, "Connection terminated.\n"); | 1006 THMSG(1, "Connection terminated.\n"); |
1007 | 1007 |
1008 if (optLogFile) { | 1008 if (optLogFile) { |
1009 THMSG(1, "Closing logfile.\n"); | 1009 THMSG(1, "Closing logfile.\n"); |
1010 fclose(optLogFile); | 1010 fclose(optLogFile); |
1011 } | 1011 } |
1012 | 1012 |
1013 return 0; | 1013 return 0; |
1014 } | 1014 } |