/************************************************************************** * Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer, * * Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe. * * * * Merc Diku Mud improvements copyright (C) 1992, 1993 by Michael * * Chastain, Michael Quan, and Mitchell Tse. * * * * In order to use any part of this Merc Diku Mud, you must comply with * * both the original Diku license in 'license.doc' as well the Merc * * license in 'license.txt'. In particular, you may not remove either of * * these copyright notices. * * * * Much time and thought has gone into this software and you are * * benefiting. We hope that you share your changes too. What goes * * around, comes around. * *************************************************************************** * ROM 2.4 is copyright 1993-1998 Russ Taylor * * ROM has been brought to you by the ROM consortium * * Russ Taylor (rtaylor@hypercube.org) * * Gabrielle Taylor (gtaylor@hypercube.org) * * Brian Moore (zump@rom.org) * * By using this code, you have agreed to follow the terms of the * * ROM license, in the file Rom24/doc/rom.license * *************************************************************************** * Copyright (c) 2000 Fatal Dimensions * * * * See the file "LICENSE" or information on usage and redistribution * * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * *************************************************************************** * Ported to Smaug 1.4a by Samson of Alsherok. Consolidated for * * cross-codebase compatibility by Samson of Alsherok. Modifications and * * enhancements to the code Copyright (c) 2001-2003 Roger Libiez * * ( Samson ) Registered with the United States Copyright Office * * TX 5-562-404. I condensed the 14 or so Fatal Dimensions source code * * files into this one file, because I for one find it far easier to * * maintain when all of the functions are right here in one file. * *************************************************************************** * 1stMud ROM Derivative (c) 2001-2004 by Markanth * * http://www.firstmud.com/ <markanth@firstmud.com> * * By using this code you have agreed to follow the term of * * the 1stMud license in ../doc/1stMud/LICENSE * ***************************************************************************/ #include "merc.h" #include "tables.h" #include "data_table.h" #include "olc.h" #include "recycle.h" #include "vnums.h" #ifndef DISABLE_I3 char I3_input_buffer[IPS]; char I3_output_buffer[OPS]; char I3_currentpacket[IPS]; bool packetdebug = false; long I3_input_pointer = 0; long I3_output_pointer = 4; const char *I3_THISMUD; const char *I3_ROUTER_NAME; const char *manual_router; SOCKET I3_control = INVALID_SOCKET; int i3wait; int i3timeout; time_t ucache_clock; long bytes_received; long bytes_sent; I3_MUD i3mud_info; Proto (I3_HEADER * I3_get_header, (char **pps)); Proto (void I3_send_channel_listen, (I3_CHANNEL *, bool)); Proto (bool i3check_permissions, (CharData *, int, int, bool)); Proto (const char *i3_funcname, (Do_F *)); Proto (Do_F * i3_function, (const char *)); char * rankbuffer (CharData * ch) { static char rbuf[MSL]; if (ch->pcdata->i3chardata->i3perm >= I3PERM_IMM) { strlcpy (rbuf, "{YStaff", MSL); if (!NullStr (CH_I3RANK (ch))) snprintf (rbuf, sizeof (rbuf), "{Y%s", CH_I3RANK (ch)); } else { strlcpy (rbuf, "{BPlayer", MSL); if (!NullStr (CH_I3RANK (ch))) snprintf (rbuf, sizeof (rbuf), "{B%s", CH_I3RANK (ch)); } return rbuf; } FlagTable i3perm_names[] = { {"Notset", I3PERM_NOTSET, true} , {"None", I3PERM_NONE, true} , {"Mort", I3PERM_MORT, true} , {"Imm", I3PERM_IMM, true} , {"Admin", I3PERM_ADMIN, true} , {"Imp", I3PERM_IMP, true} , {NULL, 0, false} }; int get_permvalue (const char *flag) { unsigned int x; for (x = 0; i3perm_names[x].name != NULL; x++) if (!str_cmp (flag, i3perm_names[x].name)) return x; return -1; } char * i3strrep (const char *src, const char *sch, const char *rep) { int lensrc = strlen (src), lensch = strlen (sch), lenrep = strlen (rep), x, y, in_p; static char newsrc[MSL]; bool searching = false; newsrc[0] = '\0'; for (x = 0, in_p = 0; x < lensrc; x++, in_p++) { if (src[x] == sch[0]) { searching = true; for (y = 0; y < lensch; y++) if (src[x + y] != sch[y]) searching = false; if (searching) { for (y = 0; y < lenrep; y++, in_p++) { if (in_p == (MSL - 1)) { newsrc[in_p] = '\0'; return newsrc; } if (src[x - 1] == sch[0]) { if (rep[0] == '\033') { if (y < lensch) { if (y == 0) newsrc[in_p - 1] = sch[y]; else newsrc[in_p] = sch[y]; } else y = lenrep; } else { if (y == 0) newsrc[in_p - 1] = rep[y]; newsrc[in_p] = rep[y]; } } else newsrc[in_p] = rep[y]; } x += lensch - 1; in_p--; searching = false; continue; } } if (in_p == (MSL - 1)) { newsrc[in_p] = '\0'; return newsrc; } newsrc[in_p] = src[x]; } newsrc[in_p] = '\0'; return newsrc; } char * i3_strip_colors (const char *txt) { I3_COLOR *color; static char tbuf[MSL]; strlcpy (tbuf, txt, MSL); for (color = i3color_first; color; color = color->next) strlcpy (tbuf, i3strrep (tbuf, color->i3fish, ""), MSL); for (color = i3color_first; color; color = color->next) strlcpy (tbuf, i3strrep (tbuf, color->i3tag, ""), MSL); for (color = i3color_first; color; color = color->next) strlcpy (tbuf, i3strrep (tbuf, color->mudtag, ""), MSL); return tbuf; } char * I3_mudtofish (const char *txt) { I3_COLOR *color; static char tbuf[MSL]; if (!txt || *txt == '\0') return ""; strlcpy (tbuf, txt, MSL); for (color = i3color_first; color; color = color->next) strlcpy (tbuf, i3strrep (tbuf, color->mudtag, color->i3fish), MSL); return tbuf; } char * I3_codetofish (const char *txt) { I3_COLOR *color; static char tbuf[MSL]; if (!txt || *txt == '\0') return ""; strlcpy (tbuf, txt, MSL); for (color = i3color_first; color; color = color->next) strlcpy (tbuf, i3strrep (tbuf, color->i3tag, color->i3fish), MSL); return tbuf; } char * I3_codetomud (CharData * ch, const char *txt) { I3_COLOR *color; static char tbuf[MSL]; if (!txt || *txt == '\0') return ""; if (!ch || IsSet (ch->pcdata->i3chardata->i3flags, I3_COLORFLAG)) { strlcpy (tbuf, txt, MSL); for (color = i3color_first; color; color = color->next) strlcpy (tbuf, i3strrep (tbuf, color->i3tag, color->mudtag), MSL); } else strlcpy (tbuf, i3_strip_colors (txt), MSL); return tbuf; } char * I3_fishtomud (CharData * ch, const char *txt) { I3_COLOR *color; static char tbuf[MSL]; if (NullStr (txt)) return ""; if (!ch || IsSet (ch->pcdata->i3chardata->i3flags, I3_COLORFLAG)) { strlcpy (tbuf, txt, MSL); for (color = i3color_first; color; color = color->next) strlcpy (tbuf, i3strrep (tbuf, color->i3fish, color->mudtag), MSL); } else strlcpy (tbuf, i3_strip_colors (txt), MSL); return tbuf; } int i3print (CharData * ch, const char *txt) { char buf[MPL * 3]; if (!ch || NullStr (txt) || !ch->desc) { return 0; } snprintf (buf, sizeof (buf), "%s{x", I3_fishtomud (ch, txt)); return d_print (ch->desc, buf); } int i3printf (CharData * ch, const char *fmt, ...) { va_list args; char buf[MPL * 3]; if (!ch || NullStr (fmt) || !ch->desc) return 0; va_start (args, fmt); vsnprintf (buf, sizeof (buf), fmt, args); va_end (args); return i3print (ch, buf); } int i3println (CharData * ch, const char *txt) { if (!ch || !ch->desc) return 0; return i3print (ch, txt) + d_print (ch->desc, NEWLINE); } int i3printlnf (CharData * ch, const char *fmt, ...) { va_list args; char buf[MPL * 3]; if (!ch || !ch->desc) return 0; va_start (args, fmt); vsnprintf (buf, sizeof (buf), fmt, args); va_end (args); return i3println (ch, buf); } int i3bprint (Buffer * b, const char *txt) { char buf[MPL * 3]; if (!b || NullStr (txt)) return 0; snprintf (buf, sizeof (buf), I3_fishtomud (NULL, txt)); return bprint (b, buf); } int i3bprintf (Buffer * b, const char *fmt, ...) { va_list args; char buf[MPL * 3]; if (!b || NullStr (fmt)) return 0; va_start (args, fmt); vsnprintf (buf, sizeof (buf), fmt, args); va_end (args); return i3bprint (b, buf); } int i3bprintln (Buffer * b, const char *txt) { if (!b) return 0; return i3bprint (b, txt) + bprint (b, NEWLINE); } int i3bprintlnf (Buffer * b, const char *fmt, ...) { va_list args; char buf[MPL * 3]; if (!b) return 0; va_start (args, fmt); vsnprintf (buf, sizeof (buf), fmt, args); va_end (args); return i3bprintln (b, buf); } bool verify_i3layout (const char *fmt, int number) { const char *c; int i = 0; c = fmt; while ((c = strchr (c, '%')) != NULL) { if (*(c + 1) == '%') { c += 2; continue; } if (*(c + 1) != 's') return false; c++; i++; } if (i != number) return false; return true; } bool I3_is_connected (void) { return (I3_control != INVALID_SOCKET); } char * I3_escape (const char *ps) { static char xnew[MSL]; char *pnew = xnew; while (ps[0]) { if (ps[0] == '"') { pnew[0] = '\\'; pnew++; } if (ps[0] == '\\') { pnew[0] = '\\'; pnew++; } pnew[0] = ps[0]; pnew++; ps++; } pnew[0] = '\0'; return xnew; } void I3_remove_quotes (char **ps) { char *ps1, *ps2; if (*ps[0] == '"') (*ps)++; if ((*ps)[strlen (*ps) - 1] == '"') (*ps)[strlen (*ps) - 1] = 0; ps1 = ps2 = *ps; while (ps2[0]) { if (ps2[0] == '\\') { ps2++; } ps1[0] = ps2[0]; ps1++; ps2++; } ps1[0] = '\0'; } I3_CHANNEL * find_I3_channel_by_localname (const char *name) { I3_CHANNEL *channel = NULL; for (channel = I3chan_first; channel; channel = channel->next) { if (!channel->local_name) continue; if (!str_cmp (channel->local_name, name)) return channel; } return NULL; } I3_CHANNEL * find_I3_channel_by_name (const char *name) { I3_CHANNEL *channel = NULL; for (channel = I3chan_first; channel; channel = channel->next) { if (!str_cmp (channel->I3_name, name)) return channel; } return NULL; } I3_CHANNEL * new_I3_channel (void) { I3_CHANNEL *cnew; alloc_mem (cnew, I3_CHANNEL, 1); return cnew; } void destroy_I3_channel (I3_CHANNEL * channel) { int x; if (channel == NULL) { bug ("destroy_I3_channel: Null parameter"); return; } free_string (channel->local_name); free_string (channel->host_mud); free_string (channel->I3_name); free_string (channel->layout_m); free_string (channel->layout_e); for (x = 0; x < MAX_I3HISTORY; x++) { if (channel->history[x] && channel->history[x] != '\0') free_string (channel->history[x]); } UnLink (channel, I3chan, next, prev); free_mem (channel); } I3_MUD * find_I3_mud_by_name (const char *name) { I3_MUD *mud; for (mud = i3mud_first; mud; mud = mud->next) { if (!str_cmp (mud->name, name)) return mud; } return NULL; } I3_MUD * new_I3_mud (const char *name) { I3_MUD *cnew, *mud_prev; alloc_mem (cnew, I3_MUD, 1); cnew->name = str_dup (name); for (mud_prev = i3mud_first; mud_prev; mud_prev = mud_prev->next) if (str_cmp (mud_prev->name, name) >= 0) break; if (!mud_prev) Link (cnew, i3mud, next, prev); else Insert (cnew, mud_prev, i3mud, next, prev); return cnew; } void destroy_I3_mud (I3_MUD * mud) { if (mud == NULL) { bug ("destroy_I3_mud: Null parameter"); return; } free_string (mud->name); free_string (mud->ipaddress); free_string (mud->mudlib); free_string (mud->base_mudlib); free_string (mud->driver); free_string (mud->mud_type); free_string (mud->open_status); free_string (mud->admin_email); free_string (mud->telnet); free_string (mud->web_wrong); free_string (mud->banner); free_string (mud->web); free_string (mud->time); free_string (mud->daemon); if (mud != &i3mud_info) { UnLink (mud, i3mud, next, prev); free_mem (mud); } } void I3_connection_close (bool reconnect) { ROUTER_DATA *router = NULL; bool rfound = false; for (router = router_first; router; router = router->next) if (!str_cmp (router->name, I3_ROUTER_NAME)) { rfound = true; break; } if (!rfound) { socket_error ("Disconnecting from router."); closesocket (I3_control); I3_control = INVALID_SOCKET; return; } new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Closing connection to Intermud-3 router %s", router->name); closesocket (I3_control); I3_control = INVALID_SOCKET; if (reconnect) { if (router->reconattempts <= 3) { i3wait = 100; wiznet ("Will attempt to reconnect in approximately 15 seconds.", NULL, NULL, WIZ_I3, true, 1); } else if (router->next != NULL) { new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Unable to reach %s. Abandoning connection.", router->name); logf ("Bytes sent: %ld. Bytes received: %ld.", bytes_sent, bytes_received); bytes_sent = 0; bytes_received = 0; i3wait = 100; new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Will attempt new connection to %s in approximately 15 seconds.", router->next->name); } else { bytes_sent = 0; bytes_received = 0; i3wait = -2; wiznet ("Unable to reconnect. No routers responding.", NULL, NULL, WIZ_I3, true, 1); ; return; } } logf ("Bytes sent: %ld. Bytes received: %ld.", bytes_sent, bytes_received); bytes_sent = 0; bytes_received = 0; return; } void I3_write_buffer (const char *msg) { long newsize = I3_output_pointer + strlen (msg); if (newsize > OPS - 1) { bugf ("I3_write_buffer: buffer too large (would become %ld)", newsize); return; } strlcpy (I3_output_buffer + I3_output_pointer, msg, newsize); I3_output_pointer = newsize; } void send_to_i3 (const char *text) { char buf[MSL * 3]; snprintf (buf, sizeof (buf), "%s", I3_codetofish (text)); I3_write_buffer (buf); } void I3_write_header (const char *identifier, const char *originator_mudname, const char *originator_username, const char *target_mudname, const char *target_username) { I3_write_buffer ("({\""); I3_write_buffer (identifier); I3_write_buffer ("\",5,"); if (originator_mudname) { I3_write_buffer ("\""); I3_write_buffer (originator_mudname); I3_write_buffer ("\","); } else I3_write_buffer ("0,"); if (originator_username) { I3_write_buffer ("\""); I3_write_buffer (originator_username); I3_write_buffer ("\","); } else I3_write_buffer ("0,"); if (target_mudname) { I3_write_buffer ("\""); I3_write_buffer (target_mudname); I3_write_buffer ("\","); } else I3_write_buffer ("0,"); if (target_username) { I3_write_buffer ("\""); I3_write_buffer (target_username); I3_write_buffer ("\","); } else I3_write_buffer ("0,"); } char * I3_get_field (char *packet, char **ps) { int count[256]; char has_apostrophe = 0, has_backslash = 0; char foundit = 0; memset (count, 0, sizeof (count)); *ps = packet; while (1) { switch (*ps[0]) { case '{': if (!has_apostrophe) count[(int) '{']++; break; case '}': if (!has_apostrophe) count[(int) '}']++; break; case '[': if (!has_apostrophe) count[(int) '[']++; break; case ']': if (!has_apostrophe) count[(int) ']']++; break; case '(': if (!has_apostrophe) count[(int) '(']++; break; case ')': if (!has_apostrophe) count[(int) ')']++; break; case '\\': if (has_backslash) has_backslash = 0; else has_backslash = 1; break; case '"': if (has_backslash) { has_backslash = 0; } else { if (has_apostrophe) has_apostrophe = 0; else has_apostrophe = 1; } break; case ',': case ':': if (has_apostrophe) break; if (has_backslash) break; if (count[(int) '{'] != count[(int) '}']) break; if (count[(int) '['] != count[(int) ']']) break; if (count[(int) '('] != count[(int) ')']) break; foundit = 1; break; } if (foundit) break; (*ps)++; } *ps[0] = '\0'; (*ps)++; return *ps; } CharData * I3_find_user (const char *name) { Descriptor *d; for (d = descriptor_first; d; d = d->next) { if (d->character && !str_cmp (GetName (d->character), name)) return d->character; } return NULL; } bool i3ignoring (CharData * ch, const char *ignore) { I3_IGNORE *temp; I3_MUD *mud; char *ps; char ipbuf[512], mudname[MIL]; for (temp = ch->pcdata->i3chardata->i3ignore_first; temp; temp = temp->next) { if (!fnmatch (temp->name, ignore, 0)) return true; } ps = strchr (ignore, '@'); if (NullStr (ignore) || ps == NULL) return false; ps[0] = '\0'; strlcpy (mudname, ps + 1, MIL); for (mud = i3mud_first; mud; mud = mud->next) { if (!str_cmp (mud->name, mudname)) { snprintf (ipbuf, sizeof (ipbuf), "%s:%d", mud->ipaddress, mud->player_port); for (temp = ch->pcdata->i3chardata->i3ignore_first; temp; temp = temp->next) { if (!str_cmp (temp->name, ipbuf)) return true; } } } return false; } bool I3_write_packet (char *msg) { int oldsize, size, check, x; char *s = I3_output_buffer; oldsize = size = strlen (msg + 4); s[3] = size % 256; size >>= 8; s[2] = size % 256; size >>= 8; s[1] = size % 256; size >>= 8; s[0] = size % 256; for (x = 0; x < oldsize + 4; x++) { if (msg[x] == '\r' && x > 3) msg[x] = '\0'; } check = send (I3_control, msg, oldsize + 4, 0); if (!check || (check < 0 && !check_errno (EWOULDBLOCK) #ifndef WIN32 && !check_errno (EAGAIN) #endif )) { if (check < 0) socket_error ("Write error on socket."); else socket_error ("EOF encountered on socket write."); I3_connection_close (true); return false; } if (check < 0) return true; bytes_sent += check; if (packetdebug) { logf ("Size: %d. Bytes Sent: %d.", oldsize, check); logf ("Packet Sent: %s", msg + 4); } I3_output_pointer = 4; return true; } void I3_send_packet (void) { I3_write_packet (I3_output_buffer); return; } void I3_startup_packet (void) { char s[MIL]; char *strtime; if (!I3_is_connected ()) return; I3_output_pointer = 4; I3_output_buffer[0] = '\0'; new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Sending startup_packet to %s", I3_ROUTER_NAME); I3_write_header ("startup-req-3", I3_THISMUD, NULL, I3_ROUTER_NAME, NULL); snprintf (s, sizeof (s), "%d", i3mud_info.password); I3_write_buffer (s); I3_write_buffer (","); snprintf (s, sizeof (s), "%d", i3mud_info.mudlist_id); I3_write_buffer (s); I3_write_buffer (","); snprintf (s, sizeof (s), "%d", i3mud_info.chanlist_id); I3_write_buffer (s); I3_write_buffer (","); snprintf (s, sizeof (s), "%d", i3mud_info.player_port); I3_write_buffer (s); I3_write_buffer (",0,0,\""); I3_write_buffer (i3mud_info.mudlib); I3_write_buffer ("\",\""); I3_write_buffer (i3mud_info.base_mudlib); I3_write_buffer ("\",\""); I3_write_buffer (i3mud_info.driver); I3_write_buffer ("\",\""); I3_write_buffer (i3mud_info.mud_type); I3_write_buffer ("\",\""); I3_write_buffer (i3mud_info.open_status); I3_write_buffer ("\",\""); I3_write_buffer (i3mud_info.admin_email); I3_write_buffer ("\","); I3_write_buffer ("(["); if (i3mud_info.emoteto) I3_write_buffer ("\"emoteto\":1,"); if (i3mud_info.news) I3_write_buffer ("\"news\":1,"); if (i3mud_info.ucache) I3_write_buffer ("\"ucache\":1,"); if (i3mud_info.auth) I3_write_buffer ("\"auth\":1,"); if (i3mud_info.locate) I3_write_buffer ("\"locate\":1,"); if (i3mud_info.finger) I3_write_buffer ("\"finger\":1,"); if (i3mud_info.channel) I3_write_buffer ("\"channel\":1,"); if (i3mud_info.who) I3_write_buffer ("\"who\":1,"); if (i3mud_info.tell) I3_write_buffer ("\"tell\":1,"); if (i3mud_info.beep) I3_write_buffer ("\"beep\":1,"); if (i3mud_info.mail) I3_write_buffer ("\"mail\":1,"); if (i3mud_info.file) I3_write_buffer ("\"file\":1,"); if (i3mud_info.http) { snprintf (s, sizeof (s), "\"http\":%d,", i3mud_info.http); I3_write_buffer (s); } if (i3mud_info.smtp) { snprintf (s, sizeof (s), "\"smtp\":%d,", i3mud_info.smtp); I3_write_buffer (s); } if (i3mud_info.pop3) { snprintf (s, sizeof (s), "\"pop3\":%d,", i3mud_info.pop3); I3_write_buffer (s); } if (i3mud_info.ftp) { snprintf (s, sizeof (s), "\"ftp\":%d,", i3mud_info.ftp); I3_write_buffer (s); } if (i3mud_info.nntp) { snprintf (s, sizeof (s), "\"nntp\":%d,", i3mud_info.nntp); I3_write_buffer (s); } if (i3mud_info.rcp) { snprintf (s, sizeof (s), "\"rcp\":%d,", i3mud_info.rcp); I3_write_buffer (s); } if (i3mud_info.amrcp) { snprintf (s, sizeof (s), "\"amrcp\":%d,", i3mud_info.amrcp); I3_write_buffer (s); } I3_write_buffer ("]),(["); if (!NullStr (i3mud_info.web)) { #ifndef DISABLE_WEBSRV if (web_is_connected ()) snprintf (s, sizeof (s), "\"url\":\"%s:%d\",", i3mud_info.web, webport); else #endif snprintf (s, sizeof (s), "\"url\":\"%s\",", i3mud_info.web); I3_write_buffer (s); } strtime = ctime (¤t_time); strtime[strlen (strtime) - 1] = '\0'; snprintf (s, sizeof (s), "\"time\":\"%s\",", strtime); I3_write_buffer (s); I3_write_buffer ("]),})\r"); I3_send_packet (); } DataTable ucache_data_table[] = { DTE (STRING, ucache, name, NULL, NULL, str, NULL), DTE (INT, ucache, gender, NULL, NULL, int, NULL), DTE (TIME, ucache, time, NULL, NULL, time, NULL), DTE_END }; DataTable I3ban_data_table[] = { DTE (STRING, I3ban, name, NULL, NULL, str, NULL), DTE_END }; DataTable I3chan_data_table[] = { DTE (STRING, I3chan, local_name, NULL, NULL, str, NULL), DTE (STRING, I3chan, host_mud, NULL, NULL, str, NULL), DTE (STRING, I3chan, I3_name, NULL, NULL, str, NULL), DTE (STRING, I3chan, layout_m, NULL, NULL, str, NULL), DTE (STRING, I3chan, layout_e, NULL, NULL, str, NULL), DTE (INT, I3chan, status, NULL, NULL, int, NULL), DTE (INT, I3chan, i3perm, NULL, NULL, int, NULL), DTE_SHOW (STRING_ARRAY, I3chan, history, MAX_I3HISTORY, NULL, NULL), DTE (FLAGVECTOR, I3chan, flags, NULL, NULL, flag, NULL), DTE_END }; DataTable i3mud_data_table[] = { DTE (INT, i3mud, status, NULL, NULL, int, NULL), DTE (STRING, i3mud, name, NULL, NULL, str, NULL), DTE (STRING, i3mud, ipaddress, NULL, NULL, str, NULL), DTE (STRING, i3mud, mudlib, NULL, NULL, str, NULL), DTE (STRING, i3mud, base_mudlib, NULL, NULL, str, NULL), DTE (STRING, i3mud, driver, NULL, NULL, str, NULL), DTE (STRING, i3mud, mud_type, NULL, NULL, str, NULL), DTE (STRING, i3mud, open_status, NULL, NULL, str, NULL), DTE (STRING, i3mud, admin_email, NULL, NULL, str, NULL), DTE (STRING, i3mud, telnet, NULL, NULL, str, NULL), DTE (STRING, i3mud, web_wrong, NULL, NULL, str, NULL), DTE (INT, i3mud, player_port, NULL, NULL, int, NULL), DTE (INT, i3mud, imud_tcp_port, NULL, NULL, int, NULL), DTE (INT, i3mud, imud_udp_port, NULL, NULL, int, NULL), DTE (BOOL, i3mud, tell, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, beep, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, emoteto, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, who, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, finger, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, locate, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, channel, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, news, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, mail, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, file, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, auth, NULL, NULL, bool, NULL), DTE (BOOL, i3mud, ucache, NULL, NULL, bool, NULL), DTE (INT, i3mud, smtp, NULL, NULL, int, NULL), DTE (INT, i3mud, ftp, NULL, NULL, int, NULL), DTE (INT, i3mud, nntp, NULL, NULL, int, NULL), DTE (INT, i3mud, http, NULL, NULL, int, NULL), DTE (INT, i3mud, pop3, NULL, NULL, int, NULL), DTE (INT, i3mud, rcp, NULL, NULL, int, NULL), DTE (INT, i3mud, amrcp, NULL, NULL, int, NULL), DTE (STRING, i3mud, banner, NULL, NULL, str, NULL), DTE (STRING, i3mud, web, NULL, NULL, str, NULL), DTE (STRING, i3mud, time, NULL, NULL, str, NULL), DTE (STRING, i3mud, daemon, NULL, NULL, str, NULL), DTE (INT, i3mud, jeamland, NULL, NULL, int, NULL), DTE (BOOL, i3mud, autoconnect, NULL, NULL, bool, NULL), DTE (INT, i3mud, password, NULL, NULL, int, NULL), DTE (INT, i3mud, mudlist_id, NULL, NULL, int, NULL), DTE (INT, i3mud, chanlist_id, NULL, NULL, int, NULL), DTE (INT, i3mud, minlevel, NULL, NULL, int, NULL), DTE (INT, i3mud, immlevel, NULL, NULL, int, NULL), DTE (INT, i3mud, adminlevel, NULL, NULL, int, NULL), DTE (INT, i3mud, implevel, NULL, NULL, int, NULL), DTE_END }; DataTable router_data_table[] = { DTE (STRING, router, name, NULL, NULL, str, NULL), DTE (STRING, router, ip, NULL, NULL, str, NULL), DTE (INT, router, port, NULL, NULL, int, NULL), DTE_END }; DataTable i3color_data_table[] = { DTE (STRING, i3color, name, NULL, NULL, str, NULL), DTE (STRING, i3color, mudtag, NULL, NULL, str, NULL), DTE (STRING, i3color, i3tag, NULL, NULL, str, NULL), DTE (STRING, i3color, i3fish, NULL, NULL, str, NULL), DTE_END }; TableRW_Fun (i3_fun_rw) { Do_F **fun = (Do_F **) temp; switch (type) { case act_write: *arg = i3_funcname (*fun); return true; case act_read: *fun = (Do_F *) i3_function (*arg); return true; default: return false; } } DataTable i3cmd_data_table[] = { DTE (STRING, i3cmd, name, NULL, NULL, str, NULL), DTE (STRING, i3cmd, args, NULL, NULL, str, NULL), DTE (STRING, i3cmd, descr, NULL, NULL, str, NULL), DTE_SHOW (FUNCTION_INT_TO_STR, i3cmd, function, i3_fun_rw, NULL, NULL), DTE (INT_FLAGSTRING, i3cmd, level, i3perm_names, NULL, flag, NULL), DTE (BOOL, i3cmd, connected, NULL, NULL, bool, NULL), DTE_SHOW (NAMELIST, i3cmd, alias_first, &i3cmd_zero.alias_last, NULL, NULL), DTE_END }; DataTable i3help_data_table[] = { DTE (STRING, i3help, name, NULL, NULL, str, NULL), DTE (STRING, i3help, text, 1, NULL, str, NULL), DTE (INT_FLAGSTRING, i3help, level, i3perm_names, NULL, flag, NULL), }; void I3_process_startup_reply (I3_HEADER * header, char *s) { ROUTER_DATA *router; I3_CHANNEL *channel; char *ps = s, *next_ps; I3_get_field (ps, &next_ps); log_string (ps); ps = next_ps; I3_get_field (ps, &next_ps); i3mud_info.password = atoi (ps); new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Received startup_reply from %s", header->originator_mudname); for (router = router_first; router; router = router->next) { if (!str_cmp (router->name, header->originator_mudname)) { router->reconattempts = 0; I3_ROUTER_NAME = router->name; break; } } i3wait = 0; i3timeout = 0; wiznet ("Intermud-3 Network connection complete.", NULL, NULL, WIZ_I3, true, 1); for (channel = I3chan_first; channel; channel = channel->next) { if (!NullStr (channel->local_name)) { new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Subscribing to %s", channel->local_name); I3_send_channel_listen (channel, true); } } return; } void I3_process_chanack (I3_HEADER * header, char *s) { CharData *ch; char *next_ps, *ps = s; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); if (!(ch = I3_find_user (header->target_username))) log_string (ps); else i3printlnf (ch, "{G%s", ps); return; } void I3_send_error (const char *mud, const char *user, const char *code, const char *message) { if (!I3_is_connected ()) return; I3_write_header ("error", I3_THISMUD, 0, mud, user); I3_write_buffer ("\""); I3_write_buffer (code); I3_write_buffer ("\",\""); I3_write_buffer (I3_escape (message)); I3_write_buffer ("\",0,})\r"); I3_send_packet (); } void I3_process_error (I3_HEADER * header, char *s) { CharData *ch; char *next_ps, *ps = s; char type[MIL], error[MSL]; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (type, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); if (!str_cmp (header->originator_mudname, "VargonMUD")) return; snprintf (error, sizeof (error), "Error: from %s to %s@%s\n\r%s: %s", header->originator_mudname, header->target_username, header->target_mudname, type, ps); if (!(ch = I3_find_user (header->target_username))) log_string (error); else i3println (ch, error); } sex_t i3todikugender (sex_t gender) { sex_t sex = SEX_NONE; switch (gender) { case SEX_NEUTRAL: sex = SEX_MALE; break; case SEX_MALE: sex = SEX_FEMALE; break; default: sex = SEX_NEUTRAL; break; } return sex; } sex_t dikutoi3gender (sex_t gender) { sex_t sex = SEX_NONE; switch (gender) { default: sex = SEX_FEMALE; break; case SEX_MALE: sex = SEX_NEUTRAL; break; case SEX_FEMALE: sex = SEX_MALE; break; } return sex; } Do_Fun (I3_show_ucache_contents) { I3_UCACHE *user; Buffer *buf; int users = 0; buf = new_buf (); i3bprintln (buf, "Cached user information"); i3bprintln (buf, "1 = Female, 2 = Neuter, User | Gender ( 0 = Male)"); i3bprintln (buf, draw_line (ch, NULL, 0)); for (user = ucache_first; user; user = user->next) { i3bprintlnf (buf, "%-30s %d", user->name, user->gender); users++; } i3bprintlnf (buf, "%d users being cached.", users); sendpage (ch, buf_string (buf)); free_buf (buf); return; } sex_t I3_get_ucache_gender (char *name) { I3_UCACHE *user; for (user = ucache_first; user; user = user->next) { if (!str_cmp (user->name, name)) return user->gender; } return SEX_NONE; } I3_UCACHE * new_ucache (void) { I3_UCACHE *Data; alloc_mem (Data, I3_UCACHE, 1); return Data; } TableSave_Fun (rw_i3_ucache) { rw_list (type, I3_UCACHE_FILE, I3_UCACHE, ucache); } void I3_prune_ucache (void) { I3_UCACHE *ucache, *next_ucache; for (ucache = ucache_first; ucache; ucache = next_ucache) { next_ucache = ucache->next; if (current_time - ucache->time >= (DAY * 30)) { free_string (ucache->name); UnLink (ucache, ucache, next, prev); free_mem (ucache); } } rw_i3_ucache (act_write); return; } void I3_ucache_update (char *name, sex_t gender) { I3_UCACHE *user; for (user = ucache_first; user; user = user->next) { if (!str_cmp (user->name, name)) { user->gender = gender; user->time = current_time; return; } } alloc_mem (user, I3_UCACHE, 1); user->name = str_dup (name); user->gender = gender; user->time = current_time; Link (user, ucache, next, prev); rw_i3_ucache (act_write); return; } void I3_send_ucache_update (const char *visname, sex_t gender) { char buf[10]; if (!I3_is_connected ()) return; I3_write_header ("ucache-update", I3_THISMUD, NULL, NULL, NULL); I3_write_buffer ("\""); I3_write_buffer (visname); I3_write_buffer ("\",\""); I3_write_buffer (visname); I3_write_buffer ("\","); snprintf (buf, sizeof (buf), "%d", gender); I3_write_buffer (buf); I3_write_buffer (",})\r"); I3_send_packet (); return; } void I3_process_ucache_update (I3_HEADER * header, char *s) { char *ps = s, *next_ps; char username[MIL], visname[MIL], buf[MSL]; sex_t sex, gender; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (username, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (visname, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); gender = (sex_t) atoi (ps); snprintf (buf, sizeof (buf), "%s@%s", visname, header->originator_mudname); sex = I3_get_ucache_gender (buf); if (sex == gender) return; I3_ucache_update (buf, gender); return; } void I3_send_chan_user_req (const char *targetmud, const char *targetuser) { if (!I3_is_connected ()) return; I3_write_header ("chan-user-req", I3_THISMUD, NULL, targetmud, NULL); I3_write_buffer ("\""); I3_write_buffer (targetuser); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_process_chan_user_req (I3_HEADER * header, char *s) { char buf[MSL]; char *ps = s, *next_ps; CharData *ch; sex_t sex, gender; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (buf, sizeof (buf), "%s@%s", header->originator_username, header->originator_mudname); if (!(ch = I3_find_user (ps))) { if (!exists_player (ps)) I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); else I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } if (ch->pcdata->i3chardata->i3perm < I3PERM_MORT) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); return; } if (I3ISINVIS (ch) || i3ignoring (ch, buf)) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } gender = ch->sex; sex = dikutoi3gender (gender); I3_write_header ("chan-user-reply", I3_THISMUD, NULL, header->originator_mudname, NULL); I3_write_buffer ("\""); I3_write_buffer (GetName (ch)); I3_write_buffer ("\",\""); I3_write_buffer (GetName (ch)); I3_write_buffer ("\","); snprintf (buf, sizeof (buf), "%d", sex); I3_write_buffer (buf); I3_write_buffer (",})\r"); I3_send_packet (); return; } void I3_process_chan_user_reply (I3_HEADER * header, char *s) { char *ps = s, *next_ps; char username[MIL], visname[MIL], buf[MSL]; sex_t sex, gender; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (username, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (visname, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); gender = (sex_t) atoi (ps); snprintf (buf, sizeof (buf), "%s@%s", visname, header->originator_mudname); sex = I3_get_ucache_gender (buf); if (sex == gender) return; I3_ucache_update (buf, gender); return; } void I3_process_mudlist (I3_HEADER * header, char *s) { char *ps = s, *next_ps; I3_MUD *mud = NULL; char mud_name[MIL]; I3_get_field (ps, &next_ps); i3mud_info.mudlist_id = atoi (ps); ps = next_ps; ps += 2; while (1) { char *next_ps2; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (mud_name, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps2); if (ps[0] != '0') { mud = find_I3_mud_by_name (mud_name); if (!mud) mud = new_I3_mud (mud_name); ps += 2; I3_get_field (ps, &next_ps); mud->status = atoi (ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); replace_str (&mud->ipaddress, ps); ps = next_ps; I3_get_field (ps, &next_ps); mud->player_port = atoi (ps); ps = next_ps; I3_get_field (ps, &next_ps); mud->imud_tcp_port = atoi (ps); ps = next_ps; I3_get_field (ps, &next_ps); mud->imud_udp_port = atoi (ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); replace_str (&mud->mudlib, ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); replace_str (&mud->base_mudlib, ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); replace_str (&mud->driver, ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); replace_str (&mud->mud_type, ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); replace_str (&mud->open_status, ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); replace_str (&mud->admin_email, ps); ps = next_ps; I3_get_field (ps, &next_ps); ps += 2; while (1) { char *next_ps3; char key[MIL]; if (ps[0] == ']') break; I3_get_field (ps, &next_ps3); I3_remove_quotes (&ps); strlcpy (key, ps, MIL); ps = next_ps3; I3_get_field (ps, &next_ps3); switch (key[0]) { case 'a': if (!str_cmp (key, "auth")) { mud->auth = ps[0] == '0' ? 0 : 1; break; } if (!str_cmp (key, "amrcp")) { mud->amrcp = atoi (ps); break; } break; case 'b': if (!str_cmp (key, "beep")) { mud->beep = ps[0] == '0' ? 0 : 1; break; } break; case 'c': if (!str_cmp (key, "channel")) { mud->channel = ps[0] == '0' ? 0 : 1; break; } break; case 'e': if (!str_cmp (key, "emoteto")) { mud->emoteto = ps[0] == '0' ? 0 : 1; break; } break; case 'f': if (!str_cmp (key, "file")) { mud->file = ps[0] == '0' ? 0 : 1; break; } if (!str_cmp (key, "finger")) { mud->finger = ps[0] == '0' ? 0 : 1; break; } if (!str_cmp (key, "ftp")) { mud->ftp = atoi (ps); break; } break; case 'h': if (!str_cmp (key, "http")) { mud->http = atoi (ps); break; } break; case 'l': if (!str_cmp (key, "locate")) { mud->locate = ps[0] == '0' ? 0 : 1; break; } break; case 'm': if (!str_cmp (key, "mail")) { mud->mail = ps[0] == '0' ? 0 : 1; break; } break; case 'n': if (!str_cmp (key, "news")) { mud->news = ps[0] == '0' ? 0 : 1; break; } if (!str_cmp (key, "nntp")) { mud->nntp = atoi (ps); break; } break; case 'p': if (!str_cmp (key, "pop3")) { mud->pop3 = atoi (ps); break; } break; case 'r': if (!str_cmp (key, "rcp")) { mud->rcp = atoi (ps); break; } break; case 's': if (!str_cmp (key, "smtp")) { mud->smtp = atoi (ps); break; } break; case 't': if (!str_cmp (key, "tell")) { mud->tell = ps[0] == '0' ? 0 : 1; break; } break; case 'u': if (!str_cmp (key, "ucache")) { mud->ucache = ps[0] == '0' ? 0 : 1; break; } if (!str_cmp (key, "url")) { I3_remove_quotes (&ps); replace_str (&mud->web_wrong, ps); break; } break; case 'w': if (!str_cmp (key, "who")) { mud->who = ps[0] == '0' ? 0 : 1; break; } break; default: break; } ps = next_ps3; if (ps[0] == ']') break; } ps = next_ps; I3_get_field (ps, &next_ps); ps = next_ps; } else { if ((mud = find_I3_mud_by_name (mud_name)) != NULL) destroy_I3_mud (mud); } ps = next_ps2; if (ps[0] == ']') break; } return; } I3_CHANNEL * new_I3chan (void) { I3_CHANNEL *Data; alloc_mem (Data, I3_CHANNEL, 1); set_array (Data->history, &str_empty[0], MAX_I3HISTORY); return Data; } void init_i3_channels (void) { I3_CHANNEL *channel; for (channel = I3chan_first; channel; channel = channel->next) { if (channel->i3perm > I3PERM_IMP) { if (channel->i3perm < i3mud_info.minlevel) channel->i3perm = I3PERM_NONE; else if (channel->i3perm >= i3mud_info.minlevel && channel->i3perm < i3mud_info.immlevel) channel->i3perm = I3PERM_MORT; else if (channel->i3perm >= i3mud_info.immlevel && channel->i3perm < i3mud_info.adminlevel) channel->i3perm = I3PERM_IMM; else if (channel->i3perm >= i3mud_info.adminlevel && channel->i3perm < i3mud_info.implevel) channel->i3perm = I3PERM_ADMIN; else if (channel->i3perm >= i3mud_info.implevel) channel->i3perm = I3PERM_IMP; } } } TableSave_Fun (rw_i3_channels) { rw_list (type, I3_CHANNEL_FILE, I3_CHANNEL, I3chan); if (type == act_read) { init_i3_channels (); } } void I3_process_chanlist_reply (I3_HEADER * header, char *s) { char *ps = s, *next_ps; I3_CHANNEL *channel; char chan[MIL]; I3_get_field (ps, &next_ps); i3mud_info.chanlist_id = atoi (ps); ps = next_ps; ps += 2; while (1) { char *next_ps2; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (chan, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps2); if (ps[0] != '0') { if (!(channel = find_I3_channel_by_name (chan))) { channel = new_I3_channel (); channel->I3_name = str_dup (chan); } ps += 2; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); replace_str (&channel->host_mud, ps); ps = next_ps; I3_get_field (ps, &next_ps); channel->status = atoi (ps); } else { if ((channel = find_I3_channel_by_name (chan)) != NULL) { if (!NullStr (channel->local_name)) new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Locally configured channel %s has been purged from router %s", channel->local_name, I3_ROUTER_NAME); destroy_I3_channel (channel); rw_i3_channels (act_write); } } ps = next_ps2; if (ps[0] == ']') break; } return; } void I3_send_channel_message (I3_CHANNEL * channel, const char *name, const char *message) { if (!I3_is_connected ()) return; I3_write_header ("channel-m", I3_THISMUD, name, NULL, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",\""); I3_write_buffer (name); I3_write_buffer ("\",\""); send_to_i3 (I3_escape (message)); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_send_channel_emote (I3_CHANNEL * channel, const char *name, const char *message) { char buf[MSL]; if (!I3_is_connected ()) return; if (strstr (message, "$N") == NULL) snprintf (buf, sizeof (buf), "$N %s", message); else strlcpy (buf, message, MSL); I3_write_header ("channel-e", I3_THISMUD, name, NULL, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",\""); I3_write_buffer (name); I3_write_buffer ("\",\""); send_to_i3 (I3_escape (buf)); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_send_channel_t (I3_CHANNEL * channel, const char *name, const char *tmud, const char *tuser, const char *msg_o, const char *msg_t, const char *tvis) { if (!I3_is_connected ()) return; I3_write_header ("channel-t", I3_THISMUD, name, NULL, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",\""); I3_write_buffer (tmud); I3_write_buffer ("\",\""); I3_write_buffer (tuser); I3_write_buffer ("\",\""); send_to_i3 (I3_escape (msg_o)); I3_write_buffer ("\",\""); send_to_i3 (I3_escape (msg_t)); I3_write_buffer ("\",\""); I3_write_buffer (name); I3_write_buffer ("\",\""); I3_write_buffer (tvis); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } int I3_token (char type, char *string, char *oname, char *tname) { char code[50]; char *p = '\0'; switch (type) { default: code[0] = type; code[1] = '\0'; return 1; case '$': strlcpy (code, "$", 50); break; case ' ': strlcpy (code, " ", 50); break; case 'N': strlcpy (code, oname, 50); break; case 'O': strlcpy (code, tname, 50); break; } p = code; while (*p != '\0') { *string = *p++; *++string = '\0'; } return (strlen (code)); } void I3_message_convert (char *buffer, const char *txt, char *oname, char *tname) { const char *point; int skip = 0; for (point = txt; *point; point++) { if (*point == '$') { point++; if (*point == '\0') point--; else skip = I3_token (*point, buffer, oname, tname); while (skip-- > 0) ++buffer; continue; } *buffer = *point; *++buffer = '\0'; } *buffer = '\0'; return; } char * I3_convert_channel_message (const char *message, char *sname, char *tname) { static char msgbuf[MSL]; if (!message) { bug ("I3_convert_channel_message: NULL message!"); return "ERROR"; } if (!sname) { bug ("I3_convert_channel_message: NULL sname!"); return "ERROR"; } if (!tname) { bug ("I3_convert_channel_message: NULL tname!"); return "ERROR"; } I3_message_convert (msgbuf, message, sname, tname); return msgbuf; } void update_chanhistory (I3_CHANNEL * channel, const char *message) { char msg[MSL], buf[MSL]; struct tm *local; time_t t; int x; if (!channel) { bug ("update_chanhistory: NULL channel received!"); return; } if (NullStr (message)) { bug ("update_chanhistory: NULL message received!"); return; } strlcpy (msg, message, MSL); for (x = 0; x < MAX_I3HISTORY; x++) { if (channel->history[x] == NULL) { t = time (NULL); local = localtime (&t); snprintf (buf, sizeof (buf), "{R[%-2.2d/%-2.2d %-2.2d:%-2.2d] {G%s" NEWLINE, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, msg); channel->history[x] = str_dup (buf); if (IsSet (channel->flags, I3CHAN_LOG)) { FileData *fp; snprintf (buf, sizeof (buf), I3DIR "%s.log", channel->local_name); if (!(fp = f_open (buf, "a"))) { log_error (buf); bugf ("Could not open file %s!", buf); } else { f_printf (fp, "%s\n", i3_strip_colors (channel->history[x])); f_close (fp); } } break; } if (x == MAX_I3HISTORY - 1) { int y; for (y = 1; y < MAX_I3HISTORY; y++) { int z = y - 1; if (channel->history[z] != NULL) { replace_str (&channel->history[z], channel->history[y]); } } t = time (NULL); local = localtime (&t); snprintf (buf, sizeof (buf), "{R[%-2.2d/%-2.2d %-2.2d:%-2.2d] {G%s" NEWLINE, local->tm_mon + 1, local->tm_mday, local->tm_hour, local->tm_min, msg); replace_str (&channel->history[x], buf); if (IsSet (channel->flags, I3CHAN_LOG)) { FileData *fp; snprintf (buf, sizeof (buf), I3DIR "%s.log", channel->local_name); if (!(fp = f_open (buf, "a"))) { log_error (buf); bugf ("Could not open file %s!", buf); } else { f_printf (fp, "%s\n", i3_strip_colors (channel->history[x])); f_close (fp); } } } } return; } void I3_chan_filter_m (I3_CHANNEL * channel, I3_HEADER * header, char *s) { char *ps = s, *next_ps; char visname[MIL], newmsg[MSL]; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (visname, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (newmsg, ps, MSL); snprintf (newmsg, sizeof (newmsg), "%s%s", ps, " (filtered M)"); I3_write_header ("chan-filter-reply", I3_THISMUD, NULL, I3_ROUTER_NAME, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",({\"channel-m\",5,\""); I3_write_buffer (header->originator_mudname); I3_write_buffer ("\",\""); I3_write_buffer (header->originator_username); I3_write_buffer ("\",0,0,\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",\""); I3_write_buffer (visname); I3_write_buffer ("\",\""); I3_write_buffer (newmsg); I3_write_buffer ("\",}),})\r"); I3_send_packet (); return; } void I3_chan_filter_e (I3_CHANNEL * channel, I3_HEADER * header, char *s) { char *ps = s, *next_ps; char visname[MIL], newmsg[MSL]; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (visname, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (newmsg, sizeof (newmsg), "%s%s", ps, " (filtered E)"); I3_write_header ("chan-filter-reply", I3_THISMUD, NULL, I3_ROUTER_NAME, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",({\"channel-e\",5,\""); I3_write_buffer (header->originator_mudname); I3_write_buffer ("\",\""); I3_write_buffer (header->originator_username); I3_write_buffer ("\",0,0,\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",\""); I3_write_buffer (visname); I3_write_buffer ("\",\""); I3_write_buffer (newmsg); I3_write_buffer ("\",}),})\r"); I3_send_packet (); return; } void I3_chan_filter_t (I3_CHANNEL * channel, I3_HEADER * header, char *s) { char *ps = s, *next_ps; char targetmud[MIL], targetuser[MIL], message_o[MSL], message_t[MSL]; char visname_o[MIL]; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (targetmud, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (targetuser, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (message_o, sizeof (message_o), "%s%s", ps, " (filtered T)"); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (message_t, sizeof (message_t), "%s%s", ps, " (filtered T)"); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (visname_o, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); I3_write_header ("chan-filter-reply", I3_THISMUD, NULL, I3_ROUTER_NAME, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",({\"channel-t\",5,\""); I3_write_buffer (header->originator_mudname); I3_write_buffer ("\",\""); I3_write_buffer (header->originator_username); I3_write_buffer ("\",0,0,\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",\""); I3_write_buffer (targetmud); I3_write_buffer ("\",\""); I3_write_buffer (targetuser); I3_write_buffer ("\",\""); send_to_i3 (I3_escape (message_o)); I3_write_buffer ("\",\""); send_to_i3 (I3_escape (message_t)); I3_write_buffer ("\",\""); I3_write_buffer (visname_o); I3_write_buffer ("\",\""); I3_write_buffer (ps); I3_write_buffer ("\",}),})\r"); I3_send_packet (); return; } void I3_process_channel_filter (I3_HEADER * header, char *s) { char *ps = s, *next_ps; char ptype[MIL]; I3_CHANNEL *channel = NULL; I3_HEADER *second_header; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); if (!(channel = find_I3_channel_by_name (ps))) { logf ("I3_process_channel_filter: received unknown channel (%s)", ps); return; } if (!channel->local_name) return; ps = next_ps; ps += 2; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (ptype, ps, MIL); second_header = I3_get_header (&ps); I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); if (!str_cmp (ptype, "channel-m")) I3_chan_filter_m (channel, second_header, next_ps); if (!str_cmp (ptype, "channel-e")) I3_chan_filter_e (channel, second_header, next_ps); if (!str_cmp (ptype, "channel-t")) I3_chan_filter_t (channel, second_header, next_ps); free_mem (second_header); return; } void I3_process_channel_t (I3_HEADER * header, char *s) { char *ps = s, *next_ps; Descriptor *d; CharData *vch = NULL; char targetmud[MIL], targetuser[MIL], message_o[MSL], message_t[MSL], buf[MSL]; char visname_o[MIL], sname[MIL], tname[MIL], lname[MIL], tmsg[MSL], omsg[MSL]; I3_CHANNEL *channel = NULL; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); if (!(channel = find_I3_channel_by_name (ps))) { logf ("I3_process_channel_t: received unknown channel (%s)", ps); return; } if (!channel->local_name) return; ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (targetmud, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (targetuser, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (message_o, ps, MSL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (message_t, ps, MSL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (visname_o, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (sname, sizeof (sname), "%s@%s", visname_o, header->originator_mudname); snprintf (tname, sizeof (tname), "%s@%s", ps, targetmud); snprintf (omsg, sizeof (omsg), "%s", I3_convert_channel_message (message_o, sname, tname)); snprintf (tmsg, sizeof (tmsg), "%s", I3_convert_channel_message (message_t, sname, tname)); for (d = descriptor_first; d; d = d->next) { if (!d->character) continue; vch = CH (d); if (!hasname (vch->pcdata->i3chardata->i3_listen, channel->local_name) || hasname (vch->pcdata->i3chardata->i3_denied, channel->local_name)) continue; snprintf (lname, sizeof (lname), "%s@%s", GetName (vch), I3_THISMUD); if (d->connected == CON_PLAYING && !i3ignoring (vch, sname)) { if (!str_cmp (lname, tname)) { snprintf (buf, sizeof (buf), channel->layout_e, channel->local_name, tmsg); i3println (vch, buf); } else { snprintf (buf, sizeof (buf), channel->layout_e, channel->local_name, omsg); i3println (vch, buf); } } } update_chanhistory (channel, omsg); return; } void I3_process_channel_m (I3_HEADER * header, char *s) { char *ps = s, *next_ps; Descriptor *d; CharData *vch = NULL; char visname[MIL], buf[MSL]; I3_CHANNEL *channel; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); if (!(channel = find_I3_channel_by_name (ps))) { logf ("channel_m: received unknown channel (%s)", ps); return; } if (!channel->local_name) return; ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (visname, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (buf, sizeof (buf), channel->layout_m, channel->local_name, visname, header->originator_mudname, ps); for (d = descriptor_first; d; d = d->next) { if (!d->character) continue; vch = CH (d); if (!hasname (vch->pcdata->i3chardata->i3_listen, channel->local_name) || hasname (vch->pcdata->i3chardata->i3_denied, channel->local_name)) continue; if (d->connected == CON_PLAYING && !i3ignoring (vch, visname)) i3println (vch, buf); } update_chanhistory (channel, buf); return; } void I3_process_channel_e (I3_HEADER * header, char *s) { char *ps = s, *next_ps; Descriptor *d; CharData *vch = NULL; char visname[MIL], msg[MSL], buf[MSL]; I3_CHANNEL *channel; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); if (!(channel = find_I3_channel_by_name (ps))) { logf ("channel_e: received unknown channel (%s)", ps); return; } if (!channel->local_name) return; ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (visname, sizeof (visname), "%s@%s", ps, header->originator_mudname); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (msg, sizeof (msg), "%s", I3_convert_channel_message (ps, visname, visname)); snprintf (buf, sizeof (buf), channel->layout_e, channel->local_name, msg); for (d = descriptor_first; d; d = d->next) { if (!d->character) continue; vch = CH (d); if (!hasname (vch->pcdata->i3chardata->i3_listen, channel->local_name) || hasname (vch->pcdata->i3chardata->i3_denied, channel->local_name)) continue; if (d->connected == CON_PLAYING && !i3ignoring (vch, visname)) i3println (vch, buf); } update_chanhistory (channel, buf); return; } void I3_process_chan_who_req (I3_HEADER * header, char *s) { Descriptor *d; char *ps = s, *next_ps; char buf[MSL], ibuf[MIL]; I3_CHANNEL *channel; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (ibuf, sizeof (ibuf), "%s@%s", header->originator_username, header->originator_mudname); if (!(channel = find_I3_channel_by_name (ps))) { snprintf (buf, sizeof (buf), "The channel you specified (%s) is unknown at %s", ps, I3_THISMUD); I3_send_error (header->originator_mudname, header->originator_username, "unk-channel", buf); logf ("chan_who_req: received unknown channel (%s)", ps); return; } if (!channel->local_name) { snprintf (buf, sizeof (buf), "The channel you specified (%s) is not registered at %s", ps, I3_THISMUD); I3_send_error (header->originator_mudname, header->originator_username, "unk-channel", buf); return; } I3_write_header ("chan-who-reply", I3_THISMUD, NULL, header->originator_mudname, header->originator_username); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",({"); for (d = descriptor_first; d; d = d->next) { if (!d->character) continue; if (I3ISINVIS (d->character)) continue; if (hasname (d->character->pcdata->i3chardata->i3_listen, channel->local_name) && !i3ignoring (d->character, ibuf) && !hasname (d->character->pcdata->i3chardata->i3_denied, channel->local_name)) { I3_write_buffer ("\""); I3_write_buffer (GetName (d->character)); I3_write_buffer ("\","); } } I3_write_buffer ("}),})\r"); I3_send_packet (); return; } void I3_process_chan_who_reply (I3_HEADER * header, char *s) { char *ps = s, *next_ps; CharData *ch; if (!(ch = I3_find_user (header->target_username))) { bugf ("I3_process_chan_who_reply(): user %s not found.", header->target_username); return; } I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); i3printlnf (ch, "{WUsers listening to %s on %s:" NEWLINE, ps, header->originator_mudname); ps = next_ps; I3_get_field (ps, &next_ps); ps += 2; while (1) { if (ps[0] == '}') { i3println (ch, "{cNo information returned or no people listening."); return; } I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); i3printlnf (ch, "{c%s", ps); ps = next_ps; if (ps[0] == '}') break; } return; } void I3_send_chan_who (CharData * ch, I3_CHANNEL * channel, I3_MUD * mud) { if (!I3_is_connected ()) return; I3_write_header ("chan-who-req", I3_THISMUD, GetName (ch), mud->name, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_send_beep (CharData * ch, const char *to, I3_MUD * mud) { if (!I3_is_connected ()) return; I3_escape (to); I3_write_header ("beep", I3_THISMUD, GetName (ch), mud->name, to); I3_write_buffer ("\""); I3_write_buffer (GetName (ch)); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_process_beep (I3_HEADER * header, char *s) { char buf[MIL]; char *ps = s, *next_ps; CharData *ch; snprintf (buf, sizeof (buf), "%s@%s", header->originator_username, header->originator_mudname); if (!(ch = I3_find_user (header->target_username))) { if (!exists_player (header->target_username)) I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); else I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } if (ch->pcdata->i3chardata->i3perm < I3PERM_MORT) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); return; } if (I3ISINVIS (ch) || i3ignoring (ch, buf)) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } if (IsSet (ch->pcdata->i3chardata->i3flags, I3_BEEP)) { snprintf (buf, sizeof (buf), "%s is not accepting beeps.", GetName (ch)); I3_send_error (header->originator_mudname, header->originator_username, "unk-user", buf); return; } I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); i3printlnf (ch, "{Y\a%s@%s beeps you.", ps, header->originator_mudname); return; } Do_Fun (I3_beep) { char *ps; char mud[MIL]; I3_MUD *pmud; if (IsSet (ch->pcdata->i3chardata->i3flags, I3_DENYBEEP)) { i3println (ch, "You are not allowed to use i3beeps."); return; } if (NullStr (argument)) { cmd_syntax (ch, NULL, "user@mud", "on/off", NULL); return; } if (!str_cmp (argument, "on")) { RemBit (ch->pcdata->i3chardata->i3flags, I3_BEEP); i3println (ch, "You now send and receive i3beeps."); return; } if (!str_cmp (argument, "off")) { SetBit (ch->pcdata->i3chardata->i3flags, I3_BEEP); i3println (ch, "You no longer send and receive i3beeps."); return; } if (IsSet (ch->pcdata->i3chardata->i3flags, I3_BEEP)) { i3println (ch, "Your i3beeps are turned off."); return; } if (I3ISINVIS (ch)) { i3println (ch, "You are invisible."); return; } ps = strchr (argument, '@'); if (NullStr (argument) || ps == NULL) { i3println (ch, "{YYou should specify a person@mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } ps[0] = '\0'; ps++; strlcpy (mud, ps, MIL); if (!(pmud = find_I3_mud_by_name (mud))) { i3println (ch, "{YNo such mud known.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (!str_cmp (I3_THISMUD, pmud->name)) { i3println (ch, "Use your mud's own internal system for that."); return; } if (pmud->status >= 0) { i3printlnf (ch, "%s is marked as down.", pmud->name); return; } if (pmud->beep == 0) i3printlnf (ch, "%s does not support the 'beep' command. Sending anyway.", pmud->name); I3_send_beep (ch, argument, pmud); i3printlnf (ch, "{YYou beep %s@%s.", capitalize (argument), pmud->name); } void I3_send_tell (CharData * ch, const char *to, I3_MUD * mud, const char *message) { if (!I3_is_connected ()) return; I3_escape (to); I3_write_header ("tell", I3_THISMUD, GetName (ch), mud->name, to); I3_write_buffer ("\""); I3_write_buffer (GetName (ch)); I3_write_buffer ("\",\""); send_to_i3 (I3_escape (message)); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void i3_update_tellhistory (CharData * ch, const char *msg) { char new_msg[MSL]; time_t t = time (NULL); struct tm *local = localtime (&t); int x; snprintf (new_msg, sizeof (new_msg), "{R[%-2.2d:%-2.2d] %s", local->tm_hour, local->tm_min, msg); for (x = 0; x < MAX_I3TELLHISTORY; x++) { if (ch->pcdata->i3chardata->i3_tellhistory[x] == '\0') { ch->pcdata->i3chardata->i3_tellhistory[x] = str_dup (new_msg); break; } if (x == MAX_I3TELLHISTORY - 1) { int i; for (i = 1; i < MAX_I3TELLHISTORY; i++) { free_string (ch->pcdata->i3chardata->i3_tellhistory[i - 1]); ch->pcdata->i3chardata->i3_tellhistory[i - 1] = str_dup (ch->pcdata->i3chardata->i3_tellhistory[i]); } free_string (ch->pcdata->i3chardata->i3_tellhistory[x]); ch->pcdata->i3chardata->i3_tellhistory[x] = str_dup (new_msg); } } return; } void I3_process_tell (I3_HEADER * header, char *s) { char buf[MIL], usr[MIL]; char *ps = s, *next_ps; CharData *ch; snprintf (buf, sizeof (buf), "%s@%s", header->originator_username, header->originator_mudname); if (!(ch = I3_find_user (header->target_username))) { if (!exists_player (header->target_username)) I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); else I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } if (ch->pcdata->i3chardata->i3perm < I3PERM_MORT) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); return; } if (I3ISINVIS (ch) || i3ignoring (ch, buf)) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } if (IsSet (ch->pcdata->i3chardata->i3flags, I3_TELL)) { snprintf (buf, sizeof (buf), "%s is not accepting tells.", GetName (ch)); I3_send_error (header->originator_mudname, header->originator_username, "unk-user", buf); return; } if (I3AFK (ch)) { snprintf (buf, sizeof (buf), "%s is currently AFK. Try back later.", GetName (ch)); I3_send_error (header->originator_mudname, header->originator_username, "unk-user", buf); return; } I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (usr, sizeof (usr), "%s@%s", ps, header->originator_mudname); snprintf (buf, sizeof (buf), "'%s@%s'", ps, header->originator_mudname); replace_str (&ch->pcdata->i3chardata->i3_replyname, buf); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (buf, sizeof (buf), "{Y%s i3tells you: {c%s", usr, ps); i3println (ch, buf); i3_update_tellhistory (ch, buf); return; } Do_Fun (I3_tell) { char to[MIL], *ps; char mud[MIL]; I3_MUD *pmud; if (IsSet (ch->pcdata->i3chardata->i3flags, I3_DENYTELL)) { i3println (ch, "You are not allowed to use i3tells."); return; } if (NullStr (argument)) { int x; cmd_syntax (ch, NULL, "<user@mud> <message>", "on/off", NULL); i3printlnf (ch, "{cThe last %d things you were told:", MAX_I3TELLHISTORY); for (x = 0; x < MAX_I3TELLHISTORY; x++) { if (ch->pcdata->i3chardata->i3_tellhistory[x] == NULL) break; i3println (ch, ch->pcdata->i3chardata->i3_tellhistory[x]); } return; } if (!str_cmp (argument, "on")) { RemBit (ch->pcdata->i3chardata->i3flags, I3_TELL); i3println (ch, "You now send and receive i3tells."); return; } if (!str_cmp (argument, "off")) { SetBit (ch->pcdata->i3chardata->i3flags, I3_TELL); i3println (ch, "You no longer send and receive i3tells."); return; } if (IsSet (ch->pcdata->i3chardata->i3flags, I3_TELL)) { i3println (ch, "Your i3tells are turned off."); return; } if (I3ISINVIS (ch)) { i3println (ch, "You are invisible."); return; } argument = first_arg (argument, to, false); ps = strchr (to, '@'); if (NullStr (to) || NullStr (argument) || ps == NULL) { i3println (ch, "{YYou should specify a person and a mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } ps[0] = '\0'; ps++; strlcpy (mud, ps, MIL); if (!(pmud = find_I3_mud_by_name (mud))) { i3print (ch, "{YNo such mud known.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (!str_cmp (I3_THISMUD, pmud->name)) { i3println (ch, "Use your mud's own internal system for that."); return; } if (pmud->status >= 0) { i3printlnf (ch, "%s is marked as down.", pmud->name); return; } if (pmud->tell == 0) { i3printlnf (ch, "%s does not support the 'tell' command.", pmud->name); return; } I3_send_tell (ch, to, pmud, argument); snprintf (mud, sizeof (mud), "{YYou i3tell %s@%s: {c%s", capitalize (to), pmud->name, argument); i3println (ch, mud); i3_update_tellhistory (ch, mud); } Do_Fun (I3_reply) { char buf[MSL]; if (IsSet (ch->pcdata->i3chardata->i3flags, I3_DENYTELL)) { i3println (ch, "You are not allowed to use i3tells."); return; } if (NullStr (argument)) { cmd_syntax (ch, NULL, "<message>", NULL); return; } if (IsSet (ch->pcdata->i3chardata->i3flags, I3_TELL)) { i3println (ch, "Your i3tells are turned off."); return; } if (I3ISINVIS (ch)) { i3println (ch, "You are invisible."); return; } if (!ch->pcdata->i3chardata->i3_replyname) { i3println (ch, "You have not yet received an i3tell?!?"); return; } snprintf (buf, sizeof (buf), "%s %s", ch->pcdata->i3chardata->i3_replyname, argument); I3_tell (n_fun, ch, buf); return; } void I3_send_who (CharData * ch, const char *mud) { if (!I3_is_connected ()) return; I3_escape (mud); I3_write_header ("who-req", I3_THISMUD, GetName (ch), mud, NULL); I3_write_buffer ("})\r"); I3_send_packet (); return; } char * i3centerline (const char *string, int length) { char stripped[300]; static char outbuf[400]; int amount; strlcpy (stripped, i3_strip_colors (string), 300); amount = length - strlen (stripped); if (amount < 1) amount = 1; snprintf (outbuf, sizeof (outbuf), "%*s%s%*s", (amount / 2), "", string, ((amount / 2) * 2) == amount ? (amount / 2) : ((amount / 2) + 1), ""); return outbuf; } #ifndef I3CUSTOMWHO void I3_process_who_req (I3_HEADER * header, char *s) { Descriptor *d; CharData *person; char ibuf[MIL], personbuf[MSL], tailbuf[MSL]; char smallbuf[50], buf[300], outbuf[400], stats[200], rank[200]; int pcount = 0, xx, yy; long int bogusidle = 9999; snprintf (ibuf, sizeof (ibuf), "%s@%s", header->originator_username, header->originator_mudname); I3_write_header ("who-reply", I3_THISMUD, NULL, header->originator_mudname, header->originator_username); I3_write_buffer ("({"); I3_write_buffer ("({\""); snprintf (buf, 300, "{R-=[ {WPlayers on %s {R]=-", I3_THISMUD); strlcpy (outbuf, i3centerline (buf, 78), 400); send_to_i3 (I3_escape (outbuf)); I3_write_buffer ("\","); snprintf (smallbuf, 50, "%ld", -1l); I3_write_buffer (smallbuf); I3_write_buffer (",\" \",}),({\""); snprintf (buf, 300, "{Y-=[ {Wtelnet://%s:%d {Y]=-", i3mud_info.telnet, i3mud_info.player_port); strlcpy (outbuf, i3centerline (buf, 78), 400); send_to_i3 (I3_escape (outbuf)); I3_write_buffer ("\","); snprintf (smallbuf, 50, "%ld", bogusidle); I3_write_buffer (smallbuf); I3_write_buffer (",\" \",}),"); xx = 0; for (d = descriptor_first; d; d = d->next) { person = d->original ? d->original : d->character; if (person && d->connected >= CON_PLAYING) { if (person->pcdata->i3chardata->i3perm < I3PERM_MORT || person->pcdata->i3chardata->i3perm >= I3PERM_IMM || I3ISINVIS (person) || i3ignoring (person, ibuf)) continue; pcount++; if (xx == 0) { I3_write_buffer ("({\""); send_to_i3 (I3_escape ("{B--------------------------------=[ {WPlayers {B]=---------------------------------")); I3_write_buffer ("\","); snprintf (smallbuf, 50, "%ld", bogusidle); I3_write_buffer (smallbuf); I3_write_buffer (",\" \",}),"); } I3_write_buffer ("({\""); strlcpy (rank, rankbuffer (person), 200); strlcpy (outbuf, i3centerline (rank, 20), 400); send_to_i3 (I3_escape (outbuf)); I3_write_buffer ("\","); snprintf (smallbuf, 50, "%ld", -1l); I3_write_buffer (smallbuf); I3_write_buffer (",\""); strlcpy (stats, "{D[", 200); if (I3AFK (person)) strlcat (stats, "AFK", 200); else strlcat (stats, "---", 200); strlcat (stats, "]{G", 200); snprintf (personbuf, sizeof (personbuf), "%s %s%s", stats, GetName (person), person->pcdata->title); send_to_i3 (I3_escape (personbuf)); I3_write_buffer ("\",}),"); xx++; } } yy = 0; for (d = descriptor_first; d; d = d->next) { person = CH (d); if (person && d->connected >= CON_PLAYING) { if (person->pcdata->i3chardata->i3perm < I3PERM_IMM || I3ISINVIS (person) || i3ignoring (person, ibuf)) continue; pcount++; if (yy == 0) { I3_write_buffer ("({\""); send_to_i3 (I3_escape ("{R-------------------------------=[ {WImmortals {R]=--------------------------------")); I3_write_buffer ("\","); if (xx > 0) snprintf (smallbuf, 50, "%ld", bogusidle * 3); else snprintf (smallbuf, 50, "%ld", bogusidle); I3_write_buffer (smallbuf); I3_write_buffer (",\" \",}),"); } I3_write_buffer ("({\""); strlcpy (rank, rankbuffer (person), 200); strlcpy (outbuf, i3centerline (rank, 20), 400); send_to_i3 (I3_escape (outbuf)); I3_write_buffer ("\","); snprintf (smallbuf, 50, "%ld", -1l); I3_write_buffer (smallbuf); I3_write_buffer (",\""); strlcpy (stats, "{D[", 200); if (I3AFK (person)) strlcat (stats, "AFK", 200); else strlcat (stats, "---", 200); strlcat (stats, "]{G", 200); snprintf (personbuf, sizeof (personbuf), "%s %s%s", stats, GetName (person), person->pcdata->title); send_to_i3 (I3_escape (personbuf)); I3_write_buffer ("\",}),"); yy++; } } I3_write_buffer ("({\""); snprintf (tailbuf, sizeof (tailbuf), "{Y[{W%d Player%s{Y]", pcount, pcount == 1 ? "" : "s"); send_to_i3 (I3_escape (tailbuf)); I3_write_buffer ("\","); snprintf (smallbuf, 50, "%ld", bogusidle * 2); I3_write_buffer (smallbuf); I3_write_buffer (",\""); #ifndef DISABLE_WEBSRV if (web_is_connected ()) snprintf (tailbuf, sizeof (tailbuf), "{Y[{WHomepage: http://%s:%d/{Y]", i3mud_info.web, webport); else #endif snprintf (tailbuf, sizeof (tailbuf), "{Y[{WHomepage: http://%s/{Y]", i3mud_info.web); send_to_i3 (I3_escape (tailbuf)); I3_write_buffer ("\",}),}),})\r"); I3_send_packet (); return; } #endif void I3_process_who_reply (I3_HEADER * header, char *s) { char *ps = s, *next_ps, *next_ps2; CharData *ch; char person[MSL], title[MIL]; int idle; if (!(ch = I3_find_user (header->target_username))) return; ps += 2; while (1) { if (ps[0] == '}') { i3println (ch, "{WNo information returned."); return; } I3_get_field (ps, &next_ps); ps += 2; I3_get_field (ps, &next_ps2); I3_remove_quotes (&ps); strlcpy (person, ps, MSL); ps = next_ps2; I3_get_field (ps, &next_ps2); idle = atoi (ps); ps = next_ps2; I3_get_field (ps, &next_ps2); I3_remove_quotes (&ps); strlcpy (title, ps, MIL); ps = next_ps2; if (idle == 9999) i3printlnf (ch, "%s %s" NEWLINE, person, title); else if (idle == 19998) i3printlnf (ch, "\n\r%s %s", person, title); else if (idle == 29997) i3printlnf (ch, "\n\r%s %s" NEWLINE, person, title); else i3printlnf (ch, "%s %s", person, title); ps = next_ps; if (ps[0] == '}') break; } return; } void I3_send_emoteto (CharData * ch, const char *to, I3_MUD * mud, const char *message) { char buf[MSL]; if (!I3_is_connected ()) return; if (strstr (message, "$N") == NULL) snprintf (buf, sizeof (buf), "$N %s", message); else strlcpy (buf, message, MSL); I3_escape (to); I3_write_header ("emoteto", I3_THISMUD, GetName (ch), mud->name, to); I3_write_buffer ("\""); I3_write_buffer (GetName (ch)); I3_write_buffer ("\",\""); send_to_i3 (I3_escape (buf)); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_process_emoteto (I3_HEADER * header, char *s) { CharData *ch; char *ps = s, *next_ps; char visname[MIL], buf[MIL]; snprintf (buf, sizeof (buf), "%s@%s", header->originator_username, header->originator_mudname); if (!(ch = I3_find_user (header->target_username))) { if (!exists_player (header->target_username)) I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); else I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } if (ch->pcdata->i3chardata->i3perm < I3PERM_MORT) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); return; } if (I3ISINVIS (ch) || i3ignoring (ch, buf) || !ch->desc) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (visname, sizeof (visname), "%s@%s", ps, header->originator_mudname); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); i3printlnf (ch, "{c%s", I3_convert_channel_message (ps, visname, visname)); return; } void I3_send_finger (CharData * ch, const char *user, const char *mud) { if (!I3_is_connected ()) return; I3_escape (mud); I3_write_header ("finger-req", I3_THISMUD, GetName (ch), mud, NULL); I3_write_buffer ("\""); I3_write_buffer (I3_escape (user)); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_process_finger_reply (I3_HEADER * header, char *s) { CharData *ch; char *ps = s, *next_ps; char title[MIL], email[MIL], last[MIL], level[MIL]; if (!(ch = I3_find_user (header->target_username))) return; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); i3printlnf (ch, "{wI3FINGER information for {G%s@%s", ps, header->originator_mudname); i3println (ch, "{w-------------------------------------------------"); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (title, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (email, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (last, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (level, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); i3printlnf (ch, "{wTitle: {G%s", title); i3printlnf (ch, "{wLevel: {G%s", level); i3printlnf (ch, "{wEmail: {G%s", email); i3printlnf (ch, "{wHTTP : {G%s", ps); i3printlnf (ch, "{wLast on: {G%s", last); return; } void I3_process_finger_req (I3_HEADER * header, char *s) { CharData *ch; char *ps = s, *next_ps; char smallbuf[200], buf[MIL]; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (buf, sizeof (buf), "%s@%s", header->originator_username, header->originator_mudname); if (!(ch = I3_find_user (ps))) { if (!exists_player (ps)) I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); else I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } if (ch->pcdata->i3chardata->i3perm < I3PERM_MORT) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "No such player."); return; } if (I3ISINVIS (ch) || i3ignoring (ch, buf)) { I3_send_error (header->originator_mudname, header->originator_username, "unk-user", "That player is offline."); return; } if (IsSet (ch->pcdata->i3chardata->i3flags, I3_DENYFINGER) || IsSet (ch->pcdata->i3chardata->i3flags, I3_PRIVACY)) { snprintf (buf, sizeof (buf), "%s is not accepting fingers.", GetName (ch)); I3_send_error (header->originator_mudname, header->originator_username, "unk-user", buf); return; } i3printlnf (ch, "%s@%s has requested your i3finger information.", header->originator_username, header->originator_mudname); I3_write_header ("finger-reply", I3_THISMUD, NULL, header->originator_mudname, header->originator_username); I3_write_buffer ("\""); I3_write_buffer (I3_escape (GetName (ch))); I3_write_buffer ("\",\""); I3_write_buffer (I3_escape (GetName (ch))); send_to_i3 (I3_escape (ch->pcdata->title)); I3_write_buffer ("\",\"\",\""); #ifdef FINGERCODE if (ch->pcdata->email) { if (!IsSet (ch->pcdata->flags, PCFLAG_PRIVACY)) I3_write_buffer (ch->pcdata->email); else I3_write_buffer ("[Private]"); } #else I3_write_buffer ("Not supported"); #endif I3_write_buffer ("\",\""); strlcpy (smallbuf, "-1", 200); I3_write_buffer (smallbuf); I3_write_buffer ("\","); snprintf (smallbuf, sizeof (smallbuf), "%ld", -1l); I3_write_buffer (smallbuf); I3_write_buffer (",\""); I3_write_buffer ("[PRIVATE]"); I3_write_buffer ("\",\""); snprintf (buf, sizeof (buf), "%s", rankbuffer (ch)); send_to_i3 (buf); #ifdef FINGERCODE I3_write_buffer ("\",\""); if (ch->pcdata->homepage) I3_write_buffer (I3_escape (ch->pcdata->homepage)); else I3_write_buffer ("Not Provided"); I3_write_buffer ("\",})\r"); #else I3_write_buffer ("\",\"Not Suported\",})\r"); #endif I3_send_packet (); return; } void I3_send_locate (CharData * ch, const char *user) { if (!I3_is_connected ()) return; I3_write_header ("locate-req", I3_THISMUD, GetName (ch), NULL, NULL); I3_write_buffer ("\""); I3_write_buffer (I3_escape (user)); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_process_locate_reply (I3_HEADER * header, char *s) { char mud_name[MIL], user_name[MIL], status[MIL]; char *ps = s, *next_ps; CharData *ch; if (!(ch = I3_find_user (header->target_username))) return; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (mud_name, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (user_name, ps, MIL); ps = next_ps; I3_get_field (ps, &next_ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (status, ps, MIL); if (!str_cmp (status, "active")) strlcpy (status, "Online", MIL); if (!str_cmp (status, "exists, but not logged on")) strlcpy (status, "Offline", MIL); i3printlnf (ch, "{RI3 Locate: {Y%s@%s: {c%s.", user_name, mud_name, status); return; } void I3_process_locate_req (I3_HEADER * header, char *s) { char *ps = s, *next_ps; char smallbuf[50], buf[MIL]; CharData *ch; bool choffline = false; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); snprintf (buf, sizeof (buf), "%s@%s", header->originator_username, header->originator_mudname); if (!(ch = I3_find_user (ps))) { if (exists_player (ps)) choffline = true; else return; } if (ch) { if (ch->pcdata->i3chardata->i3perm < I3PERM_MORT) return; if (I3ISINVIS (ch)) choffline = true; if (i3ignoring (ch, buf)) choffline = true; } I3_write_header ("locate-reply", I3_THISMUD, NULL, header->originator_mudname, header->originator_username); I3_write_buffer ("\""); I3_write_buffer (I3_THISMUD); I3_write_buffer ("\",\""); if (!choffline) I3_write_buffer (GetName (ch)); else I3_write_buffer (capitalize (ps)); I3_write_buffer ("\","); snprintf (smallbuf, sizeof (smallbuf), "%ld", -1l); I3_write_buffer (smallbuf); if (!choffline) I3_write_buffer (",\"Online\",})\r"); else I3_write_buffer (",\"Offline\",})\r"); I3_send_packet (); return; } void I3_send_channel_listen (I3_CHANNEL * channel, bool lconnect) { if (!I3_is_connected ()) return; I3_write_header ("channel-listen", I3_THISMUD, NULL, I3_ROUTER_NAME, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\","); if (lconnect) I3_write_buffer ("1,})\r"); else I3_write_buffer ("0,})\r"); I3_send_packet (); return; } Do_Fun (I3_mudlisten) { I3_CHANNEL *channel; char arg[MIL]; if (NullStr (argument)) { i3println (ch, "Usage: i3mudlisten [all/none]"); i3println (ch, "Usage: i3mudlisten <localchannel> [on/off]"); return; } if (!str_cmp (argument, "all")) { for (channel = I3chan_first; channel; channel = channel->next) { if (NullStr (channel->local_name)) continue; i3printlnf (ch, "Subscribing to %s.", channel->local_name); I3_send_channel_listen (channel, true); } i3println (ch, "{YThe mud is now subscribed to all available local I3 channels."); return; } if (!str_cmp (argument, "none")) { for (channel = I3chan_first; channel; channel = channel->next) { if (NullStr (channel->local_name)) continue; i3printlnf (ch, "Unsubscribing from %s.", channel->local_name); I3_send_channel_listen (channel, false); } i3println (ch, "{YThe mud is now unsubscribed from all available local I3 channels."); return; } argument = first_arg (argument, arg, false); if (!(channel = find_I3_channel_by_localname (arg))) { i3println (ch, "No such channel configured locally."); return; } if (!str_cmp (argument, "on")) { i3printlnf (ch, "Turning %s channel on.", channel->local_name); I3_send_channel_listen (channel, true); return; } if (!str_cmp (argument, "off")) { i3printlnf (ch, "Turning %s channel off.", channel->local_name); I3_send_channel_listen (channel, false); return; } I3_mudlisten (n_fun, ch, ""); return; } void i3init_char (CharData * ch) { if (IsNPC (ch)) return; alloc_mem (ch->pcdata->i3chardata, I3_CHARDATA, 1); ch->pcdata->i3chardata->i3_listen = NULL; ch->pcdata->i3chardata->i3_denied = NULL; ch->pcdata->i3chardata->i3_replyname = NULL; ch->pcdata->i3chardata->i3flags = I3_COLORFLAG; ch->pcdata->i3chardata->i3ignore_first = NULL; ch->pcdata->i3chardata->i3ignore_last = NULL; ch->pcdata->i3chardata->i3perm = I3PERM_NOTSET; return; } void I3_char_login (CharData * ch) { sex_t gender, sex; char buf[MIL]; if (ch->pcdata->i3chardata->i3perm == I3PERM_NOTSET) { if (ch->level < i3mud_info.minlevel) ch->pcdata->i3chardata->i3perm = I3PERM_NONE; else if (ch->level >= i3mud_info.minlevel && ch->level < i3mud_info.immlevel) ch->pcdata->i3chardata->i3perm = I3PERM_MORT; else if (ch->level >= i3mud_info.immlevel && ch->level < i3mud_info.adminlevel) ch->pcdata->i3chardata->i3perm = I3PERM_IMM; else if (ch->level >= i3mud_info.adminlevel && ch->level < i3mud_info.implevel) ch->pcdata->i3chardata->i3perm = I3PERM_ADMIN; else if (ch->level >= i3mud_info.implevel) ch->pcdata->i3chardata->i3perm = I3PERM_IMP; } if (!I3_is_connected ()) { if (ch->pcdata->i3chardata->i3perm >= I3PERM_IMM && i3wait == -2) i3println (ch, "{RThe Intermud-3 connection is down. Attempts to reconnect were abandoned due to excessive failures."); return; } if (ch->pcdata->i3chardata->i3perm < I3PERM_MORT) return; if (i3mud_info.ucache == true) { snprintf (buf, sizeof (buf), "%s@%s", GetName (ch), I3_THISMUD); gender = I3_get_ucache_gender (buf); sex = dikutoi3gender (ch->sex); if (gender == sex) return; I3_ucache_update (buf, sex); if (!IsSet (ch->pcdata->i3chardata->i3flags, I3_INVIS)) I3_send_ucache_update (GetName (ch), sex); } return; } bool i3load_char (CharData * ch, FileData * fp, const char *word) { bool fMatch = false; if (IsNPC (ch)) return false; switch (toupper (word[0])) { case 'I': Key ("i3perm", ch->pcdata->i3chardata->i3perm, read_enum (i3perm_t, fp)); if (!str_cmp (word, "i3flags")) { ch->pcdata->i3chardata->i3flags = read_number (fp); I3_char_login (ch); read_to_eol (fp); fMatch = true; break; } if (!str_cmp (word, "i3invis")) { bool tempinvis = (bool) read_number (fp); if (tempinvis == true) SetBit (ch->pcdata->i3chardata->i3flags, I3_INVIS); I3_char_login (ch); read_to_eol (fp); fMatch = true; break; } if (!str_cmp (word, "i3listen")) { ch->pcdata->i3chardata->i3_listen = read_string (fp); if (ch->pcdata->i3chardata->i3_listen != NULL && I3_is_connected ()) { I3_CHANNEL *channel = NULL; const char *channels = ch->pcdata->i3chardata->i3_listen; char arg[MIL]; while (1) { if (channels[0] == '\0') break; channels = first_arg (channels, arg, false); if (!(channel = find_I3_channel_by_localname (arg))) unflagname (&ch->pcdata->i3chardata->i3_listen, arg); if (channel && ch->pcdata->i3chardata->i3perm < channel->i3perm) unflagname (&ch->pcdata->i3chardata->i3_listen, arg); } } read_to_eol (fp); fMatch = true; break; } if (!str_cmp (word, "i3deny")) { ch->pcdata->i3chardata->i3_denied = read_string (fp); if (ch->pcdata->i3chardata->i3_denied != NULL && I3_is_connected ()) { I3_CHANNEL *channel = NULL; const char *channels = ch->pcdata->i3chardata->i3_denied; char arg[MIL]; while (1) { if (channels[0] == '\0') break; channels = first_arg (channels, arg, false); if (!(channel = find_I3_channel_by_localname (arg))) unflagname (&ch->pcdata->i3chardata->i3_denied, arg); if (channel && ch->pcdata->i3chardata->i3perm < channel->i3perm) unflagname (&ch->pcdata->i3chardata->i3_denied, arg); } } read_to_eol (fp); fMatch = true; break; } if (!str_cmp (word, "i3ignore")) { I3_IGNORE *temp; alloc_mem (temp, I3_IGNORE, 1); temp->name = read_string (fp); Link (temp, ch->pcdata->i3chardata->i3ignore, next, prev); read_to_eol (fp); fMatch = true; break; } break; } return fMatch; } void i3save_char (CharData * ch, FileData * fp) { I3_IGNORE *temp; if (IsNPC (ch)) return; write_int (fp, "i3perm", "%d", ch->pcdata->i3chardata->i3perm, I3PERM_NOTSET); write_bit (fp, "i3flags", ch->pcdata->i3chardata->i3flags, I3_COLORFLAG); write_string (fp, "i3listen", ch->pcdata->i3chardata->i3_listen, NULL); write_string (fp, "i3deny", ch->pcdata->i3chardata->i3_denied, NULL); for (temp = ch->pcdata->i3chardata->i3ignore_first; temp; temp = temp->next) write_string (fp, "i3ignore", temp->name, NULL); return; } I3_COLOR * new_i3color (void) { I3_COLOR *Data; alloc_mem (Data, I3_COLOR, 1); return Data; } TableSave_Fun (rw_i3_colors) { rw_list (type, I3_COLOR_FILE, I3_COLOR, i3color); } I3_HELP_DATA * new_i3help (void) { I3_HELP_DATA *Data; alloc_mem (Data, I3_HELP_DATA, 1); return Data; } TableSave_Fun (rw_i3_helps) { rw_list (type, I3_HELP_FILE, I3_HELP_DATA, i3help); } I3_CMD_DATA * new_i3cmd (void) { I3_CMD_DATA *Data; alloc_mem (Data, I3_CMD_DATA, 1); return Data; } TableSave_Fun (rw_i3_cmds) { rw_list (type, I3_CMD_FILE, I3_CMD_DATA, i3cmd); } ROUTER_DATA * new_router (void) { ROUTER_DATA *Data; alloc_mem (Data, ROUTER_DATA, 1); Data->reconattempts = 0; return Data; } TableSave_Fun (rw_i3_config) { rw_single (type, I3_CONFIG_FILE, i3mud); } TableSave_Fun (rw_i3_routers) { rw_list (type, I3_ROUTER_FILE, ROUTER_DATA, router); } ROUTER_DATA * i3_find_router (const char *name) { ROUTER_DATA *router; for (router = router_first; router; router = router->next) { if (!str_cmp (router->name, name)) return router; } return NULL; } bool I3_read_config (int mudport) { wiznet ("Loading Intermud-3 network data...", NULL, NULL, WIZ_I3, true, 1); i3mud_info.status = -1; i3mud_info.autoconnect = 0; i3mud_info.password = 0; i3mud_info.mudlist_id = 0; i3mud_info.chanlist_id = 0; i3mud_info.minlevel = 10; i3mud_info.immlevel = LEVEL_IMMORTAL; i3mud_info.adminlevel = MAX_LEVEL - 2; i3mud_info.implevel = MAX_LEVEL; rw_i3_config (act_read); replace_strf (&i3mud_info.name, "%s-%d", mud_info.name, mud_info.unique_id); i3mud_info.player_port = mudport; replace_str (&i3mud_info.mudlib, MUDSTRING); if (str_cmp (i3mud_info.base_mudlib, MUDNAME)) replace_str (&i3mud_info.base_mudlib, MUDNAME); replace_str (&i3mud_info.driver, I3DRIVER); if (NullStr (i3mud_info.telnet)) replace_str (&i3mud_info.telnet, HOSTNAME); if (NullStr (i3mud_info.admin_email)) replace_strf (&i3mud_info.admin_email, "%s@%s", UNAME, HOSTNAME); if (NullStr (i3mud_info.web)) replace_str (&i3mud_info.web, HOSTNAME); I3_THISMUD = i3mud_info.name; return true; } I3_BAN * new_I3ban (void) { I3_BAN *Data; alloc_mem (Data, I3_BAN, 1); return Data; } TableSave_Fun (rw_i3_bans) { rw_list (type, I3_BAN_FILE, I3_BAN, I3ban); } Do_Fun (I3_mudlist) { I3_MUD *mud; char filter[MIL]; int mudcount = 0; bool all = false; Buffer *output; argument = first_arg (argument, filter, false); if (!str_cmp (filter, "all")) { all = true; argument = first_arg (argument, filter, false); } if (i3mud_first == NULL) { i3println (ch, "There are no muds to list!?"); return; } output = new_buf (); i3bprintlnf (output, "{W%-30s%-10.10s%-25.25s%-15.15s %s", "Name", "Type", "Mudlib", "Address", "Port"); for (mud = i3mud_first; mud; mud = mud->next) { if (mud == NULL) { bug ("I3_mudlist: NULL mud found in listing!"); continue; } if (mud->name == NULL) { bug ("I3_mudlist: NULL mud name found in listing!"); continue; } if (filter[0] && str_prefix (filter, mud->name) && (mud->mud_type && str_prefix (filter, mud->mud_type)) && (mud->mudlib && str_prefix (filter, mud->mudlib))) continue; if (!all && mud->status == 0) continue; mudcount++; switch (mud->status) { case -1: i3bprintlnf (output, "{c%-30s%-10.10s%-25.25s%-15.15s %d", mud->name, mud->mud_type, mud->mudlib, mud->ipaddress, mud->player_port); break; case 0: i3bprintlnf (output, "{R%-26s (down)", mud->name); break; default: i3bprintlnf (output, "{Y%-26s (rebooting, back in %d seconds)", mud->name, mud->status); break; } } i3bprintlnf (output, "{W%d total muds listed.", mudcount); sendpage (ch, buf_string (output)); free_buf (output); return; } Do_Fun (I3_chanlist) { I3_CHANNEL *channel; bool all = false, found = false; char filter[MIL]; Buffer *output; argument = first_arg (argument, filter, false); if (!str_cmp (filter, "all") && I3_is_connected ()) { all = true; argument = first_arg (argument, filter, false); } output = new_buf (); i3bprintln (output, "{cLocal name Perm I3 Name Hosted at Status"); i3bprintln (output, draw_line (ch, "{c-{w-", 0)); for (channel = I3chan_first; channel; channel = channel->next) { found = false; if (!all && !channel->local_name && (NullStr (filter))) continue; if (ch->pcdata->i3chardata->i3perm < I3PERM_ADMIN && !channel->local_name) continue; if (ch->pcdata->i3chardata->i3perm < channel->i3perm) continue; if (!all && !NullStr (filter) && str_prefix (filter, channel->I3_name) && str_prefix (filter, channel->host_mud)) continue; if (channel->local_name && hasname (ch->pcdata->i3chardata->i3_listen, channel->local_name)) found = true; i3bprintlnf (output, "{C%c {W%-18s{Y%-8s{B%-20s{M%-20s%-8s", found ? '*' : ' ', channel->local_name ? channel-> local_name : "Not configured", i3perm_names[channel->i3perm].name, channel->I3_name, channel->host_mud, channel->status == 0 ? "{GPublic" : "{RPrivate"); } i3bprintln (output, "{C*: You are listening to these channels."); sendpage (ch, buf_string (output)); free_buf (output); return; } Do_Fun (I3_setup_channel) { Descriptor *d; char localname[MIL], I3_name[MIL]; I3_CHANNEL *channel, *channel2; int permvalue = I3PERM_MORT; argument = first_arg (argument, I3_name, false); argument = first_arg (argument, localname, false); if (!(channel = find_I3_channel_by_name (I3_name))) { i3printlnf (ch, "{YUnknown channel\n\r" "(use {Wi3chanlist{Y to get an overview of the channels available)"); return; } if (NullStr (localname)) { if (!channel->local_name) { i3printlnf (ch, "Channel %s@%s isn't configured.", channel->I3_name, channel->host_mud); return; } if (channel->i3perm > ch->pcdata->i3chardata->i3perm) { i3printlnf (ch, "You do not have sufficient permission to remove the %s channel.", channel->local_name); return; } for (d = descriptor_first; d; d = d->next) { if (!d->character) continue; if (hasname (d->character->pcdata->i3chardata->i3_listen, channel->local_name)) unflagname (&d->character->pcdata->i3chardata->i3_listen, channel->local_name); if (hasname (d->character->pcdata->i3chardata->i3_denied, channel->local_name)) unflagname (&d->character->pcdata->i3chardata->i3_denied, channel->local_name); } logf ("setup_channel: removing %s as %s@%s", channel->local_name, channel->I3_name, channel->host_mud); I3_send_channel_listen (channel, false); free_string (channel->local_name); rw_i3_channels (act_write); } else { if (channel->local_name) { i3printlnf (ch, "Channel %s@%s is already known as %s.", channel->I3_name, channel->host_mud, channel->local_name); return; } if ((channel2 = find_I3_channel_by_localname (localname))) { i3printlnf (ch, "Channel %s@%s is already known as %s.", channel2->I3_name, channel2->host_mud, channel2->local_name); return; } if (!NullStr (argument)) { permvalue = get_permvalue (argument); if (permvalue < 0 || permvalue > I3PERM_IMP) { i3println (ch, "Invalid permission setting."); return; } if (permvalue > ch->pcdata->i3chardata->i3perm) { i3println (ch, "You cannot assign a permission value above your own."); return; } } channel->local_name = str_dup (localname); channel->i3perm = (i3perm_t) permvalue; channel->layout_m = str_dup ("{R[{W%s{R] {C%s@%s: {c%s"); channel->layout_e = str_dup ("{R[{W%s{R] {c%s"); i3printlnf (ch, "%s@%s is now locally known as %s", channel->I3_name, channel->host_mud, channel->local_name); logf ("setup_channel: setting up %s@%s as %s", channel->I3_name, channel->host_mud, channel->local_name); I3_send_channel_listen (channel, true); rw_i3_channels (act_write); } } Do_Fun (I3_edit_channel) { char localname[MIL]; char arg2[MIL]; I3_CHANNEL *channel; if (NullStr (argument)) { i3println (ch, "Usage: i3 editchan <localname> localname <new localname>"); i3println (ch, "Usage: i3 editchan <localname> perm <type>"); return; } argument = first_arg (argument, localname, false); if ((channel = find_I3_channel_by_localname (localname)) == NULL) { i3println (ch, "{YUnknown local channel\n\r" "(use {Wi3chanlist{Y to get an overview of the channels available)"); return; } argument = first_arg (argument, arg2, false); if (channel->i3perm > ch->pcdata->i3chardata->i3perm) { i3println (ch, "You do not have sufficient permissions to edit this channel."); return; } if (!str_cmp (arg2, "localname")) { i3printlnf (ch, "Local channel %s renamed to %s.", channel->local_name, argument); replace_str (&channel->local_name, argument); rw_i3_channels (act_write); return; } if (!str_cmp (arg2, "perm") || !str_cmp (arg2, "permission")) { int permvalue = get_permvalue (argument); if (permvalue < 0 || permvalue > I3PERM_IMP) { i3println (ch, "Invalid permission setting."); return; } if (permvalue > ch->pcdata->i3chardata->i3perm) { i3println (ch, "You cannot set a permission higher than your own."); return; } if (channel->i3perm > ch->pcdata->i3chardata->i3perm) { i3println (ch, "You cannot edit a channel above your permission level."); return; } channel->i3perm = (i3perm_t) permvalue; i3printlnf (ch, "Local channel %s permission changed to %s.", channel->local_name, argument); rw_i3_channels (act_write); return; } I3_edit_channel (n_fun, ch, ""); return; } Do_Fun (I3_chan_who) { char channel_name[MIL]; I3_CHANNEL *channel; I3_MUD *mud; argument = first_arg (argument, channel_name, false); if (NullStr (channel_name) || NullStr (argument)) { i3println (ch, "Usage: i3chanwho <local channel> <mud>"); return; } if ((channel = find_I3_channel_by_localname (channel_name)) == NULL) { i3println (ch, "{YUnknown channel.\n\r" "(use {Wi3chanlist{Y to get an overview of the channels available)"); return; } if (!(mud = find_I3_mud_by_name (argument))) { i3println (ch, "{YUnknown mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (mud->status >= 0) { i3printlnf (ch, "%s is marked as down.", mud->name); return; } I3_send_chan_who (ch, channel, mud); } Do_Fun (I3_listen_channel) { I3_CHANNEL *channel; if (NullStr (argument)) { i3println (ch, "Usage: i3listen <local channel name>"); return; } if (!str_cmp (argument, "all")) { for (channel = I3chan_first; channel; channel = channel->next) { if (NullStr (channel->local_name)) continue; if (ch->pcdata->i3chardata->i3perm >= channel->i3perm && !hasname (ch->pcdata->i3chardata->i3_listen, channel->local_name)) flagname (&ch->pcdata->i3chardata->i3_listen, channel->local_name); } i3println (ch, "{YYou are now listening to all available I3 channels."); return; } if (!str_cmp (argument, "none")) { for (channel = I3chan_first; channel; channel = channel->next) { if (NullStr (channel->local_name)) continue; if (hasname (ch->pcdata->i3chardata->i3_listen, channel->local_name)) unflagname (&ch->pcdata->i3chardata->i3_listen, channel->local_name); } i3println (ch, "{YYou no longer listen to any available I3 channels."); return; } if ((channel = find_I3_channel_by_localname (argument)) == NULL) { i3println (ch, "{YUnknown channel.\n\r" "(use {Wi3chanlist{Y to get an overview of the channels available)"); return; } if (hasname (ch->pcdata->i3chardata->i3_listen, channel->local_name)) { i3printlnf (ch, "You no longer listen to %s", channel->local_name); unflagname (&ch->pcdata->i3chardata->i3_listen, channel->local_name); } else { if (ch->pcdata->i3chardata->i3perm < channel->i3perm) { i3printlnf (ch, "Channel %s is above your permission level.", channel->local_name); return; } i3printlnf (ch, "You now listen to %s", channel->local_name); flagname (&ch->pcdata->i3chardata->i3_listen, channel->local_name); } return; } Do_Fun (I3_deny_channel) { char vic_name[MIL]; CharData *victim; I3_CHANNEL *channel; argument = first_arg (argument, vic_name, false); if (NullStr (vic_name) || NullStr (argument)) { i3println (ch, "Usage: i3deny <person> <local channel name>"); i3println (ch, "Usage: i3deny <person> [tell/beep/finger]"); return; } if (!(victim = I3_find_user (vic_name))) { i3println (ch, "No such person is currently online."); return; } if (ch->pcdata->i3chardata->i3perm <= victim->pcdata->i3chardata->i3perm) { i3println (ch, "You cannot alter their settings."); return; } if (!str_cmp (argument, "tell")) { if (!IsSet (victim->pcdata->i3chardata->i3flags, I3_DENYTELL)) { SetBit (victim->pcdata->i3chardata->i3flags, I3_DENYTELL); i3printlnf (ch, "%s can no longer use i3tells.", GetName (victim)); return; } RemBit (victim->pcdata->i3chardata->i3flags, I3_DENYTELL); i3printlnf (ch, "%s can use i3tells again.", GetName (victim)); return; } if (!str_cmp (argument, "beep")) { if (!IsSet (victim->pcdata->i3chardata->i3flags, I3_DENYBEEP)) { SetBit (victim->pcdata->i3chardata->i3flags, I3_DENYBEEP); i3printlnf (ch, "%s can no longer use i3beeps.", GetName (victim)); return; } RemBit (victim->pcdata->i3chardata->i3flags, I3_DENYBEEP); i3printlnf (ch, "%s can use i3beeps again.", GetName (victim)); return; } if (!str_cmp (argument, "finger")) { if (!IsSet (victim->pcdata->i3chardata->i3flags, I3_DENYFINGER)) { SetBit (victim->pcdata->i3chardata->i3flags, I3_DENYFINGER); i3printlnf (ch, "%s can no longer use i3fingers.", GetName (victim)); return; } RemBit (victim->pcdata->i3chardata->i3flags, I3_DENYFINGER); i3printlnf (ch, "%s can use i3fingers again.", GetName (victim)); return; } if (!(channel = find_I3_channel_by_localname (argument))) { i3println (ch, "{YUnknown channel.\n\r" "(use {Wi3chanlist{Y to get an overview of the channels available)"); return; } if (hasname (ch->pcdata->i3chardata->i3_denied, channel->local_name)) { i3printlnf (ch, "%s can now listen to %s", GetName (victim), channel->local_name); unflagname (&ch->pcdata->i3chardata->i3_denied, channel->local_name); } else { i3printlnf (ch, "%s can no longer listen to %s", GetName (victim), channel->local_name); flagname (&ch->pcdata->i3chardata->i3_denied, channel->local_name); } return; } void free_i3chardata (PcData * pcdata) { I3_IGNORE *temp, *next; if (!pcdata) return; free_string (pcdata->i3chardata->i3_listen); free_string (pcdata->i3chardata->i3_denied); free_string (pcdata->i3chardata->i3_replyname); if (pcdata->i3chardata->i3ignore_first) { for (temp = pcdata->i3chardata->i3ignore_first; temp; temp = next) { next = temp->next; free_string (temp->name); UnLink (temp, pcdata->i3chardata->i3ignore, next, prev); free_mem (temp); } } free_mem (pcdata->i3chardata); return; } Do_Fun (I3_mudinfo) { I3_MUD *mud; if (NullStr (argument)) { i3println (ch, "{YWhich mud do you want information about?\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (!(mud = find_I3_mud_by_name (argument))) { i3println (ch, "{YUnknown mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } i3printf (ch, "Information about %s\n\r" NEWLINE, mud->name); if (mud->status == 0) i3println (ch, "Status : Currently down"); else if (mud->status > 0) i3printlnf (ch, "Status : Currently rebooting, back in %d seconds", mud->status); i3printlnf (ch, "MUD port : %s %d", mud->ipaddress, mud->player_port); i3printlnf (ch, "Base mudlib: %s", mud->base_mudlib); i3printlnf (ch, "Mudlib : %s", mud->mudlib); i3printlnf (ch, "Driver : %s", mud->driver); i3printlnf (ch, "Type : %s", mud->mud_type); i3printlnf (ch, "Open status: %s", mud->open_status); i3printlnf (ch, "Admin : %s", mud->admin_email); if (mud->web) { #ifndef DISABLE_WEBSRV if (web_is_connected ()) i3printlnf (ch, "URL : %s:%d", mud->web, webport); else #endif i3printlnf (ch, "URL : %s", mud->web); } if (mud->web_wrong && !mud->web) i3printlnf (ch, "URL : %s", mud->web_wrong); if (mud->daemon) i3printlnf (ch, "Daemon : %s", mud->daemon); if (mud->time) i3printlnf (ch, "Time : %s", mud->time); if (mud->banner) i3printlnf (ch, "Banner:" NEWLINE "%s", mud->banner); i3print (ch, "Supports : "); if (mud->tell) i3print (ch, "tell, "); if (mud->beep) i3print (ch, "beep, "); if (mud->emoteto) i3print (ch, "emoteto, "); if (mud->who) i3print (ch, "who, "); if (mud->finger) i3print (ch, "finger, "); if (mud->locate) i3print (ch, "locate, "); if (mud->channel) i3print (ch, "channel, "); if (mud->news) i3print (ch, "news, "); if (mud->mail) i3print (ch, "mail, "); if (mud->file) i3print (ch, "file, "); if (mud->auth) i3print (ch, "auth, "); if (mud->ucache) i3print (ch, "ucache, "); i3println (ch, ""); i3print (ch, "Supports : "); if (mud->smtp) i3printf (ch, "smtp (port %d), ", mud->smtp); if (mud->http) i3printf (ch, "http (port %d), ", mud->http); if (mud->ftp) i3printf (ch, "ftp (port %d), ", mud->ftp); if (mud->pop3) i3printf (ch, "pop3 (port %d), ", mud->pop3); if (mud->nntp) i3printf (ch, "nntp (port %d), ", mud->nntp); if (mud->rcp) i3printf (ch, "rcp (port %d), ", mud->rcp); if (mud->amrcp) i3printf (ch, "amrcp (port %d), ", mud->amrcp); i3println (ch, ""); } Do_Fun (I3_chanlayout) { I3_CHANNEL *channel = NULL; char arg1[MIL]; char arg2[MIL]; if (NullStr (argument)) { i3println (ch, "Usage: i3chanlayout <localchannel> <layout> <format...>"); i3println (ch, "Layout can be one of these: layout_e layout_m"); i3println (ch, "Format can be any way you want it to look, provided you have the proper number of %s tags in it."); return; } argument = first_arg (argument, arg1, false); argument = first_arg (argument, arg2, false); if (NullStr (arg1)) { I3_chanlayout (n_fun, ch, ""); return; } if (NullStr (arg2)) { I3_chanlayout (n_fun, ch, ""); return; } if (NullStr (argument)) { I3_chanlayout (n_fun, ch, ""); return; } if (!(channel = find_I3_channel_by_localname (arg1))) { i3println (ch, "{YUnknown channel.\n\r" "(use {Wi3chanlist{Y to get an overview of the channels available)"); return; } if (!str_cmp (arg2, "layout_e")) { if (!verify_i3layout (argument, 2)) { i3println (ch, "Incorrect format for layout_e. You need exactly 2 %s's."); return; } replace_str (&channel->layout_e, argument); i3println (ch, "Channel layout_e changed."); rw_i3_channels (act_write); return; } if (!str_cmp (arg2, "layout_m")) { if (!verify_i3layout (argument, 4)) { i3println (ch, "Incorrect format for layout_m. You need exactly 4 %s's."); return; } replace_str (&channel->layout_m, argument); i3println (ch, "Channel layout_m changed."); rw_i3_channels (act_write); return; } I3_chanlayout (n_fun, ch, ""); return; } void free_i3data (bool complete) { I3_MUD *mud, *next_mud; I3_CHANNEL *channel, *next_chan; I3_BAN *ban, *next_ban; I3_UCACHE *ucache, *next_ucache; ROUTER_DATA *router, *router_next; I3_COLOR *color, *color_next; I3_CMD_DATA *cmd, *cmd_next; I3_HELP_DATA *help, *help_next; if (I3ban_first) { for (ban = I3ban_first; ban; ban = next_ban) { next_ban = ban->next; free_string (ban->name); UnLink (ban, I3ban, next, prev); free_mem (ban); } } if (I3chan_first) { for (channel = I3chan_first; channel; channel = next_chan) { next_chan = channel->next; destroy_I3_channel (channel); } } if (i3mud_first) { for (mud = i3mud_first; mud; mud = next_mud) { next_mud = mud->next; destroy_I3_mud (mud); } } if (ucache_first) { for (ucache = ucache_first; ucache; ucache = next_ucache) { next_ucache = ucache->next; free_string (ucache->name); UnLink (ucache, ucache, next, prev); free_mem (ucache); } } if (complete) { if (router_first) { for (router = router_first; router; router = router_next) { router_next = router->next; free_string (router->name); free_string (router->ip); UnLink (router, router, next, prev); free_mem (router); } } for (cmd = i3cmd_first; cmd; cmd = cmd_next) { NameList *alias, *alias_next; cmd_next = cmd->next; free_string (cmd->name); free_string (cmd->args); free_string (cmd->descr); UnLink (cmd, i3cmd, next, prev); for (alias = cmd->alias_first; alias; alias = alias_next) { alias_next = alias->next; free_namelist (alias); } free_mem (cmd); } for (help = i3help_first; help; help = help_next) { help_next = help->next; free_string (help->name); free_string (help->text); UnLink (help, i3help, next, prev); free_mem (help); } for (color = i3color_first; color; color = color_next) { color_next = color->next; free_string (color->name); free_string (color->mudtag); free_string (color->i3tag); free_string (color->i3fish); UnLink (color, i3color, next, prev); free_mem (color); } } return; } Do_Fun (I3_disconnect) { if (!I3_is_connected ()) { i3println (ch, "The MUD isn't connected to the Intermud-3 router."); return; } i3println (ch, "Disconnecting from Intermud-3 router."); I3_shutdown (0); return; } Do_Fun (I3_bancmd) { I3_BAN *temp; if (NullStr (argument)) { i3println (ch, "{GThe mud currently has the following ban list:\n\r"); if (!I3ban_first) { i3println (ch, "{YNothing\n\r"); i3println (ch, "{YTo add a ban, just specify a target. Suggested targets being user@mud or IP:Port"); i3println (ch, "{YUser@mud bans can also have wildcard specifiers, such as *@Mud or User@*"); return; } for (temp = I3ban_first; temp; temp = temp->next) i3printlnf (ch, "{Y\t - %s", temp->name); return; } if (!fnmatch (argument, I3_THISMUD, 0)) { i3println (ch, "{YYou don't really want to do that...."); return; } for (temp = I3ban_first; temp; temp = temp->next) { if (!str_cmp (temp->name, argument)) { free_string (temp->name); UnLink (temp, I3ban, next, prev); free_mem (temp); rw_i3_bans (act_write); i3printlnf (ch, "{YThe mud no longer bans %s.", argument); return; } } alloc_mem (temp, I3_BAN, 1); temp->name = str_dup (argument); Link (temp, I3ban, next, prev); rw_i3_bans (act_write); i3printlnf (ch, "{YThe mud now bans all incoming traffic from %s.", temp->name); } Do_Fun (I3_ignorecmd) { I3_IGNORE *temp; char buf[MIL]; if (NullStr (argument)) { i3println (ch, "{GYou are currently ignoring the following:\n\r"); if (!ch->pcdata->i3chardata->i3ignore_first) { i3print (ch, "{YNobody" NEWLINE); i3println (ch, "{YTo add an ignore, just specify a target. Suggested targets being user@mud or IP:Port"); i3println (ch, "{YUser@mud ignores can also have wildcard specifiers, such as *@Mud or User@*"); return; } for (temp = ch->pcdata->i3chardata->i3ignore_first; temp; temp = temp->next) i3printlnf (ch, "{Y\t - %s", temp->name); return; } snprintf (buf, sizeof (buf), "%s@%s", GetName (ch), I3_THISMUD); if (!str_cmp (buf, argument)) { i3println (ch, "{YYou don't really want to do that...."); return; } if (!fnmatch (argument, I3_THISMUD, 0)) { i3println (ch, "{YIgnoring your own mud would be silly."); return; } for (temp = ch->pcdata->i3chardata->i3ignore_first; temp; temp = temp->next) { if (!str_cmp (temp->name, argument)) { free_string (temp->name); UnLink (temp, ch->pcdata->i3chardata->i3ignore, next, prev); free_mem (temp); i3printlnf (ch, "{YYou are no longer ignoring %s.", argument); return; } } alloc_mem (temp, I3_IGNORE, 1); temp->name = str_dup (argument); Link (temp, ch->pcdata->i3chardata->i3ignore, next, prev); i3printlnf (ch, "{YYou now ignore %s.", temp->name); } Do_Fun (I3_afk) { if (IsSet (ch->pcdata->i3chardata->i3flags, I3_AFK)) { RemBit (ch->pcdata->i3chardata->i3flags, I3_AFK); i3println (ch, "You are no longer AFK to I3."); } else { SetBit (ch->pcdata->i3chardata->i3flags, I3_AFK); i3println (ch, "You are now AFK to I3."); } return; } Do_Fun (I3_color) { if (ch->pcdata->i3chardata->i3perm >= I3PERM_IMM && !str_cmp (argument, "save")) { i3println (ch, "I3 color file saved."); rw_i3_colors (act_write); return; } if (IsSet (ch->pcdata->i3chardata->i3flags, I3_COLORFLAG)) { RemBit (ch->pcdata->i3chardata->i3flags, I3_COLORFLAG); i3println (ch, "I3 color is now off."); } else { SetBit (ch->pcdata->i3chardata->i3flags, I3_COLORFLAG); i3println (ch, "{RI3 c{Yo{Gl{Bo{Mr {Ris now on."); } return; } Do_Fun (i3_cedit) { I3_CMD_DATA *cmd, *tmp; NameList *alias, *alias_next; char name[MIL], option[MIL]; bool found = false, aliasfound = false; argument = one_argument (argument, name); argument = one_argument (argument, option); if (NullStr (name) || NullStr (option)) { i3println (ch, "Usage: i3cedit <command> <create|delete|alias|rename|args|descr|code|permission|connected> <field>."); return; } for (cmd = i3cmd_first; cmd; cmd = cmd->next) { if (!str_cmp (cmd->name, name)) { found = true; break; } for (alias = cmd->alias_first; alias; alias = alias->next) { if (!str_cmp (alias->name, name)) aliasfound = true; } } if (!str_cmp (option, "create")) { if (found) { i3printlnf (ch, "{gA command named {W%s {galready exists.", name); return; } if (aliasfound) { i3printlnf (ch, "{g%s already exists as an alias for another command.", name); return; } alloc_mem (cmd, I3_CMD_DATA, 1); cmd->name = str_dup (name); cmd->args = &str_empty[0]; cmd->descr = &str_empty[0]; cmd->level = ch->pcdata->i3chardata->i3perm; cmd->connected = false; i3printlnf (ch, "{gCommand {W%s {gcreated.", cmd->name); if (NullStr (argument)) { cmd->function = i3_function (argument); if (cmd->function == NULL) i3printlnf (ch, "{gFunction {W%s {gdoes not exist - set to NULL.", argument); } else { i3println (ch, "{gFunction set to NULL."); cmd->function = NULL; } Link (cmd, i3cmd, next, prev); rw_i3_cmds (act_write); return; } if (!found) { i3printlnf (ch, "{gNo command named {W%s {gexists.", name); return; } if (!i3check_permissions (ch, cmd->level, cmd->level, false)) return; if (!str_cmp (option, "delete")) { i3printlnf (ch, "{gCommand {W%s {ghas been deleted.", cmd->name); for (alias = cmd->alias_first; alias; alias = alias_next) { alias_next = alias->next; free_namelist (alias); } UnLink (cmd, i3cmd, next, prev); free_string (cmd->name); free_string (cmd->args); free_string (cmd->descr); free_mem (cmd); rw_i3_cmds (act_write); return; } if (!str_cmp (option, "alias")) { for (alias = cmd->alias_first; alias; alias = alias_next) { alias_next = alias->next; if (!str_cmp (alias->name, argument)) { i3printlnf (ch, "{W%s {ghas been removed as an alias for {W%s", argument, cmd->name); UnLink (alias, cmd->alias, next, prev); free_namelist (alias); rw_i3_cmds (act_write); return; } } for (tmp = i3cmd_first; tmp; tmp = tmp->next) { if (!str_cmp (tmp->name, argument)) { i3printlnf (ch, "{W%s {gis already a command name.", argument); return; } for (alias = tmp->alias_first; alias; alias = alias->next) { if (!str_cmp (argument, alias->name)) { i3printlnf (ch, "{W%s {gis already an alias for {W%s", argument, tmp->name); return; } } } alias = new_namelist (); alias->name = str_dup (argument); Link (alias, cmd->alias, next, prev); i3printlnf (ch, "{W%s {ghas been added as an alias for {W%s", alias->name, cmd->name); rw_i3_cmds (act_write); return; } if (!str_cmp (option, "connected")) { cmd->connected = !cmd->connected; if (cmd->connected) i3printlnf (ch, "{gCommand {W%s {gwill now require a connection to I3 to use.", cmd->name); else i3printlnf (ch, "{gCommand {W%s {gwill no longer require a connection to I3 to use.", cmd->name); rw_i3_cmds (act_write); return; } if (!str_cmp (option, "show")) { char buf[MSL]; i3printlnf (ch, "{gCommand : {W%s", cmd->name); i3printlnf (ch, "{gArgs : {W%s", cmd->args); i3printlnf (ch, "{gDescr : {W%s", cmd->descr); i3printlnf (ch, "{gPermission : {W%s", i3perm_names[cmd->level].name); i3printlnf (ch, "{gFunction : {W%s", i3_funcname (cmd->function)); i3printlnf (ch, "{gConnection Req: {W%s", cmd->connected ? "Yes" : "No"); if (cmd->alias_first) { int col = 0; strlcpy (buf, "{gAliases : {W", sizeof (buf)); for (alias = cmd->alias_first; alias; alias = alias->next) { snprintf (buf + strlen (buf), sizeof (buf) - strlen (buf), "%s ", alias->name); if (++col % 10 == 0) strlcat (buf, "\n\r", sizeof (buf)); } if (col % 10 != 0) strlcat (buf, "\n\r", sizeof (buf)); i3print (ch, buf); } return; } if (NullStr (argument)) { i3println (ch, "Required argument missing."); i3_cedit (n_fun, ch, ""); return; } if (!str_cmp (option, "rename")) { i3printlnf (ch, "{gCommand {W%s {ghas been renamed to {W%s.", cmd->name, argument); free_string (cmd->name); cmd->name = str_dup (argument); rw_i3_cmds (act_write); return; } if (!str_cmp (option, "args")) { i3printlnf (ch, "{gCommand {W%s {garg list has been changed to {W%s.", cmd->name, argument); replace_str (&cmd->args, argument); rw_i3_cmds (act_write); return; } if (!str_cmp (option, "descr")) { i3printlnf (ch, "{gCommand {W%s {gdescription has been changed to {W%s.", cmd->name, argument); replace_str (&cmd->descr, argument); rw_i3_cmds (act_write); return; } if (!str_cmp (option, "code")) { cmd->function = i3_function (argument); if (cmd->function == NULL) i3printlnf (ch, "{gFunction {W%s {gdoes not exist - set to NULL.", argument); else i3printlnf (ch, "{gFunction set to {W%s.", argument); rw_i3_cmds (act_write); return; } if (!str_cmp (option, "perm") || !str_cmp (option, "permission")) { int permvalue = get_permvalue (argument); if (!i3check_permissions (ch, permvalue, cmd->level, false)) return; cmd->level = (i3perm_t) permvalue; i3printlnf (ch, "{gCommand {W%s {gpermission level has been changed to {W%s.", cmd->name, i3perm_names[permvalue].name); rw_i3_cmds (act_write); return; } i3_cedit (n_fun, ch, ""); return; } Do_Fun (I3_invis) { if (I3INVIS (ch)) { RemBit (ch->pcdata->i3chardata->i3flags, I3_INVIS); i3println (ch, "You are now i3visible."); } else { SetBit (ch->pcdata->i3chardata->i3flags, I3_INVIS); i3println (ch, "You are now i3invisible."); } return; } Do_Fun (I3_debug) { packetdebug = !packetdebug; if (packetdebug) i3println (ch, "Packet debugging enabled."); else i3println (ch, "Packet debugging disabled."); return; } Do_Fun (I3_send_user_req) { char user[MIL], mud[MIL]; char *ps; I3_MUD *pmud; if (NullStr (argument)) { i3println (ch, "{YQuery who at which mud?\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (!(ps = strchr (argument, '@'))) { i3println (ch, "{YYou should specify a person and a mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } ps[0] = '\0'; strlcpy (user, argument, MIL); strlcpy (mud, ps + 1, MIL); if (NullStr (user) || NullStr (mud)) { i3println (ch, "{YYou should specify a person and a mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (!(pmud = find_I3_mud_by_name (mud))) { i3println (ch, "{YNo such mud known.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (pmud->status >= 0) { i3printlnf (ch, "%s is marked as down.", pmud->name); return; } I3_send_chan_user_req (pmud->name, user); return; } void I3_process_channel_adminlist_reply (I3_HEADER * header, char *s) { char *ps = s, *next_ps; I3_CHANNEL *channel; CharData *ch; if ((ch = I3_find_user (header->target_username)) == NULL) { bugf ("I3_process_channel_adminlist_reply(): user %s not found.", header->target_username); return; } I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); if (!(channel = find_I3_channel_by_name (ps))) { bugf ("I3_process_channel_adminlist_reply(): Invalid local channel %s reply received.", ps); return; } i3printlnf (ch, "{RThe following muds are %s %s:" NEWLINE, channel->status == 0 ? "banned from" : "invited to", channel->local_name); ps = next_ps; I3_get_field (ps, &next_ps); ps += 2; while (1) { if (ps[0] == '}') { i3println (ch, "{YNo entries found."); return; } I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); i3printlnf (ch, "{Y%s", ps); ps = next_ps; if (ps[0] == '}') break; } return; } void I3_send_channel_adminlist (CharData * ch, const char *chan_name) { if (!I3_is_connected ()) return; I3_write_header ("chan-adminlist", I3_THISMUD, GetName (ch), I3_ROUTER_NAME, NULL); I3_write_buffer ("\""); I3_write_buffer (chan_name); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } void I3_send_channel_admin (CharData * ch, const char *chan_name, const char *list) { if (!I3_is_connected ()) return; I3_write_header ("channel-admin", I3_THISMUD, GetName (ch), I3_ROUTER_NAME, NULL); I3_write_buffer ("\""); I3_write_buffer (chan_name); I3_write_buffer ("\","); I3_write_buffer (list); I3_write_buffer ("})\r"); I3_send_packet (); return; } Do_Fun (I3_admin_channel) { I3_CHANNEL *channel = NULL; char arg1[MIL], arg2[MIL], buf[MSL]; if (NullStr (argument)) { i3println (ch, "Usage: i3adminchan <localchannel> <add|remove> <mudname>"); i3println (ch, "Usage: i3adminchan <localchannel> list"); return; } argument = first_arg (argument, arg1, false); argument = first_arg (argument, arg2, false); if (NullStr (arg1)) { I3_admin_channel (n_fun, ch, ""); return; } if (!(channel = find_I3_channel_by_localname (arg1))) { i3println (ch, "No such channel with that name here."); return; } if (NullStr (arg2)) { I3_admin_channel (n_fun, ch, ""); return; } if (!str_cmp (arg2, "list")) { I3_send_channel_adminlist (ch, channel->I3_name); i3println (ch, "Sending request for administrative list."); return; } if (NullStr (argument)) { I3_admin_channel (n_fun, ch, ""); return; } if (!str_cmp (arg2, "add")) { snprintf (buf, sizeof (buf), "({\"%s\",}),({}),", argument); I3_send_channel_admin (ch, channel->I3_name, buf); i3println (ch, "Sending administrative list addition."); return; } if (!str_cmp (arg2, "remove")) { snprintf (buf, sizeof (buf), "({}),({\"%s\",}),", argument); I3_send_channel_admin (ch, channel->I3_name, buf); i3println (ch, "Sending administrative list removal."); return; } I3_admin_channel (n_fun, ch, ""); return; } void I3_send_channel_add (CharData * ch, char *arg, int type) { if (!I3_is_connected ()) return; I3_write_header ("channel-add", I3_THISMUD, GetName (ch), I3_ROUTER_NAME, NULL); I3_write_buffer ("\""); I3_write_buffer (arg); I3_write_buffer ("\","); switch (type) { default: bug ("I3_send_channel_add: Illegal channel type!"); return; case 0: I3_write_buffer ("0,})\r"); break; case 1: I3_write_buffer ("1,})\r"); break; case 2: I3_write_buffer ("2,})\r"); break; } I3_send_packet (); return; } Do_Fun (I3_addchan) { I3_CHANNEL *channel; char arg[MIL], arg2[MIL], buf[MSL]; int type, x; argument = first_arg (argument, arg, false); argument = first_arg (argument, arg2, false); if (NullStr (argument) || NullStr (arg) || NullStr (arg2)) { i3print (ch, "Usage: i3addchan <channelname> <localname> <type>" NEWLINE); i3println (ch, "Channelname should be the name seen on 'chanlist all'"); i3println (ch, "Localname should be the local name you want it listed as."); i3print (ch, "Type can be one of the following:" NEWLINE); i3println (ch, "0: selectively banned"); i3println (ch, "1: selectively admitted"); i3println (ch, "2: filtered - valid for selectively admitted ONLY"); return; } if ((channel = find_I3_channel_by_name (arg)) != NULL) { i3printlnf (ch, "{R%s is already hosted by %s.", channel->I3_name, channel->host_mud); return; } if ((channel = find_I3_channel_by_localname (arg2)) != NULL) { i3printlnf (ch, "{RChannel %s@%s is already locally configured as %s.", channel->I3_name, channel->host_mud, channel->local_name); return; } if (!isdigit (argument[0])) { i3println (ch, "{RInvalid type. Must be numerical."); I3_addchan (n_fun, ch, ""); return; } type = atoi (argument); if (type < 0 || type > 2) { i3println (ch, "{RInvalid channel type."); I3_addchan (n_fun, ch, ""); return; } i3printlnf (ch, "{GAdding channel to router: {W%s", arg); I3_send_channel_add (ch, arg, type); channel = new_I3chan (); channel->I3_name = str_dup (arg); channel->host_mud = str_dup (I3_THISMUD); channel->local_name = str_dup (arg2); channel->i3perm = I3PERM_ADMIN; channel->layout_m = str_dup ("{R[{W%s{R] {C%s@%s: {c%s"); channel->layout_e = str_dup ("{R[{W%s{R] {c%s"); for (x = 0; x < MAX_I3HISTORY; x++) channel->history[x] = NULL; Link (channel, I3chan, next, prev); if (type != 0) { snprintf (buf, sizeof (buf), "({\"%s\",}),({}),", I3_THISMUD); I3_send_channel_admin (ch, channel->I3_name, buf); i3printlnf (ch, "{GSending command to add %s to the invite list.", I3_THISMUD); } i3printlnf (ch, "{Y%s@%s {Wis now locally known as {Y%s", channel->I3_name, channel->host_mud, channel->local_name); I3_send_channel_listen (channel, true); rw_i3_channels (act_write); return; } void I3_send_channel_remove (CharData * ch, I3_CHANNEL * channel) { if (!I3_is_connected ()) return; I3_write_header ("channel-remove", I3_THISMUD, GetName (ch), I3_ROUTER_NAME, NULL); I3_write_buffer ("\""); I3_write_buffer (channel->I3_name); I3_write_buffer ("\",})\r"); I3_send_packet (); return; } Do_Fun (I3_removechan) { I3_CHANNEL *channel = NULL; if (NullStr (argument)) { i3println (ch, "{YUsage: i3removechan <channel>"); i3println (ch, "{WChannelname should be the name seen on 'chanlist all'"); return; } if ((channel = find_I3_channel_by_name (argument)) == NULL) { i3println (ch, "{RNo channel by that name exists."); return; } if (str_cmp (channel->host_mud, I3_THISMUD)) { i3printlnf (ch, "{R%s does not host this channel and cannot remove it.", I3_THISMUD); return; } i3printlnf (ch, "{YRemoving channel from router: {W%s", channel->I3_name); I3_send_channel_remove (ch, channel); i3printlnf (ch, "{RDestroying local channel entry for {W%s", channel->I3_name); destroy_I3_channel (channel); rw_i3_channels (act_write); return; } Do_Fun (I3_setconfig) { char arg[MIL]; argument = first_arg (argument, arg, false); if (NullStr (arg)) { i3println (ch, "{GConfiguration info for your mud. Changes save when edited."); i3print (ch, "{GYou can set the following:" NEWLINE); i3println (ch, "{wShow : {GDisplays your current congfiguration."); i3println (ch, "{wAutoconnect: {GA toggle. Either on or off. Your mud will connect automatically with it on."); i3println (ch, "{wMudname : {GThe name you want displayed on I3 for your mud."); i3println (ch, "{wTelnet : {GThe telnet address for your mud. Do not include the port number."); i3println (ch, "{wWeb : {GThe website address for your mud. In the form of: www.address.com"); i3println (ch, "{wEmail : {GThe email address of your mud's administrator. Needs to be valid!!"); i3println (ch, "{wStatus : {GThe open status of your mud. IE: Public, Development, etc."); i3println (ch, "{wMudtype : {GWhat type of mud you have. Diku, Rom, Smaug, Merc, etc."); i3println (ch, "{wBaselib : {GThe base version of the codebase you have."); i3println (ch, "{wMudlib : {GWhat you call the current version of your codebase."); i3println (ch, "{wMinlevel : {GMinimum level at which I3 will recognize your players."); i3println (ch, "{wImmlevel : {GThe level at which immortal commands become available."); i3println (ch, "{wAdminlevel : {GThe level at which administrative commands become available."); i3println (ch, "{wImplevel : {GThe level at which implementor commands become available."); return; } if (!str_cmp (arg, "show")) { i3printlnf (ch, "{wMudname {R: {G%s", i3mud_info.name); i3printlnf (ch, "{wAutoconnect : {G%s", i3mud_info.autoconnect == true ? "Enabled" : "Disabled"); i3printlnf (ch, "{wTelnet : {G%s:%d", i3mud_info.telnet, i3mud_info.player_port); #ifndef DISABLE_WEBSRV if (web_is_connected ()) i3printlnf (ch, "{wWeb : {G%s:%d", i3mud_info.web, webport); else #endif i3printlnf (ch, "{wWeb : {G%s", i3mud_info.web); i3printlnf (ch, "{wEmail : {G%s", i3mud_info.admin_email); i3printlnf (ch, "{wStatus : {G%s", i3mud_info.open_status); i3printlnf (ch, "{wMudtype : {G%s", i3mud_info.mud_type); i3printlnf (ch, "{wBaselib {R: {G%s", i3mud_info.base_mudlib); i3printlnf (ch, "{wMudlib : {G%s", i3mud_info.mudlib); i3printlnf (ch, "{wMinlevel : {G%d", i3mud_info.minlevel); i3printlnf (ch, "{wImmlevel : {G%d", i3mud_info.immlevel); i3printlnf (ch, "{wAdminlevel : {G%d", i3mud_info.adminlevel); i3printlnf (ch, "{wImplevel : {G%d", i3mud_info.implevel); return; } if (!str_cmp (arg, "autoconnect")) { i3mud_info.autoconnect = !i3mud_info.autoconnect; if (i3mud_info.autoconnect) i3println (ch, "Autoconnect enabled."); else i3println (ch, "Autoconnect disabled."); rw_i3_config (act_write); return; } if (NullStr (argument)) { I3_setconfig (n_fun, ch, ""); return; } if (!str_cmp (arg, "implevel") && ch->pcdata->i3chardata->i3perm == I3PERM_IMP) { int value = atoi (argument); i3mud_info.implevel = value; rw_i3_config (act_write); i3printlnf (ch, "Implementor level changed to %d", value); return; } if (!str_cmp (arg, "adminlevel")) { int value = atoi (argument); i3mud_info.adminlevel = value; rw_i3_config (act_write); i3printlnf (ch, "Admin level changed to %d", value); return; } if (!str_cmp (arg, "immlevel")) { int value = atoi (argument); i3mud_info.immlevel = value; rw_i3_config (act_write); i3printlnf (ch, "Immortal level changed to %d", value); return; } if (!str_cmp (arg, "minlevel")) { int value = atoi (argument); i3mud_info.minlevel = value; rw_i3_config (act_write); i3printlnf (ch, "Minimum level changed to %d", value); return; } if (I3_is_connected ()) { i3printlnf (ch, "%s may not be changed while the mud is connected.", arg); return; } if (!str_cmp (arg, "telnet")) { replace_str (&i3mud_info.telnet, argument); rw_i3_config (act_write); i3printlnf (ch, "Telnet address changed to %s:%d", argument, i3mud_info.player_port); return; } if (!str_cmp (arg, "web")) { replace_str (&i3mud_info.web, argument); rw_i3_config (act_write); i3printlnf (ch, "Website changed to %s", argument); return; } if (!str_cmp (arg, "email")) { replace_str (&i3mud_info.admin_email, argument); rw_i3_config (act_write); i3printlnf (ch, "Admin email changed to %s", argument); return; } if (!str_cmp (arg, "status")) { replace_str (&i3mud_info.open_status, argument); rw_i3_config (act_write); i3printlnf (ch, "Status changed to %s", argument); return; } if (!str_cmp (arg, "mudtype")) { replace_str (&i3mud_info.mud_type, argument); rw_i3_config (act_write); i3printlnf (ch, "Mud type changed to %s", argument); return; } if (!str_cmp (arg, "mudlib")) { replace_str (&i3mud_info.mudlib, argument); rw_i3_config (act_write); i3printlnf (ch, "Mudlib changed to %s", argument); return; } I3_setconfig (n_fun, ch, ""); return; } Do_Fun (I3_permstats) { CharData *victim; if (NullStr (argument)) { i3println (ch, "Usage: i3perms <user>"); return; } if (!(victim = I3_find_user (argument))) { i3println (ch, "No such person is currently online."); return; } if (victim->pcdata->i3chardata->i3perm < 0 || victim->pcdata->i3chardata->i3perm > I3PERM_IMP) { i3printlnf (ch, "{R%s has an invalid permission setting!", GetName (victim)); return; } i3printlnf (ch, "{YPermissions for %s: %s", GetName (victim), i3perm_names[victim->pcdata->i3chardata->i3perm].name); i3printlnf (ch, "{gThese permissions were obtained %s.", IsSet (victim->pcdata->i3chardata->i3flags, I3_PERMOVERRIDE) ? "manually via i3permset" : "automatically by level"); return; } bool i3check_permissions (CharData * ch, int checkvalue, int targetvalue, bool enforceequal) { if (checkvalue < 0 || checkvalue > I3PERM_IMP) { i3println (ch, "Invalid permission setting."); return false; } if (checkvalue > ch->pcdata->i3chardata->i3perm) { i3println (ch, "You cannot set permissions higher than your own."); return false; } if (checkvalue == ch->pcdata->i3chardata->i3perm && ch->pcdata->i3chardata->i3perm != I3PERM_IMP && enforceequal) { i3println (ch, "You cannot set permissions equal to your own. Someone higher up must do this."); return false; } if (ch->pcdata->i3chardata->i3perm < targetvalue) { i3println (ch, "You cannot alter the permissions of someone or something above your own."); return false; } return true; } Do_Fun (I3_permset) { CharData *victim; char arg[MIL]; int permvalue; argument = first_arg (argument, arg, false); if (NullStr (arg)) { i3println (ch, "Usage: i3permset <user> <permission>"); i3println (ch, "Permission can be one of: None, Mort, Imm, Admin, Imp"); return; } if (!(victim = I3_find_user (arg))) { i3println (ch, "No such person is currently online."); return; } if (!str_cmp (argument, "override")) permvalue = -1; else { permvalue = get_permvalue (argument); if (!i3check_permissions (ch, permvalue, victim->pcdata->i3chardata->i3perm, true)) return; } if (victim->pcdata->i3chardata->i3perm == permvalue) { i3printlnf (ch, "%s already has a permission level of %s.", GetName (victim), i3perm_names[permvalue].name); return; } if (permvalue == -1) { RemBit (victim->pcdata->i3chardata->i3flags, I3_PERMOVERRIDE); i3printlnf (ch, "{YPermission flag override has been removed from %s", GetName (victim)); return; } victim->pcdata->i3chardata->i3perm = (i3perm_t) permvalue; i3printlnf (ch, "{YPermission level for %s has been changed to %s", GetName (victim), i3perm_names[permvalue].name); if (victim->pcdata->i3chardata->i3_listen != NULL) { I3_CHANNEL *channel = NULL; const char *channels = victim->pcdata->i3chardata->i3_listen; while (1) { if (channels[0] == '\0') break; channels = one_argument (channels, arg); if (!(channel = find_I3_channel_by_localname (arg))) unflagname (&victim->pcdata->i3chardata->i3_listen, arg); if (channel && victim->pcdata->i3chardata->i3perm < channel->i3perm) { unflagname (&victim->pcdata->i3chardata->i3_listen, arg); i3printlnf (ch, "{WRemoving '%s' level channel: '%s', exceeding new permission of '%s'", i3perm_names[channel->i3perm].name, channel->local_name, i3perm_names[victim->pcdata->i3chardata->i3perm]. name); } } } return; } Do_Fun (I3_who) { I3_MUD *mud; if (NullStr (argument)) { i3println (ch, "{YGet an overview of which mud?\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (!(mud = find_I3_mud_by_name (argument))) { i3println (ch, "{YNo such mud known.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (mud->status >= 0) { i3printlnf (ch, "%s is marked as down.", mud->name); return; } if (mud->who == 0) i3printlnf (ch, "%s does not support the 'who' command. Sending anyway.", mud->name); I3_send_who (ch, mud->name); } Do_Fun (I3_locate) { if (NullStr (argument)) { i3println (ch, "Locate who?"); return; } I3_send_locate (ch, argument); } Do_Fun (I3_finger) { char user[MIL], mud[MIL]; char *ps; I3_MUD *pmud; if (IsSet (ch->pcdata->i3chardata->i3flags, I3_DENYFINGER)) { i3println (ch, "You are not allowed to use i3finger."); return; } if (NullStr (argument)) { i3println (ch, "Usage: i3finger <user@mud>"); i3println (ch, "Usage: i3finger privacy"); return; } if (!str_cmp (argument, "privacy")) { if (!IsSet (ch->pcdata->i3chardata->i3flags, I3_PRIVACY)) { SetBit (ch->pcdata->i3chardata->i3flags, I3_PRIVACY); i3println (ch, "I3 finger privacy flag set."); return; } RemBit (ch->pcdata->i3chardata->i3flags, I3_PRIVACY); i3println (ch, "I3 finger privacy flag removed."); return; } if (I3ISINVIS (ch)) { i3println (ch, "You are invisible."); return; } if ((ps = strchr (argument, '@')) == NULL) { i3println (ch, "{YYou should specify a person and a mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } ps[0] = '\0'; strlcpy (user, argument, MIL); strlcpy (mud, ps + 1, MIL); if (user[0] == '\0' || mud[0] == '\0') { i3println (ch, "{YYou should specify a person and a mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (!(pmud = find_I3_mud_by_name (mud))) { i3println (ch, "{YNo such mud known.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (!str_cmp (I3_THISMUD, pmud->name)) { i3println (ch, "Use your mud's own internal system for that."); return; } if (pmud->status >= 0) { i3printlnf (ch, "%s is marked as down.", pmud->name); return; } if (pmud->finger == 0) i3printlnf (ch, "%s does not support the 'finger' command. Sending anyway.", pmud->name); I3_send_finger (ch, user, pmud->name); } Do_Fun (I3_emote) { char to[MIL], *ps; char mud[MIL]; I3_MUD *pmud; if (I3ISINVIS (ch)) { i3println (ch, "You are invisible."); return; } argument = first_arg (argument, to, false); ps = strchr (to, '@'); if (to[0] == '\0' || argument[0] == '\0' || ps == NULL) { i3println (ch, "{YYou should specify a person and a mud.\n\r" "(use {Wi3mudlist{Y to get an overview of the muds available)"); return; } ps[0] = '\0'; ps++; strlcpy (mud, ps, MIL); if (!(pmud = find_I3_mud_by_name (mud))) { i3println (ch, "{YNo such mud known.\n\r" "( use {Wi3mudlist{Y to get an overview of the muds available)"); return; } if (pmud->status >= 0) { i3printlnf (ch, "%s is marked as down.", pmud->name); return; } if (pmud->emoteto == 0) i3printlnf (ch, "%s does not support the 'emoteto' command. Sending anyway.", pmud->name); I3_send_emoteto (ch, to, pmud, argument); } SOCKET I3_connection_open (ROUTER_DATA * router) { struct sockaddr_in sa; new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Attempting connect to %s on port %d", router->ip, router->port); I3_control = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); if (I3_control == INVALID_SOCKET) { socket_error ("Cannot create socket!"); I3_connection_close (true); return INVALID_SOCKET; } if (!socket_cntl (I3_control)) { log_string ("I3_connection_open: fcntl(F_SETFL)"); I3_connection_close (true); return INVALID_SOCKET; } memset (&sa, 0, sizeof (sa)); sa.sin_family = AF_INET; if (!inet_aton (router->ip, &sa.sin_addr)) { struct hostent *hostp = gethostbyname (router->ip); if (!hostp) { log_string ("I3_connection_open: Cannot resolve router hostname."); I3_connection_close (true); return INVALID_SOCKET; } memcpy (&sa.sin_addr, hostp->h_addr, hostp->h_length); } sa.sin_port = htons (router->port); if (connect (I3_control, (SOCKADDR *) & sa, sizeof (sa)) == SOCKET_ERROR) { if (!check_errno (EINPROGRESS)) { socket_error (FORMATF ("I3_connection_open: Unable to connect to router %s", router->name)); I3_connection_close (true); return INVALID_SOCKET; } } I3_ROUTER_NAME = router->name; new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Connected to Intermud-3 router %s", router->name); return I3_control; } bool i3banned (const char *ignore) { I3_BAN *temp; I3_MUD *mud; char *ps; char mudname[MIL], ipbuf[512]; for (temp = I3ban_first; temp; temp = temp->next) { if (!fnmatch (temp->name, ignore, 0)) return true; } ps = strchr (ignore, '@'); if (NullStr (ignore) || ps == NULL) return false; ps[0] = '\0'; strlcpy (mudname, ps + 1, MIL); for (mud = i3mud_first; mud; mud = mud->next) { if (!str_cmp (mud->name, mudname)) { snprintf (ipbuf, sizeof (ipbuf), "%s:%d", mud->ipaddress, mud->player_port); for (temp = I3ban_first; temp; temp = temp->next) { if (!str_cmp (temp->name, ipbuf)) return true; } } } return false; } I3_HEADER * I3_get_header (char **pps) { I3_HEADER *header; char *ps = *pps, *next_ps; alloc_mem (header, I3_HEADER, 1); I3_get_field (ps, &next_ps); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (header->originator_mudname, ps, 256); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (header->originator_username, ps, 256); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (header->target_mudname, ps, 256); ps = next_ps; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (header->target_username, ps, 256); *pps = next_ps; return header; } void I3_read_packet (void) { long size; memmove (&size, I3_input_buffer, 4); size = ntohl (size); memmove (I3_currentpacket, I3_input_buffer + 4, size); if (I3_currentpacket[size - 1] != ')') I3_currentpacket[size - 1] = 0; I3_currentpacket[size] = 0; memmove (I3_input_buffer, I3_input_buffer + size + 4, I3_input_pointer - size - 4); I3_input_pointer -= size + 4; return; } void I3_parse_packet (void) { I3_HEADER *header = NULL; char *ps, *next_ps; char ptype[MIL]; ps = I3_currentpacket; if (ps[0] != '(' || ps[1] != '{') return; if (packetdebug) logf ("Packet received: %s", ps); ps += 2; I3_get_field (ps, &next_ps); I3_remove_quotes (&ps); strlcpy (ptype, ps, MIL); header = I3_get_header (&ps); if (i3banned (header->originator_mudname)) return; if (!str_cmp (ptype, "tell")) I3_process_tell (header, ps); if (!str_cmp (ptype, "beep")) I3_process_beep (header, ps); if (!str_cmp (ptype, "emoteto")) I3_process_emoteto (header, ps); if (!str_cmp (ptype, "channel-m")) I3_process_channel_m (header, ps); if (!str_cmp (ptype, "channel-e")) I3_process_channel_e (header, ps); if (!str_cmp (ptype, "chan-filter-req")) I3_process_channel_filter (header, ps); if (!str_cmp (ptype, "finger-req")) I3_process_finger_req (header, ps); if (!str_cmp (ptype, "finger-reply")) I3_process_finger_reply (header, ps); if (!str_cmp (ptype, "locate-req")) I3_process_locate_req (header, ps); if (!str_cmp (ptype, "locate-reply")) I3_process_locate_reply (header, ps); if (!str_cmp (ptype, "chan-who-req")) I3_process_chan_who_req (header, ps); if (!str_cmp (ptype, "chan-who-reply")) I3_process_chan_who_reply (header, ps); if (!str_cmp (ptype, "chan-adminlist-reply")) I3_process_channel_adminlist_reply (header, ps); if (!str_cmp (ptype, "ucache-update") && i3mud_info.ucache == true) I3_process_ucache_update (header, ps); if (!str_cmp (ptype, "who-req")) I3_process_who_req (header, ps); if (!str_cmp (ptype, "who-reply")) I3_process_who_reply (header, ps); if (!str_cmp (ptype, "chanlist-reply")) I3_process_chanlist_reply (header, ps); if (!str_cmp (ptype, "startup-reply")) I3_process_startup_reply (header, ps); if (!str_cmp (ptype, "mudlist")) I3_process_mudlist (header, ps); if (!str_cmp (ptype, "error")) I3_process_error (header, ps); if (!str_cmp (ptype, "chan-ack")) I3_process_chanack (header, ps); if (!str_cmp (ptype, "channel-t")) I3_process_channel_t (header, ps); if (!str_cmp (ptype, "chan-user-req")) I3_process_chan_user_req (header, ps); if (!str_cmp (ptype, "chan-user-reply") && i3mud_info.ucache == true) I3_process_chan_user_reply (header, ps); if (!str_cmp (ptype, "router-shutdown")) { int delay; I3_get_field (ps, &next_ps); delay = atoi (ps); if (delay == 0) { new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Router %s is shutting down.", I3_ROUTER_NAME); I3_connection_close (false); } else { new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Router %s is rebooting and will be back in %d second%s.", I3_ROUTER_NAME, delay, delay == 1 ? "" : "s"); I3_connection_close (true); } } free_mem (header); return; } I3_MUD * new_i3mud (void) { I3_MUD *Data; alloc_mem (Data, I3_MUD, 1); return Data; } TableSave_Fun (rw_i3_mudlist) { rw_list (type, I3_MUDLIST_FILE, I3_MUD, i3mud); if (type == act_read) unlink (I3_MUDLIST_FILE); } TableSave_Fun (rw_i3_chanlist) { rw_list (type, I3_CHANLIST_FILE, I3_CHANNEL, I3chan); if (type == act_read) { unlink (I3_CHANLIST_FILE); init_i3_channels (); } } void I3_loadhistory (void) { char filename[256]; FileData *tempfile; I3_CHANNEL *tempchan = NULL; int x; for (tempchan = I3chan_first; tempchan; tempchan = tempchan->next) { if (!tempchan->local_name) continue; snprintf (filename, sizeof (filename), I3DIR "%s.hist", tempchan->local_name); if (!(tempfile = f_open (filename, "r"))) continue; for (x = 0; x < MAX_I3HISTORY; x++) { if (f_eof (tempfile)) tempchan->history[x] = NULL; else tempchan->history[x] = str_dup (read_line (tempfile)); } f_close (tempfile); unlink (filename); } } void I3_savehistory (void) { char filename[256]; FileData *tempfile; I3_CHANNEL *tempchan = NULL; int x; for (tempchan = I3chan_first; tempchan; tempchan = tempchan->next) { if (!tempchan->local_name) continue; if (!tempchan->history[0]) continue; snprintf (filename, sizeof (filename), I3DIR "%s.hist", tempchan->local_name); if (!(tempfile = f_open (filename, "w"))) continue; for (x = 0; x < MAX_I3HISTORY; x++) { if (tempchan->history[x] != NULL) f_printf (tempfile, "%s", tempchan->history[x]); } f_close (tempfile); } } void router_connect (const char *router_name, bool forced, int mudport, bool isconnected) { ROUTER_DATA *router; bool rfound = false; i3wait = 0; i3timeout = 0; bytes_sent = 0; bytes_received = 0; manual_router = router_name; if (i3cmd_first == NULL) { rw_i3_cmds (act_read); if (!i3cmd_first) { wiznet ("router_connect: Unable to load command table!", NULL, NULL, WIZ_I3, true, 1); I3_control = INVALID_SOCKET; return; } } if (!I3_read_config (mudport)) { I3_control = INVALID_SOCKET; return; } if (router_first == NULL) { rw_i3_routers (act_read); if (!router_first) { wiznet ("router_connect: No router configurations were found!", NULL, NULL, WIZ_I3, true, 1); I3_control = INVALID_SOCKET; return; } I3_ROUTER_NAME = router_first->name; } if (i3help_first == NULL) rw_i3_helps (act_read); if (i3color_first == NULL) rw_i3_colors (act_read); if ((!i3mud_info.autoconnect && !forced && !isconnected) || (isconnected && I3_control == INVALID_SOCKET)) { wiznet ("Intermud-3 network data loaded. Autoconnect not set. Will need to connect manually.", NULL, NULL, WIZ_I3, true, 1); I3_control = INVALID_SOCKET; return; } else wiznet ("Intermud-3 network data loaded. Initialiazing network connection...", NULL, NULL, WIZ_I3, true, 1); rw_i3_bans (act_read); if (i3mud_info.ucache == true) { rw_i3_ucache (act_read); I3_prune_ucache (); ucache_clock = current_time + (HOUR * 24); } if (I3_control == INVALID_SOCKET) { for (router = router_first; router; router = router->next) { if (router_name && str_cmp (router_name, router->name)) continue; if (router->reconattempts <= 3) { rfound = true; I3_control = I3_connection_open (router); break; } } } if (!rfound && !isconnected) { wiznet ("Unable to connect. No available routers found.", NULL, NULL, WIZ_I3, true, 1); I3_control = INVALID_SOCKET; return; } if (I3_control == INVALID_SOCKET) { i3wait = 100; return; } sleep_seconds (1); wiznet ("Intermud-3 Network initialized.", NULL, NULL, WIZ_I3, true, 1); if (!isconnected) { rw_i3_channels (act_read); I3_startup_packet (); i3timeout = 100; } else { rw_i3_mudlist (act_read); rw_i3_chanlist (act_read); } I3_loadhistory (); } Do_Fun (I3_connect) { ROUTER_DATA *router; if (I3_is_connected ()) { i3printlnf (ch, "The MUD is already connected to Intermud-3 router %s", I3_ROUTER_NAME); return; } if (NullStr (argument)) { i3print (ch, "Connecting to Intermud-3... "); router_connect (NULL, true, i3mud_info.player_port, false); if (I3_is_connected ()) i3println (ch, "Success."); else i3println (ch, "Failed."); return; } for (router = router_first; router; router = router->next) { if (!str_cmp (router->name, argument)) { router->reconattempts = 0; i3printf (ch, "Connecting to Intermud-3 router %s...", argument); router_connect (argument, true, i3mud_info.player_port, false); if (I3_is_connected ()) i3println (ch, "Success."); else i3println (ch, "Failed."); return; } } i3printlnf (ch, "%s is not configured as a router for this mud.", argument); i3println (ch, "If you wish to add it, use the i3router command to provide its information."); return; } void I3_main (bool isconnected) { router_connect (NULL, false, mainport, isconnected); } void I3_send_shutdown (int delay) { I3_CHANNEL *channel; char s[50]; if (!I3_is_connected ()) return; for (channel = I3chan_first; channel; channel = channel->next) { if (!NullStr (channel->local_name)) I3_send_channel_listen (channel, false); } I3_write_header ("shutdown", I3_THISMUD, NULL, I3_ROUTER_NAME, NULL); snprintf (s, sizeof (s), "%d", delay); I3_write_buffer (s); I3_write_buffer (",})\r"); if (!I3_write_packet (I3_output_buffer)) I3_connection_close (false); return; } void I3_loop (void) { ROUTER_DATA *router; int ret; long size; fd_set in_set, out_set, exc_set; static struct timeval null_time; bool rfound = false; FD_ZERO (&in_set); FD_ZERO (&out_set); FD_ZERO (&exc_set); if (i3wait > 0) i3wait--; if (i3timeout > 0) { i3timeout--; if (i3timeout == 0) { I3_connection_close (true); return; } } if (i3wait == 1) { for (router = router_first; router; router = router->next) { if (manual_router && str_cmp (router->name, manual_router)) continue; if (router->reconattempts <= 3) { rfound = true; break; } } if (!rfound) { i3wait = -2; wiznet ("Unable to reconnect. No routers responding.", NULL, NULL, WIZ_I3, true, 1); ; return; } I3_control = I3_connection_open (router); if (I3_control == INVALID_SOCKET) { if (router->reconattempts <= 3) i3wait = 100; return; } sleep_seconds (1); new_wiznet (NULL, NULL, WIZ_I3, true, 1, "Connection to Intermud-3 router %s %s.", router->name, router->reconattempts > 0 ? "reestablished" : "established"); router->reconattempts++; I3_startup_packet (); i3timeout = 100; return; } if (!I3_is_connected ()) return; if (ucache_clock <= current_time) { ucache_clock = current_time + (HOUR * 24); I3_prune_ucache (); } FD_SET (I3_control, &in_set); FD_SET (I3_control, &out_set); FD_SET (I3_control, &exc_set); if (select (I3_control + 1, &in_set, &out_set, &exc_set, &null_time) == SOCKET_ERROR) { socket_error ("I3_loop: select: Unable to poll I3_control!"); I3_connection_close (true); return; } if (FD_ISSET (I3_control, &exc_set)) { FD_CLR (I3_control, &in_set); FD_CLR (I3_control, &out_set); log_string ("Exception raised on socket."); I3_connection_close (true); return; } if (FD_ISSET (I3_control, &in_set)) { ret = recv (I3_control, I3_input_buffer + I3_input_pointer, MSL, 0); if (!ret || (ret < 0 && !check_errno (EWOULDBLOCK) #ifndef WIN32 && !check_errno (EAGAIN) #endif )) { FD_CLR (I3_control, &out_set); if (ret < 0) log_string ("Read error on socket."); else log_string ("EOF encountered on socket read."); I3_connection_close (true); return; } if (ret < 0) return; I3_input_pointer += ret; bytes_received += ret; if (packetdebug) logf ("Bytes received: %d", ret); } memcpy (&size, I3_input_buffer, 4); size = ntohl (size); if (size <= I3_input_pointer - 4) { I3_read_packet (); I3_parse_packet (); } return; } void I3_shutdown (int delay) { if (I3_control == INVALID_SOCKET || crs_info.status == CRS_COPYOVER) return; I3_savehistory (); free_i3data (false); if (I3_output_pointer != 4) I3_write_packet (I3_output_buffer); I3_send_shutdown (delay); I3_connection_close (false); I3_input_pointer = 0; I3_output_pointer = 4; sleep_seconds (2); } char * I3_find_social (CharData * ch, char *sname, const char *person, const char *mud, bool victim) { static char socname[MSL]; SocialData *social; char *c; socname[0] = '\0'; for (c = sname; *c; *c = tolower (*c), c++) ; if ((social = find_social (sname)) == NULL) { i3printlnf (ch, "{YSocial {W%s{Y does not exist on this mud.", sname); return socname; } if (NullStr (person) && NullStr (mud)) { if (NullStr (person) && !str_cmp (person, GetName (ch)) && NullStr (mud) && !str_cmp (mud, I3_THISMUD)) { if (!social->others_auto) { i3printlnf (ch, "{YSocial {W%s{Y: Missing others_auto.", social->name); return socname; } strlcpy (socname, social->others_auto, MSL); } else { if (!victim) { if (!social->others_found) { i3printlnf (ch, "{YSocial {W%s{Y: Missing others_found.", social->name); return socname; } strlcpy (socname, social->others_found, MSL); } else { if (!social->vict_found) { i3printlnf (ch, "{YSocial {W%s{Y: Missing vict_found.", social->name); return socname; } strlcpy (socname, social->vict_found, MSL); } } } else { if (!social->others_no_arg) { i3printlnf (ch, "{YSocial {W%s{Y: Missing others_no_arg.", social->name); return socname; } strlcpy (socname, social->others_no_arg, MSL); } return socname; } CharData * I3_make_skeleton (const char *name) { CharData *skeleton; alloc_mem (skeleton, CharData, 1); skeleton->name = str_dup (name); skeleton->short_descr = str_dup (name); skeleton->in_room = get_room_index (ROOM_VNUM_LIMBO); return skeleton; } void I3_purge_skeleton (CharData * skeleton) { if (!skeleton) return; free_string (skeleton->name); free_string (skeleton->short_descr); free_mem (skeleton); return; } void I3_send_social (I3_CHANNEL * channel, CharData * ch, const char *argument) { CharData *skeleton = NULL; char *ps; char socbuf_o[MSL], socbuf_t[MSL], msg_o[MSL], msg_t[MSL]; char arg1[MIL], person[MIL], mud[MIL], user[MIL], buf[MSL]; unsigned int x; person[0] = '\0'; mud[0] = '\0'; argument = first_arg (argument, arg1, false); snprintf (user, sizeof (user), "%s@%s", GetName (ch), I3_THISMUD); if (!str_cmp (user, argument)) { i3println (ch, "Cannot target yourself due to the nature of I3 socials."); return; } if (!NullStr (argument)) { if (!(ps = strchr (argument, '@'))) { i3println (ch, "You need to specify a person@mud for a target."); return; } else { for (x = 0; x < strlen (argument); x++) { person[x] = argument[x]; if (person[x] == '@') break; } person[x] = '\0'; ps[0] = '\0'; strlcpy (mud, ps + 1, MIL); } } snprintf (socbuf_o, sizeof (socbuf_o), "%s", I3_find_social (ch, arg1, person, mud, false)); if (NullStr (socbuf_o)) snprintf (socbuf_t, sizeof (socbuf_t), "%s", I3_find_social (ch, arg1, person, mud, true)); if (!NullStr (socbuf_o) && !NullStr (socbuf_t)) { if (!NullStr (argument)) { sex_t sex; snprintf (buf, sizeof (buf), "%s@%s", person, mud); sex = I3_get_ucache_gender (buf); if (sex == -1) { I3_send_chan_user_req (mud, person); sex = SEX_MALE; } else sex = i3todikugender (sex); skeleton = I3_make_skeleton (buf); skeleton->sex = sex; } strlcpy (msg_o, perform_act_string (socbuf_o, ch, NULL, skeleton, false), MSL); strlcpy (msg_t, perform_act_string (socbuf_t, ch, NULL, skeleton, false), MSL); if (!skeleton) I3_send_channel_emote (channel, GetName (ch), msg_o); else { strlcpy (buf, person, MSL); buf[0] = tolower (buf[0]); I3_send_channel_t (channel, GetName (ch), mud, buf, msg_o, msg_t, person); } if (skeleton) I3_purge_skeleton (skeleton); } return; } Do_Fun (I3_router) { ROUTER_DATA *router; char cmd[MIL]; if (NullStr (argument)) { i3println (ch, "Usage: i3router add <router_name> <router_ip> <router_port>"); i3println (ch, "Usage: i3router remove <router_name>"); i3println (ch, "Usage: i3router list"); return; } argument = first_arg (argument, cmd, false); if (!str_cmp (cmd, "list")) { i3println (ch, "{RThe mud has the following routers configured:"); i3println (ch, "{WRouter Name Router IP/DNS Router Port"); for (router = router_first; router; router = router->next) i3printlnf (ch, "{c%-15.15s{c %-30.30s %d", router->name, router->ip, router->port); return; } if (NullStr (argument)) { I3_router (n_fun, ch, ""); return; } if (!str_cmp (cmd, "remove")) { for (router = router_first; router; router = router->next) { if (!str_cmp (router->name, argument) || !str_cmp (router->ip, argument)) { free_string (router->name); free_string (router->ip); UnLink (router, router, next, prev); free_mem (router); i3printlnf (ch, "{YRouter {W%s{Y has been removed from your configuration.", argument); rw_i3_config (act_write); return; } } i3printlnf (ch, "{YNo router named {W%s{Y exists in your configuration.", argument); return; } if (!str_cmp (cmd, "add")) { ROUTER_DATA *temp; char rtname[MIL]; char rtip[MIL]; int rtport; argument = first_arg (argument, rtname, false); argument = first_arg (argument, rtip, false); if (NullStr (rtname) || NullStr (rtip) || NullStr (argument)) { I3_router (n_fun, ch, ""); return; } if (rtname[0] != '*') { i3println (ch, "{YA router name must begin with a {W*{Y to be valid."); return; } for (temp = router_first; temp; temp = temp->next) { if (!str_cmp (temp->name, rtname)) { i3printlnf (ch, "{YA router named {W%s{Y is already in your configuration.", rtname); return; } } if (!is_number (argument)) { i3println (ch, "{YPort must be a numerical value."); return; } rtport = atoi (argument); if (rtport < 1 || rtport > 65535) { i3println (ch, "{YInvalid port value specified."); return; } alloc_mem (router, ROUTER_DATA, 1); Link (router, router, next, prev); router->name = str_dup (rtname); router->ip = str_dup (rtip); router->port = rtport; router->reconattempts = 0; i3printlnf (ch, "{YRouter: {W%s %s %d{Y has been added to your configuration.", router->name, router->ip, router->port); rw_i3_config (act_write); return; } I3_router (n_fun, ch, ""); return; } Do_Fun (I3_stats) { I3_MUD *mud; I3_CHANNEL *channel; int mud_count = 0, chan_count = 0; for (mud = i3mud_first; mud; mud = mud->next) mud_count++; for (channel = I3chan_first; channel; channel = channel->next) chan_count++; i3print (ch, "{cGeneral Statistics:" NEWLINE); i3printlnf (ch, "{cCurrently connected to: {W%s", I3_is_connected ()? I3_ROUTER_NAME : "Nowhere!"); i3printlnf (ch, "{cBytes sent : {W%ld", bytes_sent); i3printlnf (ch, "{cBytes received: {W%ld", bytes_received); i3printlnf (ch, "{cKnown muds : {W%d", mud_count); i3printlnf (ch, "{cKnown channels: {W%d", chan_count); return; } Do_Fun (i3_help) { I3_HELP_DATA *help; Buffer *buf; int col, perm; if (NullStr (argument)) { buf = new_buf (); i3bprintln (buf, "{gHelp is available for the following commands:"); i3bprintln (buf, "{G---------------------------------------------"); for (perm = I3PERM_MORT; perm <= ch->pcdata->i3chardata->i3perm; perm++) { col = 0; i3bprintlnf (buf, "\n\r{g%s helps:{G", i3perm_names[perm].name); for (help = i3help_first; help; help = help->next) { if (help->level != perm) continue; i3bprintf (buf, "%-15s", help->name); if (++col % 6 == 0) i3bprintln (buf, ""); } if (col % 6 != 0) i3bprintln (buf, ""); } sendpage (ch, buf_string (buf)); return; } for (help = i3help_first; help; help = help->next) { if (!str_cmp (help->name, argument)) { if (NullStr (help->text)) i3printlnf (ch, "{gNo inforation available for topic {W%s{g.", help->name); else i3printlnf (ch, "{g%s", help->text); return; } } i3printlnf (ch, "{gNo help exists for topic {W%s{g.", argument); return; } Do_Fun (i3_hedit) { I3_HELP_DATA *help; char name[MIL], cmd[MIL]; bool found = false; argument = one_argument (argument, name); argument = one_argument (argument, cmd); if (NullStr (name) || NullStr (cmd) || NullStr (argument)) { i3println (ch, "{wUsage: i3hedit <topic> [name|perm] <field>"); i3println (ch, "{wWhere <field> can be either name, or permission level."); return; } for (help = i3help_first; help; help = help->next) { if (!str_cmp (help->name, name)) { found = true; break; } } if (!found) { i3printlnf (ch, "{gNo help exists for topic {W%s{g. You will need to add it to the helpfile manually.", name); return; } if (!str_cmp (cmd, "name")) { i3printlnf (ch, "{W%s {ghas been renamed to {W%s.", help->name, argument); replace_str (&help->name, argument); rw_help_data (act_write); return; } if (!str_cmp (cmd, "perm")) { int permvalue = get_permvalue (argument); if (!i3check_permissions (ch, permvalue, help->level, false)) return; i3printlnf (ch, "{gPermission level for {W%s {ghas been changed to {W%s.", help->name, i3perm_names[permvalue].name); help->level = permvalue; rw_help_data (act_write); return; } i3_hedit (n_fun, ch, ""); return; } Do_Fun (I3_other) { I3_CMD_DATA *x; i3println (ch, "{GGeneral Usage:"); i3println (ch, draw_line (ch, "{W-{w-", 0)); for (x = i3cmd_first; x; x = x->next) { if (ch->pcdata->i3chardata->i3perm < x->level) continue; if (x->connected == false || I3_is_connected ()) { i3printlnf (ch, "{G%12s {g%-32s{w - %s", x->name, x->args, x->descr); } } i3println (ch, draw_line (ch, "{W-{w-", 0)); return; } const char * i3_funcname (Do_F * func) { if (func == I3_other) return ("I3_other"); if (func == I3_listen_channel) return ("I3_listen_channel"); if (func == I3_chanlist) return ("I3_chanlist"); if (func == I3_mudlist) return ("I3_mudlist"); if (func == I3_invis) return ("I3_invis"); if (func == I3_who) return ("I3_who"); if (func == I3_locate) return ("I3_locate"); if (func == I3_tell) return ("I3_tell"); if (func == I3_reply) return ("I3_reply"); if (func == I3_emote) return ("I3_emote"); if (func == I3_beep) return ("I3_beep"); if (func == I3_ignorecmd) return ("I3_ignorecmd"); if (func == I3_finger) return ("I3_finger"); if (func == I3_mudinfo) return ("I3_mudinfo"); if (func == I3_color) return ("I3_color"); if (func == I3_afk) return ("I3_afk"); if (func == I3_chan_who) return ("I3_chan_who"); if (func == I3_connect) return ("I3_connect"); if (func == I3_disconnect) return ("I3_disconnect"); if (func == I3_send_user_req) return ("I3_send_user_req"); if (func == I3_permstats) return ("I3_permstats"); if (func == I3_deny_channel) return ("I3_deny_channel"); if (func == I3_permset) return ("I3_permset"); if (func == I3_chanlayout) return ("I3_chanlayout"); if (func == I3_admin_channel) return ("I3_admin_channel"); if (func == I3_addchan) return ("I3_addchan"); if (func == I3_removechan) return ("I3_removechan"); if (func == I3_edit_channel) return ("I3_edit_channel"); if (func == I3_mudlisten) return ("I3_mudlisten"); if (func == I3_router) return ("I3_router"); if (func == I3_bancmd) return ("I3_bancmd"); if (func == I3_setconfig) return ("I3_setconfig"); if (func == I3_setup_channel) return ("I3_setup_channel"); if (func == I3_stats) return ("I3_stats"); if (func == I3_show_ucache_contents) return ("I3_show_ucache_contents"); if (func == I3_debug) return ("I3_debug"); if (func == i3_hedit) return ("i3_hedit"); if (func == i3_help) return ("i3_help"); if (func == i3_cedit) return ("i3_cedit"); return ""; } Do_F * i3_function (const char *func) { if (!str_cmp (func, "I3_other")) return I3_other; if (!str_cmp (func, "I3_listen_channel")) return I3_listen_channel; if (!str_cmp (func, "I3_chanlist")) return I3_chanlist; if (!str_cmp (func, "I3_mudlist")) return I3_mudlist; if (!str_cmp (func, "I3_invis")) return I3_invis; if (!str_cmp (func, "I3_who")) return I3_who; if (!str_cmp (func, "I3_locate")) return I3_locate; if (!str_cmp (func, "I3_tell")) return I3_tell; if (!str_cmp (func, "I3_reply")) return I3_reply; if (!str_cmp (func, "I3_emote")) return I3_emote; if (!str_cmp (func, "I3_beep")) return I3_beep; if (!str_cmp (func, "I3_ignorecmd")) return I3_ignorecmd; if (!str_cmp (func, "I3_finger")) return I3_finger; if (!str_cmp (func, "I3_mudinfo")) return I3_mudinfo; if (!str_cmp (func, "I3_color")) return I3_color; if (!str_cmp (func, "I3_afk")) return I3_afk; if (!str_cmp (func, "I3_chan_who")) return I3_chan_who; if (!str_cmp (func, "I3_connect")) return I3_connect; if (!str_cmp (func, "I3_disconnect")) return I3_disconnect; if (!str_cmp (func, "I3_send_user_req")) return I3_send_user_req; if (!str_cmp (func, "I3_permstats")) return I3_permstats; if (!str_cmp (func, "I3_deny_channel")) return I3_deny_channel; if (!str_cmp (func, "I3_permset")) return I3_permset; if (!str_cmp (func, "I3_admin_channel")) return I3_admin_channel; if (!str_cmp (func, "I3_bancmd")) return I3_bancmd; if (!str_cmp (func, "I3_setconfig")) return I3_setconfig; if (!str_cmp (func, "I3_setup_channel")) return I3_setup_channel; if (!str_cmp (func, "I3_chanlayout")) return I3_chanlayout; if (!str_cmp (func, "I3_addchan")) return I3_addchan; if (!str_cmp (func, "I3_removechan")) return I3_removechan; if (!str_cmp (func, "I3_edit_channel")) return I3_edit_channel; if (!str_cmp (func, "I3_mudlisten")) return I3_mudlisten; if (!str_cmp (func, "I3_router")) return I3_router; if (!str_cmp (func, "I3_stats")) return I3_stats; if (!str_cmp (func, "I3_show_ucache_contents")) return I3_show_ucache_contents; if (!str_cmp (func, "I3_debug")) return I3_debug; if (!str_cmp (func, "i3_help")) return i3_help; if (!str_cmp (func, "i3_cedit")) return i3_cedit; if (!str_cmp (func, "i3_hedit")) return i3_hedit; return NULL; } bool I3_command_hook (CharData * ch, const char *command, const char *argument) { I3_CMD_DATA *cmd; NameList *alias; I3_CHANNEL *channel; int x; if (IsNPC (ch)) return false; if (!ch->desc) return false; if (i3cmd_first == NULL) { wiznet ("Dammit! No command data is loaded!", NULL, NULL, WIZ_I3, true, 1); return false; } if (ch->pcdata->i3chardata->i3perm <= I3PERM_NONE) return false; for (cmd = i3cmd_first; cmd; cmd = cmd->next) { if (ch->pcdata->i3chardata->i3perm < i3cmd_first->level) continue; for (alias = cmd->alias_first; alias; alias = alias->next) { if (!str_cmp (command, alias->name)) { command = cmd->name; break; } } if (!str_prefix (command, cmd->name)) { if (cmd->connected == true && !I3_is_connected ()) { i3println (ch, "The mud is not currently connected to I3."); return true; } (*cmd->function) (cmd->name, ch, argument); return true; } } if ((channel = find_I3_channel_by_localname (command)) == NULL) return false; if (ch->pcdata->i3chardata->i3perm < channel->i3perm) return false; if (hasname (ch->pcdata->i3chardata->i3_denied, channel->local_name)) { i3printlnf (ch, "You have been denied the use of %s by the administration.", channel->local_name); return true; } if (NullStr (argument)) { i3printlnf (ch, "{cThe last %d %s messages:", MAX_I3HISTORY, channel->local_name); for (x = 0; x < MAX_I3HISTORY; x++) { if (channel->history[x] != NULL) i3printf (ch, "%s", channel->history[x]); else break; } return true; } if (!I3_is_connected ()) { i3println (ch, "The mud is not currently connected to I3."); return true; } if (ch->pcdata->i3chardata->i3perm >= I3PERM_ADMIN && !str_cmp (argument, "log")) { if (!IsSet (channel->flags, I3CHAN_LOG)) { SetBit (channel->flags, I3CHAN_LOG); i3printlnf (ch, "{RFile logging enabled for %s, PLEASE don't forget to undo this when it isn't needed!", channel->local_name); } else { RemBit (channel->flags, I3CHAN_LOG); i3printlnf (ch, "{GFile logging disabled for %s.", channel->local_name); } rw_i3_channels (act_write); return true; } if (!hasname (ch->pcdata->i3chardata->i3_listen, channel->local_name)) { i3printlnf (ch, "{YYou were trying to send something to an I3 " "channel but you're not listening to it.\n\rPlease use the command " "'{Wi3listen %s{Y' to listen to it.", channel->local_name); return true; } switch (argument[0]) { case ',': argument++; while (isspace (*argument)) argument++; I3_send_channel_emote (channel, GetName (ch), argument); break; case '@': argument++; while (isspace (*argument)) argument++; I3_send_social (channel, ch, argument); break; default: I3_send_channel_message (channel, GetName (ch), argument); break; } return true; } #endif