00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef lint
00021 static const char rcsid[] = "$Id: input.c,v 1.40 2006-08-29 02:15:55 sven Exp $";
00022 #endif
00023
00024 #include "server.h"
00025
00026 char *global_input_string = NULL;
00027
00028 int server_parse_input(char *text)
00029 {
00030 irc_msg_t msg;
00031 char *from_nick = NULL, *from_uhost = NULL;
00032 user_t *u = NULL;
00033 char buf[128], *full;
00034 int r;
00035
00036 if (global_input_string) {
00037 free(global_input_string);
00038 global_input_string = NULL;
00039 }
00040 r = bind_check(BT_server_input, NULL, text, text);
00041 if (r & BIND_RET_BREAK) return(0);
00042 if (global_input_string) text = global_input_string;
00043
00044
00045
00046 if (server_config.raw_log) {
00047 putlog(LOG_RAW, "*", "[@] %s", text);
00048 }
00049
00050 irc_msg_parse(text, &msg);
00051
00052 if (msg.prefix) {
00053 from_nick = msg.prefix;
00054 from_uhost = strchr(from_nick, '!');
00055 if (from_uhost) {
00056 u = user_lookup_by_irchost(from_nick);
00057 *from_uhost = 0;
00058 from_uhost++;
00059 }
00060 else {
00061 from_uhost = uhost_cache_lookup(from_nick);
00062 if (from_uhost) {
00063 full = egg_msprintf(buf, sizeof(buf), NULL, "%s!%s", from_nick, from_uhost);
00064 u = user_lookup_by_irchost(full);
00065 if (full != buf) free(full);
00066 }
00067 }
00068 }
00069
00070 bind_check(BT_raw, NULL, msg.cmd, from_nick, from_uhost, u, msg.cmd, msg.nargs, msg.args);
00071 irc_msg_cleanup(&msg);
00072 return(0);
00073 }
00074
00075
00076 static int got001(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00077 {
00078 current_server.registered = 1;
00079
00080
00081 str_redup(¤t_server.nick, args[0]);
00082
00083
00084 str_redup(¤t_server.server_self, from_nick);
00085
00086 eggdrop_event("init-server");
00087
00088
00089 if (!current_server.registered) return BIND_RET_BREAK;
00090
00091
00092 printserv(SERVER_QUICK, "WHOIS %s", current_server.nick);
00093
00094 return(0);
00095 }
00096
00097
00098
00099
00100
00101
00102 static int got005(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00103 {
00104 char *arg, *name, *equalsign, *value;
00105 int i, nsupport;
00106
00107
00108
00109 current_server.got005++;
00110
00111 nsupport = current_server.nsupport;
00112 current_server.support = realloc(current_server.support, sizeof(*current_server.support) * (nsupport+nargs));
00113 current_server.nsupport += nargs-2;
00114
00115 for (i = 1; i < nargs-1; i++) {
00116 arg = args[i];
00117
00118 equalsign = strchr(arg, '=');
00119 if (equalsign) {
00120 int len;
00121
00122 len = equalsign - arg;
00123 name = malloc(len + 1);
00124 memcpy(name, arg, len);
00125 name[len] = 0;
00126 value = strdup(equalsign+1);
00127 }
00128 else {
00129 name = strdup(arg);
00130 value = NULL;
00131 }
00132
00133 current_server.support[nsupport].name = name;
00134 current_server.support[nsupport++].value = value;
00135
00136 if (!value) continue;
00137
00138 if (!strcasecmp(name, "chantypes")) {
00139 str_redup(¤t_server.chantypes, value);
00140 }
00141 else if (!strcasecmp(arg, "casemapping")) {
00142 if (!strcasecmp(value, "ascii")) current_server.strcmp = strcasecmp;
00143 else if (!strcasecmp(value, "rfc1459")) current_server.strcmp = irccmp;
00144 else current_server.strcmp = strcasecmp;
00145 }
00146 else if (!strcasecmp(name, "chanmodes")) {
00147 char types[4][33];
00148 char *comma;
00149 int j;
00150
00151 memset(types, 0, sizeof(types));
00152 for (j = 0; j < 3; j++) {
00153 comma = strchr(value, ',');
00154 if (!comma) break;
00155 memcpy(types[j], value, comma-value);
00156 types[j][comma-value+1] = 0;
00157 value = comma+1;
00158 }
00159 if (comma) strlcpy(types[3], value, sizeof types[3]);
00160 str_redup(¤t_server.type1modes, types[0]);
00161 str_redup(¤t_server.type2modes, types[1]);
00162 str_redup(¤t_server.type3modes, types[2]);
00163 str_redup(¤t_server.type4modes, types[3]);
00164 }
00165 else if (!strcasecmp(name, "prefix")) {
00166 char *paren;
00167
00168 value++;
00169 paren = strchr(value, ')');
00170 if (!paren) continue;
00171 *paren = 0;
00172 str_redup(¤t_server.modeprefix, value);
00173 *paren = ')';
00174 value = paren+1;
00175 str_redup(¤t_server.whoprefix, value);
00176 }
00177 }
00178 return(0);
00179 }
00180
00181 static int got376(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00182 {
00183 char *fake;
00184
00185 if (!current_server.got005 && server_config.fake005 && server_config.fake005[0]) {
00186 fake = strdup(server_config.fake005);
00187 server_parse_input(fake);
00188 free(fake);
00189 }
00190 if (!current_server.chantypes) current_server.chantypes = strdup("#&");
00191 if (!current_server.strcmp) current_server.strcmp = irccmp;
00192 if (!current_server.type1modes) current_server.type1modes = strdup("b");
00193 if (!current_server.type2modes) current_server.type2modes = strdup("k");
00194 if (!current_server.type3modes) current_server.type3modes = strdup("l");
00195 if (!current_server.type4modes) current_server.type4modes = strdup("imnprst");
00196 if (!current_server.modeprefix) current_server.modeprefix = strdup("ov");
00197 if (!current_server.whoprefix) current_server.whoprefix = strdup("@+");
00198 if (strlen(current_server.modeprefix) != strlen(current_server.whoprefix)) {
00199 str_redup(¤t_server.modeprefix, "ov");
00200 str_redup(¤t_server.whoprefix, "@+");
00201 }
00202
00203
00204 channel_on_connect();
00205 return(0);
00206 }
00207
00208 static int check_ctcp_ctcr(int which, int to_channel, user_t *u, char *nick, char *uhost, char *dest, char *trailing)
00209 {
00210 char *cmd, *space, *logdest, *text, *ctcptype;
00211 bind_table_t *table;
00212 int r, len;
00213 int flags;
00214
00215 len = strlen(trailing);
00216 if ((len < 2) || (trailing[0] != 1) || (trailing[len-1] != 1)) {
00217
00218 return(0);
00219 }
00220
00221 cmd = trailing+1;
00222 trailing[len-1] = 0;
00223
00224 space = strchr(trailing, ' ');
00225 if (space) {
00226 *space = 0;
00227 text = space+1;
00228 }
00229 else text = NULL;
00230
00231 if (which == 0) table = BT_ctcp;
00232 else table = BT_ctcr;
00233
00234 r = bind_check(table, u ? &u->settings[0].flags : NULL, cmd, nick, uhost, u, dest, cmd, text);
00235
00236 if (!(r & BIND_RET_BREAK)) {
00237 if (which == 0) ctcptype = "";
00238 else ctcptype = " reply";
00239
00240 if (to_channel) {
00241 flags = LOG_PUBLIC;
00242 logdest = dest;
00243 }
00244 else {
00245 flags = LOG_MSGS;
00246 logdest = "*";
00247 }
00248 if (!strcasecmp(cmd, "ACTION")) putlog(flags, logdest, _("Action: %s %s"), nick, text);
00249 else putlog(flags, logdest, "CTCP%s %s%s%s from %s (to %s)", ctcptype, cmd, text ? ": " : "", text ? text : "", nick, dest);
00250 }
00251
00252 trailing[len-1] = 1;
00253 if (space) *space = ' ';
00254
00255 return(1);
00256 }
00257
00258 static int check_global_notice(char *from_nick, char *from_uhost, char *dest, char *trailing)
00259 {
00260 if (*dest == '$') {
00261 putlog(LOG_MSGS|LOG_SERV, "*", "[%s!%s to %s] %s", from_nick, from_uhost, dest, trailing);
00262 return(1);
00263 }
00264 return(0);
00265 }
00266
00267
00268
00269
00270 static int gotmsg(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00271 {
00272 char *dest, *destname, *trailing, *first, *space, *text;
00273 int to_channel;
00274 int r;
00275
00276 dest = args[0];
00277 trailing = args[1];
00278
00279
00280 r = check_global_notice(from_nick, from_uhost, dest, trailing);
00281 if (r) return(0);
00282
00283
00284 if (current_server.whoprefix && strchr(current_server.whoprefix, *dest)) destname = dest+1;
00285 else destname = dest;
00286
00287 if (current_server.chantypes && strchr(current_server.chantypes, *destname)) to_channel = 1;
00288 else to_channel = 0;
00289
00290
00291 r = check_ctcp_ctcr(0, to_channel, u, from_nick, from_uhost, dest, trailing);
00292 if (r) return(0);
00293
00294
00295
00296
00297 first = trailing;
00298 space = strchr(trailing, ' ');
00299 if (space) {
00300 *space = 0;
00301 text = space+1;
00302 }
00303 else text = "";
00304
00305 if (to_channel) {
00306 r = bind_check(BT_pub, u ? &u->settings[0].flags : NULL, first, from_nick, from_uhost, u, dest, text);
00307 if (r & BIND_RET_LOG) {
00308 putlog(LOG_CMDS, dest, "<<%s>> !%s! %s %s", from_nick, u ? u->handle : "*", first, text);
00309 }
00310 }
00311 else {
00312 r = bind_check(BT_msg, u ? &u->settings[0].flags : NULL, first, from_nick, from_uhost, u, text);
00313 if (r & BIND_RET_LOG) {
00314 putlog(LOG_CMDS, "*", "(%s!%s) !%s! %s %s", from_nick, from_uhost, u ? u->handle : "*", first, text);
00315 }
00316 }
00317
00318 if (space) *space = ' ';
00319
00320 if (r & BIND_RET_BREAK) return(0);
00321
00322
00323 if (to_channel) {
00324 r = bind_check(BT_pubm, u ? &u->settings[0].flags : NULL, trailing, from_nick, from_uhost, u, dest, trailing);
00325 }
00326 else {
00327 r = bind_check(BT_msgm, u ? &u->settings[0].flags : NULL, trailing, from_nick, from_uhost, u, trailing);
00328 }
00329
00330 if (!(r & BIND_RET_BREAK)) {
00331
00332 if (to_channel) {
00333 putlog(LOG_PUBLIC, dest, "<%s> %s", from_nick, trailing);
00334 }
00335 else {
00336 putlog(LOG_MSGS, "*", "[%s (%s)] %s", from_nick, from_uhost, trailing);
00337 }
00338 }
00339 return(0);
00340 }
00341
00342
00343
00344
00345 static int gotnotice(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00346 {
00347 char *dest, *destname, *trailing;
00348 int r, to_channel;
00349
00350 dest = args[0];
00351 trailing = args[1];
00352
00353
00354 if (!from_uhost) {
00355 putlog(LOG_SERV, "*", "-NOTICE- %s", trailing);
00356 return(0);
00357 }
00358
00359
00360 r = check_global_notice(from_nick, from_uhost, dest, trailing);
00361 if (r) return(0);
00362
00363
00364 if (current_server.whoprefix && strchr(current_server.whoprefix, *dest)) destname = dest+1;
00365 else destname = dest;
00366
00367 if (current_server.chantypes && strchr(current_server.chantypes, *destname)) to_channel = 1;
00368 else to_channel = 0;
00369
00370
00371 r = check_ctcp_ctcr(1, to_channel, u, from_nick, from_uhost, dest, trailing);
00372 if (r) return(0);
00373
00374 r = bind_check(BT_notice, u ? &u->settings[0].flags : NULL, trailing, from_nick, from_uhost, u, dest, trailing);
00375
00376 if (!(r & BIND_RET_BREAK)) {
00377
00378 if (to_channel) {
00379 putlog(LOG_PUBLIC, dest, "-%s:%s- %s", from_nick, dest, trailing);
00380 }
00381 else {
00382 putlog(LOG_MSGS, "*", "-%s (%s)- %s", from_nick, from_uhost, trailing);
00383 }
00384 }
00385 return(0);
00386 }
00387
00388
00389
00390
00391 static int gotwall(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00392 {
00393 char *msg;
00394 int r;
00395
00396 msg = args[1];
00397 r = bind_check(BT_wall, NULL, msg, from_nick, msg);
00398 if (!(r & BIND_RET_BREAK)) {
00399 if (from_uhost) putlog(LOG_WALL, "*", "!%s (%s)! %s", from_nick, from_uhost, msg);
00400 else putlog(LOG_WALL, "*", "!%s! %s", from_nick, msg);
00401 }
00402 return 0;
00403 }
00404
00405
00406
00407
00408
00409 static int got432(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00410 {
00411 char *badnick;
00412
00413 badnick = args[1];
00414 if (current_server.registered) {
00415 putlog(LOG_MISC, "*", _("NICK IS INVALID: %s (keeping '%s')."), badnick, current_server.nick);
00416 }
00417 else {
00418 putlog(LOG_MISC, "*", _("Server says my nickname ('%s') is invalid, trying new random nick."), badnick);
00419 try_random_nick();
00420 }
00421 return(0);
00422 }
00423
00424
00425
00426
00427 static int got433(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00428 {
00429 char *badnick;
00430
00431 badnick = args[1];
00432 if (current_server.registered) {
00433
00434 putlog(LOG_MISC, "*", _("Nick is in use: '%s' (keeping '%s')."), badnick, current_server.nick);
00435 }
00436 else {
00437 putlog(LOG_MISC, "*", _("Nick is in use: '%s' (trying next one)."), badnick, current_server.nick);
00438 try_next_nick();
00439 }
00440 return(0);
00441 }
00442
00443
00444 static int got435(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00445 {
00446 char *banned_nick, *chan;
00447
00448 banned_nick = args[1];
00449 chan = args[2];
00450 putlog(LOG_MISC, "*", _("Cannot change to banned nickname (%s on %s)."), banned_nick, chan);
00451 return(0);
00452 }
00453
00454
00455 static int got437(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00456 {
00457 char *chan;
00458
00459 chan = args[1];
00460 putlog(LOG_MISC, "*", _("Can't change nickname to %s. Is my nickname banned?"), chan);
00461
00462
00463
00464 if (!current_server.registered) {
00465 try_next_nick();
00466 }
00467 return(0);
00468 }
00469
00470
00471 static int got438(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00472 {
00473 putlog(LOG_MISC, "*", "%s", _("Nick change was too fast."));
00474 return(0);
00475 }
00476
00477 static int got451(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00478 {
00479
00480
00481
00482
00483 putlog(LOG_MISC, "*", _("%s says I'm not registered, trying next one."), from_nick);
00484 kill_server(_("The server says I'm not registered, trying next one."));
00485 return 0;
00486 }
00487
00488
00489 static int goterror(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00490 {
00491 if (current_server.registered) {
00492 char *uhost, *full;
00493
00494 if (current_server.user && current_server.host) {
00495 uhost = egg_mprintf("%s@%s", current_server.user, current_server.host);
00496 full = egg_mprintf("%s!%s", current_server.nick, uhost);
00497 u = user_lookup_by_irchost_nocache(full);
00498 free(full);
00499 }
00500 else uhost = NULL;
00501 channel_on_quit(current_server.nick, uhost, u);
00502 if (uhost) free(uhost);
00503 }
00504
00505 putlog(LOG_MSGS | LOG_SERV, "*", "-ERROR from server- %s", args[0]);
00506 putlog(LOG_SERV, "*", _("Disconnecting from server."));
00507 kill_server(_("disconnecting due to error"));
00508 return(0);
00509 }
00510
00511
00512
00513 static int gotping(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00514 {
00515 printserv(SERVER_NOQUEUE, "PONG :%s", args[0]);
00516 return(0);
00517 }
00518
00519
00520 static int gotpong(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00521 {
00522 egg_timeval_t now;
00523
00524 if (nargs > 0 && current_server.ping_id == atoi(args[nargs-1])) {
00525 timer_get_time(&now);
00526 timer_diff(¤t_server.last_ping_sent, &now, ¤t_server.last_ping_time);
00527 if (current_server.time_to_ping == 0) current_server.time_to_ping = random() % 60 + 30;
00528 current_server.npings++;
00529 }
00530
00531 return(0);
00532 }
00533
00534
00535 static int got311(char *from_nick, char *from_uhost, user_t *u, char *cmd, int nargs, char *args[])
00536 {
00537 char *nick, *user, *host, *realname;
00538
00539 if (nargs < 6) return(0);
00540
00541 nick = args[1];
00542 user = args[2];
00543 host = args[3];
00544 realname = args[5];
00545
00546 if (match_my_nick(nick)) {
00547 str_redup(¤t_server.user, user);
00548 str_redup(¤t_server.host, host);
00549 str_redup(¤t_server.real_name, realname);
00550
00551
00552 if (server_config.ip_lookup == 1) dcc_dns_set(host);
00553
00554 putlog(LOG_SERV, "*", _("Connected to %s as %s!%s@%s."),
00555 current_server.server_host, current_server.nick, current_server.user,
00556 current_server.host);
00557 }
00558
00559 return(0);
00560 }
00561
00562 bind_list_t server_raw_binds[] = {
00563 {NULL, "PRIVMSG", gotmsg},
00564 {NULL, "NOTICE", gotnotice},
00565 {NULL, "WALLOPS", gotwall},
00566 {NULL, "PING", gotping},
00567 {NULL, "PONG", gotpong},
00568 {NULL, "ERROR", goterror},
00569 {NULL, "001", got001},
00570 {NULL, "005", got005},
00571 {NULL, "376", got376},
00572 {NULL, "422", got376},
00573 {NULL, "432", got432},
00574 {NULL, "433", got433},
00575 {NULL, "435", got435},
00576 {NULL, "438", got438},
00577 {NULL, "437", got437},
00578 {NULL, "451", got451},
00579 {NULL, "311", got311},
00580 {NULL, NULL, NULL}
00581 };