summaryrefslogtreecommitdiff
path: root/vchat-protocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'vchat-protocol.c')
-rw-r--r--[-rwxr-xr-x]vchat-protocol.c799
1 files changed, 264 insertions, 535 deletions
diff --git a/vchat-protocol.c b/vchat-protocol.c
index f1b71a1..c5021e4 100755..100644
--- a/vchat-protocol.c
+++ b/vchat-protocol.c
@@ -1,6 +1,6 @@
1/* 1/*
2 * vchat-client - alpha version 2 * vchat-client - alpha version
3 * vchat-protocol.c - handling of server connection & messages 3 * vchat-protocol.c - handling of server messages
4 * 4 *
5 * Copyright (C) 2001 Andreas Kotes <count@flatline.de> 5 * Copyright (C) 2001 Andreas Kotes <count@flatline.de>
6 * 6 *
@@ -10,528 +10,367 @@
10 * without even the implied warranty of merchantability or fitness for a 10 * without even the implied warranty of merchantability or fitness for a
11 * particular purpose. In no event shall the copyright holder be liable for 11 * particular purpose. In no event shall the copyright holder be liable for
12 * any direct, indirect, incidental or special damages arising in any way out 12 * any direct, indirect, incidental or special damages arising in any way out
13 * of the use of this software. 13 * of the use of this software.
14 * 14 *
15 */ 15 */
16 16
17/* general includes */ 17/* general includes */
18#include <unistd.h>
19#include <errno.h> 18#include <errno.h>
19#include <langinfo.h>
20#include <locale.h>
20#include <stdio.h> 21#include <stdio.h>
21#include <netdb.h> 22#include <stdlib.h>
22#include <string.h> 23#include <string.h>
23#include <sys/types.h> 24
24#include <sys/socket.h>
25#include <netinet/in.h>
26#include <readline/readline.h> 25#include <readline/readline.h>
27#include <locale.h>
28#include <langinfo.h>
29 26
30// TO BE GONE 27#ifdef DEBUG
31#include <openssl/bio.h> 28FILE *dumpfile;
29#endif
32 30
33/* local includes */ 31/* local includes */
34#include "vchat.h" 32#include "vchat-connection.h"
35#include "vchat-user.h" 33#include "vchat-user.h"
36#include "vchat-ssl.h" 34#include "vchat.h"
37 35
38/* version of this module */ 36/* version of this module */
39const char *vchat_io_version = "vchat-protocol.c $Id$"; 37const char *vchat_io_version =
40 38 "vchat-protocol.c $Id$";
41/* externally used variables */
42int serverfd = -1;
43
44/* locally global variables */
45/* our connection BIO */
46static BIO *server_conn = NULL;
47 39
48/* declaration of local helper functions */ 40/* declaration of local helper functions */
49static void usersignon (char *); 41static void usersignon(char *);
50static void usersignoff (char *); 42static void usersignoff(char *);
51static void usernickchange (char *); 43static void usernickchange(char *);
52static void userjoin (char *); 44static void userjoin(char *);
53static void userleave (char *); 45static void userleave(char *);
54static void receivenicks (char *message); 46static void receivenicks(char *message);
55static void justloggedin (char *message); 47static void justloggedin(char *message);
56static void nickerr (char *message); 48static void nickerr(char *message);
57static void login (char *message); 49static void login(char *message);
58static void anonlogin (char *message); 50static void anonlogin(char *message);
59static void topicinfo (char *message); 51static void topicinfo(char *message);
60static void pubaction (char *message); 52static void pubaction(char *message);
61static void pubthoughts (char *message); 53static void pubthoughts(char *message);
62static void serverlogin (char *message); 54static void serverlogin(char *message);
63static void idleprompt (char *message); 55static void idleprompt(char *message);
64static void topicchange (char *message); 56static void topicchange(char *message);
65static void pmnotsent (char *message); 57static void pmnotsent(char *message);
66 58
67/* declaration of server message array */ 59/* declaration of server message array */
68#include "vchat-messages.h" 60#include "vchat-messages.h"
69 61
70/* status-variable from vchat-client.c
71 * eventloop is done as long as this is true */
72extern int status;
73char *encoding; 62char *encoding;
74 63
75static int connect_socket( char *server, char *port ) {
76 struct addrinfo hints, *res, *res0;
77 int s, error;
78
79 memset(&hints, 0, sizeof(hints));
80 hints.ai_family = PF_UNSPEC;
81 hints.ai_socktype = SOCK_STREAM;
82 error = getaddrinfo( server, port, &hints, &res0 );
83 if (error) return -1;
84 s = -1;
85 for (res = res0; res; res = res->ai_next) {
86 s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
87 if (s < 0) continue;
88 if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
89 close(s);
90 s = -1;
91 continue;
92 }
93 break; /* okay we got one */
94 }
95 freeaddrinfo(res0);
96
97 if (want_tcp_keepalive) { /* global from vchat-client.c */
98 int one=1;
99 setsockopt(s,SOL_SOCKET,SO_KEEPALIVE,&one,sizeof(one));
100 }
101 return s;
102}
103
104/* connects to server */
105int
106vcconnect (char *server, char *port)
107{
108 /* used for tilde expansion of cert & key filenames */
109 char *tildex = NULL;
110
111 /* vchat connection x509 store */
112 vc_x509store_t *vc_store;
113
114 /* pointer to tilde-expanded certificate/keyfile-names */
115 char *certfile = NULL, *keyfile = NULL;
116
117 /* Connect to the server */
118 serverfd = connect_socket( server, port );
119 if( serverfd < 0 ) {
120 /* inform user */
121 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port );
122 writechan (tmpstr);
123 return -1;
124 }
125 /* Abstract server IO in openssls BIO */
126 server_conn = BIO_new_socket( serverfd, 1 );
127
128 /* If SSL is requested, get our ssl-BIO running */
129 if( server_conn && getintoption(CF_USESSL) ) {
130 vc_store = vc_init_x509store();
131 if( !vc_store ) {
132 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), "Out of memory" );
133 writechan (tmpstr);
134 return -1;
135 }
136
137 vc_x509store_setflags(vc_store, VC_X509S_SSL_VERIFY_PEER);
138
139 /* get name of certificate file */
140 certfile = getstroption (CF_CERTFILE);
141 /* do we have a certificate file? */
142 if (certfile) {
143 /* does the filename start with a tilde? expand it! */
144 if (certfile[0] == '~')
145 tildex = tilde_expand (certfile);
146 else
147 tildex = certfile;
148
149 vc_x509store_setflags(vc_store, VC_X509S_USE_CERTIFICATE);
150 vc_x509store_setcertfile(vc_store, tildex);
151
152 /* get name of key file */
153 keyfile = getstroption (CF_KEYFILE);
154
155 /* if we don't have a key file, the key may be in the cert file */
156 if (!keyfile)
157 keyfile = certfile;
158
159 /* does the filename start with a tilde? expand it! */
160 if (keyfile[0] == '~')
161 tildex = tilde_expand (keyfile);
162 else
163 tildex = keyfile;
164
165 vc_x509store_set_pkeycb(vc_store, (vc_askpass_cb_t)passprompt);
166 vc_x509store_setkeyfile(vc_store, tildex);
167 }
168
169 /* upgrade our plain BIO to ssl */
170 if( vc_connect_ssl( &server_conn, vc_store ) ) {
171 BIO_free_all( server_conn );
172 server_conn = NULL;
173 errno = EIO;
174 }
175 }
176
177 if( !server_conn ) {
178 /* inform user */
179 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CANTCONNECT), server, port );
180 writechan (tmpstr);
181 return -1;
182 }
183
184 /* inform user */
185 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CONNECTED), server, port);
186 writechan (tmpstr);
187
188 /* if we didn't fail until now, we've got a connection. */
189 return 0;
190}
191
192/* disconnect from server */
193void
194vcdisconnect () {
195 BIO_free_all( server_conn );
196 server_conn = 0;
197 if (serverfd>0) {
198 close(serverfd);
199 serverfd = -1;
200 }
201}
202
203/* handle a pm not sent error 64/* handle a pm not sent error
204 * format: 412 %s */ 65 * format: 412 %s */
205static void 66static void pmnotsent(char *message) {
206pmnotsent (char *message) 67 while (*message && *message != ' ')
207{ 68 message++;
208 while(*message && *message!=' ') message++; 69 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_ERR), message + 1);
209 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_ERR),message+1); 70 writepriv(tmpstr, 0);
210 writepriv( tmpstr, 0);
211
212} 71}
213 72
214/* parse and handle an action string 73/* parse and handle an action string
215 * format: 118 %s %s 74 * format: 118 %s %s
216 * vars: %s nick 75 * vars: %s nick
217 * %s action */ 76 * %s action */
218static void 77static void pubaction(char *message) {
219pubaction (char *message)
220{
221 char *nick = NULL, *action = NULL; 78 char *nick = NULL, *action = NULL;
222 nick = strchr (message, ' '); 79 nick = strchr(message, ' ');
223 nick[0] = '\0'; 80 nick[0] = '\0';
224 nick++; 81 nick++;
225 82
226 action = strchr (nick, ' '); 83 action = strchr(nick, ' ');
227 action[0] = '\0'; 84 action[0] = '\0';
228 action++; 85 action++;
229 86
230 ul_public_action(nick); 87 ul_public_action(nick);
231 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_PUBACTION),nick,action); 88 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_PUBACTION), nick, action);
232 writechan (tmpstr); 89 writechan(tmpstr);
233} 90}
234 91
235/* parse and handle an thought string 92/* parse and handle an thought string
236 * format: 124 %s %s 93 * format: 124 %s %s
237 * vars: %s nick 94 * vars: %s nick
238 * %s thought */ 95 * %s thought */
239static void 96static void pubthoughts(char *message) {
240pubthoughts (char *message)
241{
242 char *nick = NULL, *thoughts = NULL; 97 char *nick = NULL, *thoughts = NULL;
243 nick = strchr (message, ' '); 98 nick = strchr(message, ' ');
244 nick[0] = '\0'; 99 nick[0] = '\0';
245 nick++; 100 nick++;
246 101
247 thoughts = strchr (nick, ' '); 102 thoughts = strchr(nick, ' ');
248 thoughts[0] = '\0'; 103 thoughts[0] = '\0';
249 thoughts++; 104 thoughts++;
250 105
251 ul_public_action(nick); 106 ul_public_action(nick);
252 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_PUBTHOUGHT),nick,thoughts); 107 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_PUBTHOUGHT), nick, thoughts);
253 writechan (tmpstr); 108 writechan(tmpstr);
254} 109}
255 110
256/* parse and handle server logon */ 111/* parse and handle server logon */
257static void 112static void serverlogin(char *message) {
258serverlogin (char *message) 113 (void)message;
259{ 114 int utf8 = !strcmp(nl_langinfo(CODESET), "UTF-8");
260 int utf8=!strcmp(nl_langinfo(CODESET), "UTF-8");
261 if (utf8) 115 if (utf8)
262 networkoutput(".e utf8"); 116 vc_sendmessage(".e utf8");
263} 117}
264 118
265/* parse and handle an idle message 119/* parse and handle an idle message
266 * format: 305 120 * format: 305
267 * vars: %s message */ 121 * vars: %s message */
268static void 122static void idleprompt(char *message) {
269idleprompt (char *message)
270{
271 char *msg = NULL; 123 char *msg = NULL;
272 msg = strchr (message, ' '); 124 msg = strchr(message, ' ');
273 msg[0] = '\0'; 125 msg[0] = '\0';
274 msg++; 126 msg++;
275 127
276 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_IDLE),msg); 128 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_IDLE), msg);
277 writechan (tmpstr); 129 writechan(tmpstr);
278} 130}
279 131
280/* parse and handle a topic information string 132/* parse and handle a topic information string
281 * format: 115 %d %s 133 * format: 115 %d %s
282 * vars: %d chan - channel number 134 * vars: %d chan - channel number
283 * %s topic - topic */ 135 * %s topic - topic */
284static void 136static void topicinfo(char *message) {
285topicinfo (char *message)
286{
287 char *channel = NULL, *topic = NULL; 137 char *channel = NULL, *topic = NULL;
288 int tmpchan = 0, ownchan = own_channel_get(); 138 int tmpchan = 0, ownchan = own_channel_get();
289 139
290 /* search start of channel number */ 140 /* search start of channel number */
291 channel = strchr (message, ' '); 141 channel = strchr(message, ' ');
292 channel++; 142 channel++;
293 143
294 /* search start of topic and terminate channel number */ 144 /* search start of topic and terminate channel number */
295 topic = strchr (channel, ' '); 145 topic = strchr(channel, ' ');
296 topic[0] = '\0'; 146 topic[0] = '\0';
297 topic++; 147 topic++;
298 148
299 /* convert channel number to integer */ 149 /* convert channel number to integer */
300 tmpchan = atoi (channel); 150 tmpchan = atoi(channel);
301 151
302 if (tmpchan == ownchan ) { 152 if (tmpchan == ownchan) {
303 /* show change in topic window */ 153 /* show change in topic window */
304 if (strlen(topic)) 154 if (strlen(topic))
305 snprintf (topicstr, TOPICSTRSIZE, getformatstr(FS_TOPICW), ownchan, topic); 155 snprintf(topicstr, TOPICSTRSIZE, getformatstr(FS_TOPICW), ownchan, topic);
306 else 156 else
307 snprintf (topicstr, TOPICSTRSIZE, getformatstr(FS_NOTOPICW), ownchan ); 157 snprintf(topicstr, TOPICSTRSIZE, getformatstr(FS_NOTOPICW), ownchan);
308 topicline(NULL); 158 topicline(NULL);
309 } 159 }
310 160
311 /* announce change in channel window */ 161 /* announce change in channel window */
312 if (strlen(topic)) 162 if (strlen(topic))
313 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_TOPIC), tmpchan, topic); 163 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_TOPIC), tmpchan, topic);
314 else 164 else
315 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_NOTOPIC), tmpchan); 165 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_NOTOPIC), tmpchan);
316 writechan (tmpstr); 166 writechan(tmpstr);
317} 167}
318 168
319/* parse and handle a topic change string 169/* parse and handle a topic change string
320 * format: 114 %s changes topic to '%s' 170 * format: 114 %s changes topic to '%s'
321 * vars: %s nick 171 * vars: %s nick
322 * %s topic */ 172 * %s topic */
323static void 173static void topicchange(char *message) {
324topicchange (char *message)
325{
326 char *nick = NULL, *topic = NULL; 174 char *nick = NULL, *topic = NULL;
327 int len, ownchan = own_channel_get(); 175 int len, ownchan = own_channel_get();
328 176
329 /* search start of nickname */ 177 /* search start of nickname */
330 nick = strchr (message, ' '); 178 nick = strchr(message, ' ');
331 nick++; 179 nick++;
332 180
333 /* search start of message before topic, terminate nick */ 181 /* search start of message before topic, terminate nick */
334 topic = strchr (nick, ' '); 182 topic = strchr(nick, ' ');
335 topic[0] = '\0'; 183 topic[0] = '\0';
336 topic++; 184 topic++;
337 185
338 /* search start of real topic and terminate channel number */ 186 /* search start of real topic and terminate channel number */
339 topic = strchr (topic, '\''); 187 topic = strchr(topic, '\'');
340 topic[0] = '\0'; 188 topic[0] = '\0';
341 topic++; 189 topic++;
342 190
343 /* remove ending '\'', if there */ 191 /* remove ending '\'', if there */
344 len = strlen (topic); 192 len = strlen(topic);
345 if (topic[len-1] == '\'') 193 if (topic[len - 1] == '\'')
346 topic[len-1] = '\0'; 194 topic[len - 1] = '\0';
347 195
348 ul_public_action(nick); 196 ul_public_action(nick);
349 /* show change in topic window */ 197 /* show change in topic window */
350 snprintf (topicstr, TOPICSTRSIZE, getformatstr(FS_TOPICW), ownchan, topic); 198 snprintf(topicstr, TOPICSTRSIZE, getformatstr(FS_TOPICW), ownchan, topic);
351 topicline(NULL); 199 topicline(NULL);
352 200
353 /* announce change in channel window */ 201 /* announce change in channel window */
354 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_CHGTOPIC), nick, topic); 202 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_CHGTOPIC), nick, topic);
355 writechan (tmpstr); 203 writechan(tmpstr);
356} 204}
357 205
358/* parse and handle a login message 206/* parse and handle a login message
359 * format: 212 %s %s 207 * format: 212 %s %s
360 * vars: %s str1 - nick used to login 208 * vars: %s str1 - nick used to login
361 * %s str2 - servers message */ 209 * %s str2 - servers message */
362static void 210static void justloggedin(char *message) {
363justloggedin (char *message)
364{
365 char *str1 = NULL, *str2 = NULL; 211 char *str1 = NULL, *str2 = NULL;
366 /* search start of nickname */ 212 /* search start of nickname */
367 str1 = strchr (message, ' '); 213 str1 = strchr(message, ' ');
368 str1++; 214 str1++;
369 215
370 /* search start of message, terminate nick */ 216 /* search start of message, terminate nick */
371 str2 = strchr (str1, ' '); 217 str2 = strchr(str1, ' ');
372 str2[0] = '\0'; 218 str2[0] = '\0';
373 str2++; 219 str2++;
374 220
375 /* if we have a new nick, store it */ 221 /* if we have a new nick, store it */
376 own_nick_set( str1 ); 222 own_nick_set(str1);
377 223
378 /* show change in console window */ 224 /* show change in console window */
379 snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), str1, getstroption (CF_SERVERHOST), getstroption (CF_SERVERPORT)); 225 snprintf(consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), str1,
380 consoleline (NULL); 226 getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT));
227 consoleline(NULL);
381 228
382 /* announce login as servermessage */ 229 /* announce login as servermessage */
383 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNON), str1, str2); 230 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNON), str1, str2);
384 writechan (tmpstr); 231 writechan(tmpstr);
385 232
386 /* we're not logged in, change status and request nicks */ 233 /* we're not logged in, change status and request nicks */
387 if (!loggedin) 234 if (!loggedin) {
388 { 235 loadcfg(getstroption(CF_LOGINSCRIPT), 0, handleline);
389 loadcfg(getstroption(CF_LOGINSCRIPT),0,handleline); 236 handleline(".S");
390 handleline(".S"); 237 loggedin = 1;
391 loggedin = 1; 238 flushconnect();
392 } 239 }
393} 240}
394 241
395/* this user joins a different channel */ 242/* this user joins a different channel */
396void 243void ownjoin(int channel) {
397ownjoin (int channel) 244 vc_sendmessage(".t");
398{ 245 snprintf(tmpstr, TMPSTRSIZE, ".S %d", channel);
399 networkoutput(".t"); 246 vc_sendmessage(tmpstr);
400 snprintf(tmpstr, TMPSTRSIZE, ".S %d",channel);
401 networkoutput(tmpstr);
402} 247}
403 248
404/* this user changes his nick */ 249/* this user changes his nick */
405void 250void ownnickchange(const char *newnick) { (void)newnick; }
406ownnickchange (char *newnick)
407{
408}
409 251
410/* parse and handle a nick error message 252/* parse and handle a nick error message
411 * format: 401 %s 253 * format: 401 %s
412 * 403 %s 254 * 403 %s
413 * 415 %s 255 * 415 %s
414 * vars: %s - server message */ 256 * vars: %s - server message */
415static void 257static void nickerr(char *message) {
416nickerr (char *message)
417{
418 char *helpkiller = NULL; 258 char *helpkiller = NULL;
419 /* mutate message for output */ 259 /* mutate message for output */
420 message[2] = '!'; 260 message[2] = '!';
421 /* help information found? remove it. */ 261 /* help information found? remove it. */
422 if ((helpkiller = strstr (message, " Type .h for help"))) 262 if ((helpkiller = strstr(message, " Type .h for help")))
423 helpkiller[0] = '\0'; 263 helpkiller[0] = '\0';
424 /* nickchange not done? eliminate message */ 264 /* nickchange not done? eliminate message */
425 if (loggedin && (helpkiller = strstr (message, " - Nick not changed"))) 265 if (loggedin && (helpkiller = strstr(message, " - Nick not changed")))
426 helpkiller[0] = '\0'; 266 helpkiller[0] = '\0';
427 /* show errormessage */ 267 /* show errormessage */
428 writecf (FS_ERR,&message[2]); 268 writecf(FS_ERR, &message[2]);
429 269
430 /* not logged in? insist on getting a new nick */ 270 /* not logged in? insist on getting a new nick */
431 if (!loggedin) 271 if (!loggedin) {
432 { 272 /* free bogus nick */
433 /* free bogus nick */ 273 own_nick_set(NULL);
434 own_nick_set(NULL);
435 274
436 /* get new nick via vchat-ui.c */ 275 /* get new nick via vchat-ui.c */
437 nickprompt (); 276 nickprompt();
438 277
439 /* form login message and send it to server */ 278 /* form login message and send it to server */
440 snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); 279 snprintf(tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(),
441 networkoutput (tmpstr); 280 getstroption(CF_FROM), getintoption(CF_CHANNEL));
442 } 281 vc_sendmessage(tmpstr);
282 }
443} 283}
444 284
445/* parse and handle a registered nick information 285/* parse and handle a registered nick information
446 * format: 120 %s %s 286 * format: 120 %s %s
447 * vars: %s - this users registered nick 287 * vars: %s - this users registered nick
448 * %s msg - server message */ 288 * %s msg - server message */
449static void 289static void login(char *message) {
450login (char *message) {
451 char *msg = NULL; 290 char *msg = NULL;
452 291
453 /* mutate message for output */ 292 /* mutate message for output */
454 message[2] = '*'; 293 message[2] = '*';
455 /* show message to user */ 294 /* show message to user */
456 writecf (FS_SERV,&message[2]); 295 writecf(FS_SERV, &message[2]);
457 296
458 /* we don't know our nick? */ 297 /* we don't know our nick? */
459 if (!own_nick_get() ) { 298 if (!own_nick_get()) {
460 /* find message after nick */ 299 /* find message after nick */
461 msg = strchr (&message[4], ' '); 300 msg = strchr(&message[4], ' ');
462 if (msg) { 301 if (msg) {
463 /* terminate string before message and copy nick */ 302 /* terminate string before message and copy nick */
464 msg[0] = '\0'; 303 msg[0] = '\0';
465 own_nick_set(&message[4]); 304 own_nick_set(&message[4]);
466 } else { 305 } else {
467 /* no string in servers message (huh?), ask user for nick */ 306 /* no string in servers message (huh?), ask user for nick */
468 nickprompt (); 307 nickprompt();
469 } 308 }
470 } 309 }
471 310
472 /* form login message and send it to server */ 311 /* form login message and send it to server */
473 snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); 312 snprintf(tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(),
474 networkoutput (tmpstr); 313 getstroption(CF_FROM), getintoption(CF_CHANNEL));
314 vc_sendmessage(tmpstr);
475} 315}
476 316
477/* parse and handle anon login request 317/* parse and handle anon login request
478 * format: 121 %s 318 * format: 121 %s
479 * vars: %s - server message */ 319 * vars: %s - server message */
480static void 320static void anonlogin(char *message) {
481anonlogin (char *message)
482{
483 /* mutate message for output */ 321 /* mutate message for output */
484 message[2] = '*'; 322 message[2] = '*';
485 /* show message to user */ 323 /* show message to user */
486 writecf (FS_SERV,&message[2]); 324 writecf(FS_SERV, &message[2]);
487 325
488 /* we don't know our nick? ask for it! */ 326 /* we don't know our nick? ask for it! */
489 if (!own_nick_get()) 327 if (!own_nick_get())
490 nickprompt (); 328 nickprompt();
491 329
492 /* form login message and send it to server */ 330 /* form login message and send it to server */
493 snprintf (tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(), getstroption (CF_FROM), getintoption (CF_CHANNEL)); 331 snprintf(tmpstr, TMPSTRSIZE, ".l %s %s %d", own_nick_get(),
494 networkoutput (tmpstr); 332 getstroption(CF_FROM), getintoption(CF_CHANNEL));
333 vc_sendmessage(tmpstr);
495} 334}
496 335
497/* parse and handle list of nicks (from '.S') 336/* parse and handle list of nicks (from '.S')
498 * format: 119 %s .. 337 * format: 119 %s ..
499 * vars: %s nick - a users nick */ 338 * vars: %s nick - a users nick */
500static void 339static void receivenicks(char *message) {
501receivenicks (char *message) {
502 char *str1 = NULL, *str2 = NULL; 340 char *str1 = NULL, *str2 = NULL;
503 int chanflag = -1; 341 int chanflag = -1;
504 342
505 /* show message to user */ 343 /* show message to user */
506 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_USONLINE), &message[4]); 344 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_USONLINE), &message[4]);
507 writechan (tmpstr); 345 writechan(tmpstr);
508 346
509 /* search for channelnumber */ 347 /* search for channelnumber */
510 if( !(str1 = strchr (message, ' ') ) ) return; 348 if (!(str1 = strchr(message, ' ')))
349 return;
511 str1++; 350 str1++;
512 351
513 if (str1[0] == '*') { 352 if (str1[0] == '*') {
514 ul_rebuild_list(); 353 ul_rebuild_list();
515 str1++; 354 str1++;
516 } else { 355 } else {
517 int mychan; 356 int mychan;
518 str2 = str1; 357 str2 = str1;
519 str1 = strchr(str2,' '); 358 str1 = strchr(str2, ' ');
520 str1[0] = '\0'; 359 str1[0] = '\0';
521 mychan = atoi(str2); 360 mychan = atoi(str2);
522 if( mychan != own_channel_get() ) 361 if (mychan != own_channel_get())
523 return; 362 return;
524 363
525 /* Kick all users from the IN_MY_CHANNEL list */ 364 /* Kick all users from the IN_MY_CHANNEL list */
526 own_channel_set( own_channel_get() ); 365 own_channel_set(own_channel_get());
527 chanflag = 1; 366 chanflag = 1;
528 } 367 }
529 str1++; 368 str1++;
530 369
531 /* while user .. */ 370 /* while user .. */
532 while (str1) { 371 while (str1) {
533 /* search next user */ 372 /* search next user */
534 str2 = strchr (str1, ' '); 373 str2 = strchr(str1, ' ');
535 /* there is another user? terminate this one */ 374 /* there is another user? terminate this one */
536 if (str2) { 375 if (str2) {
537 str2[0] = '\0'; 376 str2[0] = '\0';
@@ -551,52 +390,48 @@ receivenicks (char *message) {
551 * format: 211 %s %s 390 * format: 211 %s %s
552 * vars: %s nick - who logged on 391 * vars: %s nick - who logged on
553 * %s msg - servers message */ 392 * %s msg - servers message */
554static void 393static void usersignon(char *message) {
555usersignon (char *message)
556{
557 char *nick = NULL, *msg = NULL; 394 char *nick = NULL, *msg = NULL;
558 /* search start of nickname */ 395 /* search start of nickname */
559 nick = strchr (message, ' '); 396 nick = strchr(message, ' ');
560 nick++; 397 nick++;
561 398
562 /* search start of message, terminate nick */ 399 /* search start of message, terminate nick */
563 msg = strchr (nick, ' '); 400 msg = strchr(nick, ' ');
564 msg[0] = '\0'; 401 msg[0] = '\0';
565 msg++; 402 msg++;
566 403
567 /* add this user via vchat-user.c */ 404 /* add this user via vchat-user.c */
568 ul_add (nick, 0); 405 ul_add(nick, 0);
569 406
570 /* show message to user */ 407 /* show message to user */
571 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNON), nick, msg); 408 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNON), nick, msg);
572 writechan (tmpstr); 409 writechan(tmpstr);
573} 410}
574 411
575/* parse and handle a logoff message 412/* parse and handle a logoff message
576 * format: 221 %s %s 413 * format: 221 %s %s
577 * vars: %s nick - who logged off 414 * vars: %s nick - who logged off
578 * %s msg - servers message */ 415 * %s msg - servers message */
579static void 416static void usersignoff(char *message) {
580usersignoff (char *message)
581{
582 char *nick = NULL, *msg = NULL; 417 char *nick = NULL, *msg = NULL;
583 /* search start of nickname */ 418 /* search start of nickname */
584 nick = strchr (message, ' '); 419 nick = strchr(message, ' ');
585 nick++; 420 nick++;
586 421
587 /* search start of message, terminate nick */ 422 /* search start of message, terminate nick */
588 msg = strchr (nick, ' '); 423 msg = strchr(nick, ' ');
589 if( msg ) { 424 if (msg) {
590 msg[0] = '\0'; 425 msg[0] = '\0';
591 msg++; 426 msg++;
592 } 427 }
593 428
594 /* delete this user via vchat-user.c */ 429 /* delete this user via vchat-user.c */
595 ul_del (nick); 430 ul_del(nick);
596 431
597 /* show message to user */ 432 /* show message to user */
598 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNOFF), nick, msg); 433 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_SIGNOFF), nick, msg);
599 writechan (tmpstr); 434 writechan(tmpstr);
600} 435}
601 436
602/* parse and handle a join message 437/* parse and handle a join message
@@ -604,40 +439,38 @@ usersignoff (char *message)
604 * vars: %s nick - who joined 439 * vars: %s nick - who joined
605 * %s msg - servers message 440 * %s msg - servers message
606 * %d chan - channel joined */ 441 * %d chan - channel joined */
607static void 442static void userjoin(char *message) {
608userjoin (char *message)
609{
610 char *nick = NULL, *msg = NULL, *channel = NULL; 443 char *nick = NULL, *msg = NULL, *channel = NULL;
611 int chan = 0; 444 int chan = 0;
612 445
613 /* search start of nickname */ 446 /* search start of nickname */
614 nick = strchr (message, ' '); 447 nick = strchr(message, ' ');
615 nick++; 448 nick++;
616 449
617 /* search start of message, terminate nick */ 450 /* search start of message, terminate nick */
618 msg = strchr (nick, ' '); 451 msg = strchr(nick, ' ');
619 msg[0] = '\0'; 452 msg[0] = '\0';
620 msg++; 453 msg++;
621 454
622 /* search start of channel, terminate message */ 455 /* search start of channel, terminate message */
623 channel = strrchr (msg, ' '); 456 channel = strrchr(msg, ' ');
624 channel[0] = '\0'; 457 channel[0] = '\0';
625 channel++; 458 channel++;
626 459
627 /* convert channel to integer */ 460 /* convert channel to integer */
628 chan = atoi (channel); 461 chan = atoi(channel);
629 462
630 /* is it myself joining */ 463 /* is it myself joining */
631 if( own_nick_check(nick) ) 464 if (own_nick_check(nick))
632 own_channel_set(chan); 465 own_channel_set(chan);
633 466
634 /* notice channel join via vchat-user.c */ 467 /* notice channel join via vchat-user.c */
635 if( own_channel_get() == chan ) 468 if (own_channel_get() == chan)
636 ul_enter_chan(nick); 469 ul_enter_chan(nick);
637 470
638 /* show message to user */ 471 /* show message to user */
639 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_JOIN), nick, msg, chan); 472 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_JOIN), nick, msg, chan);
640 writechan (tmpstr); 473 writechan(tmpstr);
641} 474}
642 475
643/* parse and handle a leave message 476/* parse and handle a leave message
@@ -645,35 +478,33 @@ userjoin (char *message)
645 * vars: %s nick - who left 478 * vars: %s nick - who left
646 * %s msg - servers message 479 * %s msg - servers message
647 * %d chan - channel joined */ 480 * %d chan - channel joined */
648static void 481static void userleave(char *message) {
649userleave (char *message)
650{
651 char *nick = NULL, *msg = NULL, *channel = NULL; 482 char *nick = NULL, *msg = NULL, *channel = NULL;
652 int chan = 0; 483 int chan = 0;
653 484
654 /* search start of nickname */ 485 /* search start of nickname */
655 nick = strchr (message, ' '); 486 nick = strchr(message, ' ');
656 nick++; 487 nick++;
657 488
658 /* search start of message, terminate nick */ 489 /* search start of message, terminate nick */
659 msg = strchr (nick, ' '); 490 msg = strchr(nick, ' ');
660 msg[0] = '\0'; 491 msg[0] = '\0';
661 msg++; 492 msg++;
662 493
663 /* convert channel to integer */ 494 /* convert channel to integer */
664 channel = strrchr (msg, ' '); 495 channel = strrchr(msg, ' ');
665 channel[0] = '\0'; 496 channel[0] = '\0';
666 channel++; 497 channel++;
667 498
668 /* convert channel to integer */ 499 /* convert channel to integer */
669 chan = atoi (channel); 500 chan = atoi(channel);
670 501
671 /* notice channel leave via vchat-user.c */ 502 /* notice channel leave via vchat-user.c */
672 ul_leave_chan(nick); 503 ul_leave_chan(nick);
673 504
674 /* show message to user */ 505 /* show message to user */
675 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_LEAVE), nick, msg, chan); 506 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_LEAVE), nick, msg, chan);
676 writechan (tmpstr); 507 writechan(tmpstr);
677} 508}
678 509
679/* parse and handle a nickchange message 510/* parse and handle a nickchange message
@@ -681,242 +512,140 @@ userleave (char *message)
681 * vars: %s oldnick - users old nick 512 * vars: %s oldnick - users old nick
682 * %s newnick - users new nick 513 * %s newnick - users new nick
683 * %s msg - server message */ 514 * %s msg - server message */
684static void 515static void usernickchange(char *message) {
685usernickchange (char *message)
686{
687 char *oldnick = NULL, *newnick = NULL, *msg = NULL; 516 char *oldnick = NULL, *newnick = NULL, *msg = NULL;
688 517
689 /* search start of old nickname */ 518 /* search start of old nickname */
690 oldnick = strchr (message, ' '); 519 oldnick = strchr(message, ' ');
691 oldnick++; 520 oldnick++;
692 521
693 /* search start of new nickname, terminate old nick */ 522 /* search start of new nickname, terminate old nick */
694 newnick = strchr (oldnick, ' '); 523 newnick = strchr(oldnick, ' ');
695 newnick[0] = '\0'; 524 newnick[0] = '\0';
696 newnick++; 525 newnick++;
697 526
698 /* search start of message, terminate new nick */ 527 /* search start of message, terminate new nick */
699 msg = strchr (newnick, ' '); 528 msg = strchr(newnick, ' ');
700 msg[0] = '\0'; 529 msg[0] = '\0';
701 msg++; 530 msg++;
702 531
703 /* notice nickchange via vchat-user.c */ 532 /* notice nickchange via vchat-user.c */
704 ul_rename (oldnick, newnick); 533 ul_rename(oldnick, newnick);
705 534
706 if( own_nick_check(newnick) ) { 535 if (own_nick_check(newnick)) {
707 /* show change in console window */ 536 /* show change in console window */
708 snprintf (consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), newnick, getstroption (CF_SERVERHOST), getstroption (CF_SERVERPORT)); 537 snprintf(consolestr, CONSOLESTRSIZE, getformatstr(FS_CONSOLE), newnick,
709 consoleline (NULL); 538 getstroption(CF_SERVERHOST), getstroption(CF_SERVERPORT));
539 consoleline(NULL);
710 } 540 }
711 541
712 /* show message to user */ 542 /* show message to user */
713 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_NICKCHANGE), oldnick, newnick, msg); 543 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_NICKCHANGE), oldnick, newnick,
714 writechan (tmpstr); 544 msg);
545 writechan(tmpstr);
715} 546}
716 547
717/* handle received message from server */ 548/* handle received message from server */
718static void 549void protocol_parsemsg(char *message) {
719parsemsg (char *message)
720{
721 char *str1, *str2; 550 char *str1, *str2;
722 int i; 551 int i;
723 /* message to short or starts with '<'? must be channel */ 552 /* message to short or starts with '<'? must be channel */
724 if (message[0] == '<') 553 if (message[0] == '<') {
725 {
726 str1 = &message[1]; 554 str1 = &message[1];
727 str2 = strchr(str1,'>'); 555 str2 = strchr(str1, '>');
728 str2[0] = '\0'; 556 str2[0] = '\0';
729 str2++; 557 str2++;
730 if (str2[0] == ' ') str2++; 558 if (str2[0] == ' ')
559 str2++;
731 if (own_nick_check(str1)) 560 if (own_nick_check(str1))
732 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_MYPUBMSG),str1,str2); 561 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_MYPUBMSG), str1, str2);
733 else 562 else
734 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_RXPUBMSG),str1,str2); 563 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_RXPUBMSG), str1, str2);
735 writechan (tmpstr); 564 writechan(tmpstr);
736 565
737 ul_public_action(str1); 566 ul_public_action(str1);
738 } 567 } else if (message[0] == '[') {
739 else if (message[0] == '[')
740 {
741 str1 = &message[1]; 568 str1 = &message[1];
742 str2 = strchr(str1,']'); 569 str2 = strchr(str1, ']');
743 str2[0] = '\0'; 570 str2[0] = '\0';
744 str2++; 571 str2++;
745 if (str2[0] == ' ') str2++; 572 if (str2[0] == ' ')
746 if (own_nick_check( str1 )) 573 str2++;
747 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_MYPUBURL),str1,str2); 574 if (own_nick_check(str1))
575 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_MYPUBURL), str1, str2);
748 else 576 else
749 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_RXPUBURL),str1,str2); 577 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_RXPUBURL), str1, str2);
750 ul_public_action(str1); 578 ul_public_action(str1);
751 writechan (tmpstr); 579 writechan(tmpstr);
752 } 580 }
753 /* message starts with '*'? must be private */ 581 /* message starts with '*'? must be private */
754 else if (message[0] == '*') 582 else if (message[0] == '*') {
755 {
756 str1 = &message[1]; 583 str1 = &message[1];
757 str2 = strchr(str1,'*'); 584 str2 = strchr(str1, '*');
758 str2[0] = '\0'; 585 str2[0] = '\0';
759 str2++; 586 str2++;
760 if (str2[0] == ' ') str2++; 587 if (str2[0] == ' ')
761 snprintf(tmpstr,TMPSTRSIZE,getformatstr(FS_RXPRIVMSG),str1,str2); 588 str2++;
762 writepriv (tmpstr, 1); 589 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_RXPRIVMSG), str1, str2);
590 writepriv(tmpstr, 1);
763 ul_private_action(str1); 591 ul_private_action(str1);
764 } 592 }
765 /* message starts with a number? must be a servermessage */ 593 /* message starts with a number? must be a servermessage */
766 else if ((message[0] >= '0') && (message[0] <= '9')) 594 else if ((message[0] >= '0') && (message[0] <= '9')) {
767 { 595 /* walk server message array */
768 /* walk server message array */ 596 for (i = 0; servermessages[i].id[0]; i++) {
769 for (i = 0; servermessages[i].id[0]; i++) 597 /* is this the message? */
770 { 598 if (!(strncmp(servermessages[i].id, message, 3))) {
771 /* is this the message? */ 599 /* scripting hook available - call it */
772 if (!(strncmp (servermessages[i].id, message, 3))) 600 if (servermessages[i].hook)
773 { 601 servermessages[i].hook(message);
774 /* scripting hook available - call it */ 602 /* function available - call it */
775 if (servermessages[i].hook) 603 else if (servermessages[i].funct)
776 servermessages[i].hook (message); 604 servermessages[i].funct(message);
777 /* function available - call it */ 605 /* no function available, but known - give output */
778 else if (servermessages[i].funct) 606 else {
779 servermessages[i].funct (message); 607 /* remove continutation mark */
780 /* no function available, but known - give output */ 608 if (message[3] == '-')
781 else 609 message[3] = ' ';
782 { 610
783 /* remove continutation mark */ 611 /* mutate message for display */
784 if (message[3] == '-') 612 message[2] = '*';
785 message[3] = ' '; 613 /* giveout message by type */
786 614 switch (servermessages[i].type) {
787 /* mutate message for display */ 615 case SM_IGNORE:
788 message[2] = '*'; 616 break;
789 /* giveout message by type */ 617 case SM_INFO:
790 switch (servermessages[i].type) 618 /* change marker and send as servermessage */
791 { 619 message[2] = '#';
792 case SM_IGNORE: 620 writecf(FS_SERV, &message[2]);
793 break; 621 break;
794 case SM_INFO: 622 case SM_USERINFO:
795 /* change marker and send as servermessage */ 623 /* keep marker and send as servermessage */
796 message[2] = '#'; 624 writecf(FS_SERV, &message[2]);
797 writecf (FS_SERV,&message[2]); 625 break;
798 break; 626 case SM_CHANNEL:
799 case SM_USERINFO: 627 /* keep marker and send as channelmessage */
800 /* keep marker and send as servermessage */ 628 writechan(&message[2]);
801 writecf (FS_SERV,&message[2]); 629 break;
802 break; 630 case SM_ERROR:
803 case SM_CHANNEL: 631 /* change marker and send as errormessage */
804 /* keep marker and send as channelmessage */ 632 message[2] = '!';
805 writechan (&message[2]); 633 writecf(FS_ERR, &message[2]);
806 break; 634 break;
807 case SM_ERROR: 635 default:
808 /* change marker and send as errormessage */ 636 /* fallback: keep marker and send as servermessage */
809 message[2] = '!'; 637 writecf(FS_SERV, &message[2]);
810 writecf (FS_ERR,&message[2]); 638 }
811 break; 639 }
812 default: 640 return;
813 /* fallback: keep marker and send as servermessage */
814 writecf (FS_SERV,&message[2]);
815 }
816 }
817 return;
818 }
819 }
820 /* message not in list, raise errormessage */
821 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_UNKNOWNMSG), message);
822 writecf (FS_ERR,tmpstr);
823 }
824 else
825 {
826 /* message neither public, private or server, raise errormessage */
827 snprintf (tmpstr, TMPSTRSIZE, getformatstr(FS_BOGUSMSG), message);
828 writecf (FS_ERR,tmpstr);
829 }
830}
831
832/* offset in buffer (for linebreaks at packet borders) */
833static int bufoff = 0;
834
835/* get data from servers filedescriptor */
836void
837networkinput (void)
838{
839 int bytes;
840 char *tmp = NULL;
841#define BUFSIZE 4096
842 char buf[BUFSIZE]; /* data buffer */
843 char *ltmp = buf;
844 buf[BUFSIZE-1] = '\0'; /* sanity stop */
845
846 /* receive data at offset */
847 bytes = BIO_read (server_conn, &buf[bufoff], BUFSIZE-1 - bufoff);
848
849 /* no bytes transferred? raise error message, bail out */
850 if (bytes < 0)
851 {
852 snprintf (tmpstr, TMPSTRSIZE, "Receive fails, %s.", strerror(errno));
853 strncpy(errstr,tmpstr,TMPSTRSIZE-2);
854 errstr[TMPSTRSIZE-2] = '\0';
855 strcat(errstr,"\n");
856 writecf (FS_ERR,tmpstr);
857 status = 0;
858 }
859 /* end of file from server? */
860 else if (bytes == 0)
861 {
862 /* inform user, bail out */
863 writecf (FS_SERV,"* EOF from server");
864 strncpy(errstr,"* EOF from server",TMPSTRSIZE-2);
865 errstr[TMPSTRSIZE-2] = '\0';
866 strcat(errstr,"\n");
867 status = 0;
868 }
869 else
870 {
871 /* terminate message */
872 buf[bytes + bufoff] = '\0';
873 /* as long as there are lines .. */
874 while ((tmp = strchr (ltmp, '\n')) != NULL)
875 {
876 /* did the server send CR+LF instead of LF with the last line? */
877 if (tmp[-1] == '\r')
878 tmp[-1] = '\0';
879
880 /* remove newline from previous message, advance pointer of next
881 * message */
882 tmp[0] = '\0';
883 tmp++;
884
885 /* we have a last message? give away to line handler! */
886 if (ltmp[0])
887 {
888#ifdef DEBUG
889 /* debugging? log network input! */
890 fprintf (stderr, "<| %s\n", ltmp);
891#endif
892 parsemsg (ltmp);
893 }
894
895 /* move line along .. */
896 ltmp = tmp;
897 } 641 }
898 /* buffer exhausted, move partial line to start of buffer and go on .. */
899 bufoff = (bytes+bufoff) - (ltmp-buf);
900 if (bufoff > 0)
901 memmove (buf, ltmp, bufoff);
902 else
903 bufoff = 0;
904 } 642 }
905} 643 /* message not in list, raise errormessage */
906 644 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_UNKNOWNMSG), message);
907void 645 writecf(FS_ERR, tmpstr);
908networkoutput (char *msg) 646 } else {
909{ 647 /* message neither public, private or server, raise errormessage */
910#ifdef DEBUG 648 snprintf(tmpstr, TMPSTRSIZE, getformatstr(FS_BOGUSMSG), message);
911 /* debugging? log network output! */ 649 writecf(FS_ERR, tmpstr);
912 fprintf (stderr, ">| %s\n", msg); 650 }
913#endif
914
915 /* send data to server */
916 if (BIO_write (server_conn, msg, strlen (msg)) != strlen (msg))
917 writecf (FS_ERR,"Message sending fuzzy.");
918
919 /* send line termination to server */
920 if (BIO_write (server_conn, "\r\n", 2) != 2)
921 writecf (FS_ERR,"Message sending fuzzy.");
922} 651}