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 }