/************************************************************************** * 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("\",\"\",\""); I3_write_buffer(GetStr(ch->pcdata->email, "none set")); 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); if (!str_cmp(mud_info.name, MUDNAME)) replace_strf(&i3mud_info.name, "%s-%d", mud_info.name, mud_info.unique_id); else replace_str(&i3mud_info.name, mud_info.name); 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