/**************************************************************************
* 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