/**************************************************************************
* 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 *
***************************************************************************
* ROM 2.4 Integrated Web Server - Version 1.0. This is my first major *
* snippet... Please be kind. ;-) Copyright 1998 -- Defiant -- Rob *
* Siemborski -- mud@towers.crusoe.net Many thanks to Russ and the rest *
* of the developers of ROM for creating such an excellent codebase to *
* program on. If you use this code on your mud, I simply ask that you *
* place my name someplace in the credits. You can put it where you feel *
* it is appropriate. I offer no guarantee that this will work on any mud *
* except my own, and if you can't get it to work, please don't bother me. *
* I wrote and tested this only on a Linux 2.0.30 system. Comments about *
* bugs, are, however, appreciated. *
***************************************************************************
* Insanity v0.9a pre-release Modifications *
* By Chris Fewtrell (Trax) <C.J.Fewtrell@bcs.org.uk> *
* *
* - Added functionailiy for Secure Web server pages, using standard HTTP *
* Basic authentication, comparing with pass list generated with command *
* from within the Mud itself. *
* - Seperated out the HTTP codes and content type to seperate functions *
* (intending to allow more than HTML to be served via this) *
* - Adjusted the descriptor handling to prevent anyone from prematurely *
* stopping a transfer causing a fd exception and the system to exit() *
***************************************************************************
* Additional Modifications based upon with with Insanity Codebase *
* By Chris Fewtrell (Trax) <C.J.Fewtrell@bcs.org.uk> *
***************************************************************************
* 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 "interp.h"
#include "tables.h"
#include "olc.h"
#include "recycle.h"
#include "magic.h"
#include "telnet.h"
#include "data_table.h"
#include "vnums.h"
DataTable wpwd_data_table[] = {
{"name", FIELD_STRING, (void *) &wpwd_zero.name, NULL, NULL},
{"pwd", FIELD_STRING, (void *) &wpwd_zero.passw, NULL, NULL},
{"level", FIELD_INT, (void *) &wpwd_zero.level, NULL, NULL},
{NULL, (field_t) - 1, NULL, NULL, NULL}
};
TableSave_Fun(rw_wpwd_data)
{
rw_list(type, WPWD_FILE, WebpassData, wpwd);
}
void update_webpasses(CharData * ch, bool pDelete)
{
WebpassData *c_next;
WebpassData *curr;
if (IsNPC(ch))
return;
for (curr = wpwd_first; curr != NULL; curr = c_next)
{
c_next = curr->next;
if (!str_cmp(ch->name, curr->name))
{
UnLink(curr, wpwd, next, prev);
free_wpwd(curr);
}
}
if (pDelete || NullStr(ch->pcdata->webpass))
{
rw_wpwd_data(act_write);
return;
}
curr = new_wpwd();
replace_str(&curr->name, ch->name);
replace_str(&curr->passw, ch->pcdata->webpass);
curr->level = get_trust(ch);
Link(curr, wpwd, next, prev);
rw_wpwd_data(act_write);
return;
}
Do_Fun(do_webpass)
{
char arg1[MIL];
char *pArg;
char *pwdnew;
char *p;
char cEnd;
if (!ch || IsNPC(ch))
return;
if (!IsImmortal(ch))
{
chprintln(ch, "This feature is only available to immortals, sorry.");
return;
}
pArg = arg1;
while (isspace(*argument))
argument++;
cEnd = ' ';
if (*argument == '\'' || *argument == '"')
cEnd = *argument++;
while (*argument != '\0')
{
if (*argument == cEnd)
{
argument++;
break;
}
*pArg++ = *argument++;
}
*pArg = '\0';
if (NullStr(arg1))
{
cmd_syntax(ch, NULL, n_fun, "<new>", "show", NULL);
return;
}
d_write(ch->desc, echo_off_str, 0);
if (!str_cmp(arg1, "show"))
{
chprintlnf(ch, "Your password for the website is: %s",
GetStr(ch->pcdata->webpass, "Not Set."));
return;
}
if (strlen(arg1) < 5)
{
chprintln(ch, "New password must be at least five characters long.");
d_write(ch->desc, echo_on_str, 0);
return;
}
pwdnew = crypt(arg1, ch->name);
for (p = pwdnew; *p != '\0'; p++)
{
if (*p == '~')
{
chprintln(ch, "New password not acceptable, try again.");
d_write(ch->desc, echo_on_str, 0);
return;
}
}
replace_str(&ch->pcdata->webpass, pwdnew);
save_char_obj(ch);
update_webpasses(ch, false);
chprintln(ch, "Ok.");
d_write(ch->desc, echo_on_str, 0);
return;
}
WebpassData *check_web_pass(const char *username, const char *password,
int level)
{
WebpassData *current;
for (current = wpwd_first; current; current = current->next)
if (current->level >= level && !str_casecmp(current->name, username))
if (!str_casecmp(current->passw, crypt(password, username)))
return current;
return NULL;
}
#ifndef DISABLE_WEBSRV
Proto(bool bind_ip, (SOCKET, int));
Proto(void handle_web_request, (WebDescriptor *));
Proto(int w_print, (WebDescriptor *, const char *));
ProtoF(int w_printf, (WebDescriptor *, const char *, ...), 2, 3);
ProtoF(int w_printlnf, (WebDescriptor *, const char *, ...), 2, 3);
Proto(int w_println, (WebDescriptor *, const char *));
Proto(void handle_web_request, (WebDescriptor *));
const int pr2six[256] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64,
64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64,
62, 64, 64, 64, 63,
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 64, 0,
1,
2,
3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64,
64,
64, 64, 64, 26, 27,
28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
46,
47, 48, 49, 50, 51,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64,
64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64,
64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64,
64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64,
64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64,
64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
};
void Base64Decode(char *bufcoded, unsigned char *bufplain, int outbufsize)
{
int nbytesdecoded;
int nprbytes;
char *bufin = bufcoded;
unsigned char *bufout = bufplain;
while (*bufcoded == ' ' || *bufcoded == '\t')
++bufcoded;
bufin = bufcoded;
while (pr2six[(int) *(bufin++)] <= 63)
;
nprbytes = bufin - bufcoded - 1;
nbytesdecoded = ((nprbytes + 3) / 4) * 3;
if (nbytesdecoded > outbufsize)
nprbytes = (outbufsize * 4) / 3;
bufin = bufcoded;
while (nprbytes > 0)
{
*(bufout++) =
(unsigned char) (pr2six[(int) *bufin] << 2 |
pr2six[(int) bufin[1]] >> 4);
*(bufout++) =
(unsigned char) (pr2six[(int) bufin[1]] << 4 |
pr2six[(int) bufin[2]] >> 2);
*(bufout++) =
(unsigned char) (pr2six[(int) bufin[2]] << 6 |
pr2six[(int) bufin[3]]);
bufin += 4;
nprbytes -= 4;
}
if (nprbytes & 03)
{
if (pr2six[(int) bufin[-2]] > 63)
nbytesdecoded -= 2;
else
nbytesdecoded -= 1;
}
bufplain[nbytesdecoded] = '\0';
}
struct request_type
{
char *req;
char *name;
Web_F *fun;
bool secure;
bool dir;
};
EXTERN const struct request_type request_table[];
#define CONTENT_HTML 1
#define CONTENT_TEXT 2
#define CONTENT_GIF 3
#define CONTENT_JPEG 4
#define CONTENT_GZIP 5
#define CONTENT_WAV 6
#define CONTENT_VRML 7
#define CONTENT_CLASS 8
struct type_data
{
char *suffix;
int type;
};
const struct type_data status_types[] = {
{"Continue", 100},
{"Switching Protocols", 101},
{"OK", 200},
{"Created", 201},
{"Accepted", 202},
{"Non-Authoritative Information", 203},
{"No Content", 204},
{"Reset Content", 205},
{"Partial Content", 206},
{"Multiple Choices", 300},
{"Moved Permanently", 301},
{"Found", 302},
{"See Other", 303},
{"Not Modified", 304},
{"Use Proxy", 305},
{"Temporary Redirect", 307},
{"Bad Request", 400},
{"Unauthorized", 401},
{"Payment Required", 402},
{"Forbidden", 403},
{"Not Found", 404},
{"Method Not Allowed", 405},
{"Not Acceptable", 406},
{"Proxy Authentication Required", 407},
{"Request Time-out", 408},
{"Conflict", 409},
{"Gone", 410},
{"Length Required", 411},
{"Precondition Failed", 412},
{"Request Entity Too Large", 413},
{"Request-URI Too Large", 414},
{"Unsupported Media Type", 415},
{"Requested range not satisfiable", 416},
{"Expectation Failed", 417},
{"Internal Server Error", 500},
{"Not Implemented", 501},
{"Bad Gateway", 502},
{"Service Unavailable", 503},
{"Gateway Time-out", 504},
{"HTTP Version not supported", 505},
{NULL, 0}
};
const struct type_data content_types[] = {
{
".html", CONTENT_HTML}
,
{
".htm", CONTENT_HTML}
,
{
".gif", CONTENT_GIF}
,
{
".txt", CONTENT_TEXT}
,
{
".text", CONTENT_TEXT}
,
{
".jpg", CONTENT_JPEG}
,
{
".jpeg", CONTENT_JPEG}
,
{
".gz", CONTENT_GZIP}
,
{
".gzip", CONTENT_GZIP}
,
{
".wav", CONTENT_WAV}
,
{
".wrl", CONTENT_VRML}
,
{
".class", CONTENT_CLASS}
,
{
NULL, CONTENT_TEXT}
};
int determine_type(char *path)
{
int i;
for (i = 0; content_types[i].suffix != NULL; i++)
{
if (!str_suffix(content_types[i].suffix, path))
return content_types[i].type;
}
return CONTENT_TEXT;
}
int determine_status(int status)
{
int i;
for (i = 0; status_types[i].type > 0; i++)
{
if (status_types[i].type == status)
return i;
}
return -1;
}
int http_error_code = 200;
void http_status(WebDescriptor * wdesc, int status)
{
int i = determine_status(status);
if (i != -1)
{
w_printlnf(wdesc, "HTTP/1.1 %d %s", status_types[i].type,
status_types[i].suffix);
if (status_types[i].type == 401)
w_println(wdesc,
"WWW-Authenticate: Basic realm='User/Password are Case Sensitive'");
http_error_code = 200;
}
}
void send_content(WebDescriptor * wdesc, int type)
{
switch (type)
{
case CONTENT_HTML:
w_println(wdesc, "Content-type: text/html\n\n");
break;
default:
case CONTENT_TEXT:
w_println(wdesc, "Content-type: text/plain\n\n");
break;
case CONTENT_GIF:
w_println(wdesc, "Content-type: image/gif\n\n");
break;
case CONTENT_WAV:
w_println(wdesc, "Content-type: audio/x-wav\n\n");
break;
case CONTENT_GZIP:
w_println(wdesc,
"Content-type: application/x-zip-compressed\n\n");
break;
case CONTENT_VRML:
w_println(wdesc, "Content-type: x-world/x-vrml\n\n");
break;
case CONTENT_CLASS:
w_println(wdesc, "Content-type: application/octet-stream\n\n");
break;
}
}
int w_print(WebDescriptor * wdesc, const char *txt)
{
if (!wdesc || NullStr(txt))
return 0;
return write_to_socket(wdesc->fd, txt, strlen(txt));
}
int w_printf(WebDescriptor * wdesc, const char *fmt, ...)
{
char buf[MPL];
va_list args;
int len;
if (!wdesc || NullStr(fmt))
return 0;
va_start(args, fmt);
len = vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
return write_to_socket(wdesc->fd, buf, len);
}
int w_println(WebDescriptor * wdesc, const char *buf)
{
if (!wdesc)
return 0;
return (w_print(wdesc, buf) + write_to_socket(wdesc->fd, LF, 1));
}
int w_printlnf(WebDescriptor * wdesc, const char *fmt, ...)
{
char buf[MPL];
if (!wdesc)
return 0;
if (!NullStr(fmt))
{
va_list args;
va_start(args, fmt);
vsnprintf(buf, sizeof(buf), fmt, args);
va_end(args);
}
else
buf[0] = NUL;
return w_println(wdesc, buf);
}
char html_colorbuf[MSL * 10];
bool lastcolor = false;
const struct htmlcolor_type
{
color_value_t at;
char *norm;
char *bryte;
}
htmlcolor_table[] =
{
{
FG_BLACK, "black", "gray"}
,
{
FG_RED, "maroon", "red"}
,
{
FG_GREEN, "green", "lime"}
,
{
FG_YELLOW, "orange", "yellow"}
,
{
FG_BLUE, "navy", "blue"}
,
{
FG_MAGENTA, "magenta", "purple"}
,
{
FG_CYAN, "teal", "cyan"}
,
{
FG_WHITE, "silver", "white"}
,
{
CL_NONE, NULL, NULL}
};
char *htmlcolor_lookup(color_value_t at, bool bryte)
{
int i;
for (i = 0; htmlcolor_table[i].at != CL_NONE; i++)
if (htmlcolor_table[i].at == at)
return bryte ? htmlcolor_table[i].bryte : htmlcolor_table[i].norm;
return NULL;
}
char *colortohtml(colatt_t * col)
{
bool b, script = false;
char buf[MSL];
static char out[MSL];
char *pstr;
convert_random(col);
b = (getcol(col, CT_ATTR) == CL_BRIGHT);
if (VALID_BG(getcol(col, CT_BACK)))
{
if (
(pstr =
htmlcolor_lookup((color_value_t) (getcol(col, CT_BACK) - CL_MOD),
b)) == NULL)
{
script = true;
pstr = "' + document.bgColor + '";
}
sprintf(buf, " background-color: %s;", pstr);
}
if (VALID_FG(getcol(col, CT_FORE)))
{
if ((pstr = htmlcolor_lookup(getcol(col, CT_FORE), b)) == NULL)
{
script = true;
pstr = "' + document.fgColor + '";
}
sprintf(buf, " color: %s;", pstr);
}
if (buf[0] != '\0')
{
if (script)
sprintf(out,
"%s<script type='text/javascript'>document.write('<span style=\"%s\">');</script>",
lastcolor ? "</span>" : "", buf + 1);
else
sprintf(out, "%s<span style=\"%s\">", lastcolor ? "</span>" : "",
buf + 1);
lastcolor = true;
}
else
out[0] = '\0';
return out;
}
int color_slot_lookup(int slot)
{
int i;
for (i = 0; i < MAX_CUSTOM_COLOR; i++)
if (color_table[i].slot == slot)
return i;
return -1;
}
char *html_colorconv(const char *txt)
{
const char *point;
char *output;
colatt_t c;
char buf[MIL];
lastcolor = false;
memset(html_colorbuf, 0, sizeof(html_colorbuf));
output = html_colorbuf;
init_color_data(&c);
for (point = txt; *point; point++)
{
if (*point == COLORCODE)
{
point++;
if (isdigit(*point))
{
int slot = *point - '0';
if (VALID_CL(slot))
{
c[CT_SAVE] = (color_value_t) (slot);
}
if (*(point + 1) == '+' && *(point + 2))
{
point += 2;
}
}
else if (*point == '=')
{
point++;
c[CT_SAVE] = (color_value_t) (c[CT_FORE]);
}
switch (*point)
{
case '}':
strcpy(buf, "<br>");
break;
case '-':
strcpy(buf, "~");
break;
case 'n':
strcpy(buf, mud_info.name);
break;
case 'N':
strcpy(buf, strupper(mud_info.name));
break;
case 't':
case 'T':
if (*(point + 1) == '+' && *(point + 2) == '"'
&& *(point + 3))
{
char fmt[800];
size_t t = 0;
point += 3;
do
{
fmt[t++] = *point++;
}
while (*point && *point != '"' && t < sizeof(fmt));
fmt[t] = '\0';
strcpy(buf, str_time(-1, -1, fmt));
}
else
strcpy(buf, str_time(-1, -1, NULL));
break;
case 'P':
case 'p':
break;
case COLORCODE:
sprintf(buf, "%c", COLORCODE);
break;
case 'X':
case 'x':
init_color_data(&c);
sprintf(buf,
"%s<script type='text/javascript'>document.write('<span style=\"color: ' + document.fgColor + ';\">');</script>",
lastcolor ? "</span>" : "");
break;
default:
set_col_attr(*point, &c, NULL);
strcpy(buf, colortohtml(&c));
break;
}
add_text(buf, output);
}
else if (*point == CUSTOMSTART)
{
int slot = _NONE, pos;
do
{
point++;
if (isdigit(*point))
{
if (slot == _NONE)
slot = 0;
slot = (slot * 10) + (*point - '0');
}
}
while (*point && *point != CUSTOMEND);
if (!VALID_COLOR(slot) || (pos = color_slot_lookup(slot)) == -1)
{
bug("invalid custom color");
strcpy(buf, " ");
}
else
{
copy_color(c, color_table[pos].col_attr);
strcpy(buf, colortohtml(&c));
}
add_text(buf, output);
}
else if (*point == '<')
{
strcpy(buf, HTML_LT);
add_text(buf, output);
}
else if (*point == '>')
{
strcpy(buf, HTML_GT);
add_text(buf, output);
}
else if (*point == '"')
{
strcpy(buf, HTML_QUOTE);
add_text(buf, output);
}
else if (*point == '&')
{
strcpy(buf, HTML_AMP);
add_text(buf, output);
}
else if (*point == '\n')
{
strcpy(buf, "<br>");
add_text(buf, output);
}
else
{
*output++ = *point;
}
}
if (lastcolor == true)
{
char *end = "</span>";
add_text(end, output);
}
*output = '\0';
return html_colorbuf;
}
#define CHAR_URL_PREFIX "chars"
#define OBJ_URL_PREFIX "objs"
#define ROOM_URL_PREFIX "rooms"
#define HELP_URL_PREFIX "helps"
#define NOTE_URL_PREFIX "notes"
#define RACE_URL_PREFIX "races"
#define DEITY_URL_PREFIX "deity"
#define CMD_URL_PREFIX "cmds"
#define CLAN_URL_PREFIX "clans"
#define CLASS_URL_PREFIX "class"
#define STAT_URL_PREFIX "stats"
#define ADMIN_URL_PREFIX "admin"
#define LOGIN_URL_PREFIX "login"
#define NAMEGEN_URL_PREFIX "namegen"
#define SONG_URL_PREFIX "songs"
#define CHANGE_URL_PREFIX "changes"
const char *HTTP_URL(const char *fmt, ...)
{
static char buf[5][MIL];
char path[MIL];
char *result;
static int i;
path[0] = NUL;
if (!NullStr(fmt))
{
va_list args;
va_start(args, fmt);
vsnprintf(path, sizeof(path), fmt, args);
va_end(args);
}
++i;
i %= 5;
result = buf[i];
sprintf(result, "http://%s:%d/%s", HOSTNAME, webport, path);
return result;
}
const char *html_link(const char *desc, const char *fmt, ...)
{
static char buf[5][MIL];
char path[MIL];
char *result, url[MIL];
static int i;
path[0] = NUL;
if (!NullStr(fmt))
{
va_list args;
va_start(args, fmt);
vsnprintf(path, sizeof(path), fmt, args);
va_end(args);
}
++i;
i %= 5;
result = buf[i];
sprintf(url, "http://%s:%d/%s", HOSTNAME, webport, path);
sprintf(result, "<a href=\"%s\">%s</a>", url,
!NullStr(desc) ? desc : !NullStr(path) ? path : url);
return result;
}
const char *get_next(const char *path, char *base)
{
static char *buf[5];
static int i;
int x;
if (NullStr(path))
return path;
++i, i %= 5;
buf[i] = strchr(path, '/');
base[0] = NUL;
if (!NullStr(buf[i]))
{
for (x = path[0] == '/' ? 1 : 0; path[x] != NUL; x++)
{
if (path[x] == buf[i][0] && !str_cmp(&path[x], buf[i]))
{
base[x] = NUL;
break;
}
base[x] = path[x];
}
if (buf[i][0] == '/')
buf[i]++;
}
return buf[i];
}
const char *get_prev(const char *path, char *base)
{
static char *buf[5];
static int i;
int x;
if (NullStr(path))
return path;
++i, i %= 5;
buf[i] = strrchr(path, '/');
base[0] = NUL;
if (!NullStr(buf[i]))
{
for (x = path[0] == '/' ? 1 : 0; path[x] != NUL; x++)
{
if (path[x] == buf[i][0] && !str_cmp(&path[x], buf[i]))
{
base[x] = NUL;
break;
}
base[x] = path[x];
}
if (buf[i][0] == '/')
buf[i]++;
}
return buf[i];
}
WebpassData *get_name_password(WebDescriptor * wdesc, int level)
{
char *where;
char encoded[MIL];
char username[MIL];
char *password = &str_empty[0];
username[0] = '\0';
encoded[0] = '\0';
where = strstr(wdesc->stuff, "Authorization: Basic");
if (!where)
{
http_status(wdesc, 401);
}
else
{
where += strlen("Authorization: Basic");
where++;
for (password = encoded; *where && !isspace(*where);
where++, password++)
*password = *where;
*password = '\0';
Base64Decode(encoded, (unsigned char *) username, MIL);
for (password = username; *password && *password != ':'; password++)
;
{
if (*password == ':')
{
*password = '\0';
password++;
}
}
}
return check_web_pass(username, password, level);
}
void under_line(char *under_lined, const char *spaced_out)
{
char *point;
strcpy(under_lined, spaced_out);
for (point = under_lined; *point; point++)
{
if (*point == ' ')
{
*point = '_';
}
else
{
*point = tolower(*point);
}
}
return;
}
int min_class_level(int sn)
{
int min_so_far = MAX_LEVEL;
int iClass;
for (iClass = 0; iClass < top_class; iClass++)
{
if (skill_table[sn].skill_level[iClass] < min_so_far)
min_so_far = skill_table[sn].skill_level[iClass];
}
return min_so_far;
}
int meta_refresh = -1;
const char *meta_location = NULL;
void print_header(WebDescriptor * wdesc, const char *title)
{
int i;
http_status(wdesc, http_error_code);
send_content(wdesc, CONTENT_HTML);
w_println(wdesc, "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">");
w_println(wdesc, "<html><head>");
w_println(wdesc,
"<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>");
if (meta_refresh > -1)
{
w_printlnf(wdesc, "<meta http-equiv='refresh' content='%d;url=%s'",
meta_refresh, meta_location);
meta_refresh = -1;
}
w_printlnf(wdesc, "<title>");
if (!NullStr(title))
w_printlnf(wdesc, "%s: %s", mud_info.name, title);
else
w_printlnf(wdesc, "%s Homepage", mud_info.name);
w_println(wdesc, "</title>");
w_println(wdesc,
"<style>body { background-color: #000033; color: #FFCC99; font-family: ");
w_println(wdesc,
"Verdana sans-serif; font-size: 12px; letter-spacing: 1px; height: 500;}");
w_println(wdesc, "a { color: #FFCC99; text-decoration: none;}");
w_println(wdesc,
"a:link, a:visited { border-bottom: solid thin #336699; }");
w_println(wdesc,
"a:hover, a:active { border-bottom: solid thin #993333; }");
w_println(wdesc,
".head { background-color: #336699; color: #003366; border: thin solid #336699; }");
w_println(wdesc, ".head-left { font-size: 20px; }");
w_println(wdesc,
".head-right { font-size: 26px;text-align: right; font-weight: bold; color: #000033; }");
w_println(wdesc,
"hr { border: thin solid #000033; color: #336699; width: 100%; height: 3mm; }");
w_println(wdesc, "img { border: none; }");
w_println(wdesc,
".h4 { background-color: #336699; color: #000033; font-size: 16px; font-weight: 700; ");
w_println(wdesc,
"border: solid thin #000033; padding: 2px 0px 1px 1cm; word-spacing: 2px; width: 100%; }");
w_println(wdesc,
".main {background-color: #003366; padding: 5mm 5mm 5mm 5mm; border-top: 0mm; ");
w_println(wdesc,
"border-left: 2mm; border-bottom: 2mm; border-right: 2mm; border-style: solid; ");
w_println(wdesc, "border-color: #336699; height: 100%; }");
w_println(wdesc, ".menu {float: left; padding-right: 1cm; }");
w_println(wdesc,
".footer { background-color: #336699; color: #003366; border: thin solid #336699; ");
w_println(wdesc, "padding: 0px; } .small { 10px; }");
w_println(wdesc, ".footer-left { text-align: left; }");
w_println(wdesc, ".footer-right { text-align: right; }");
w_println(wdesc, ".addr { text-align: right; font-size: 9px; }");
w_println(wdesc, ".all { line-height: 150%; }");
w_println(wdesc,
"dt { font-weight: bold; } .pre { white-space: pre; font-family: monospace; }");
w_println(wdesc, "</style></head><body>");
w_println(wdesc, "<div class=\"all\">");
w_println(wdesc, "<div class=\"head\">");
w_println(wdesc,
"<table width=\"98%\"><tr><td class=\"head-left\"> ");
if (!NullStr(title))
w_println(wdesc, title);
else
w_println(wdesc, "Welcome");
w_printlnf(wdesc, "</td><td class=\"head-right\">...%s</td></tr></table>",
mud_info.name);
w_println(wdesc, "</div><div class=\"main\">");
w_println(wdesc,
"<div class=\"menu\"><table><tr><td class=\"footer-left\">Contents</td></tr>");
for (i = 0; request_table[i].req != NULL; i++)
{
if (!request_table[i].name)
continue;
w_printlnf(wdesc,
"<tr><td class=\"footer-left\"><a %shref='%s'>%s</a></td></tr>",
request_table[i].secure ? "class=\"small\" " : "",
HTTP_URL(request_table[i].req), request_table[i].name);
}
w_println(wdesc, "</table></div>");
}
void print_footer(WebDescriptor * wdesc)
{
w_println(wdesc, "</div><div class=\"footer\">");
w_println(wdesc, "<table width=\"98%\"><tr>");
w_println(wdesc, "<td class=\"footer-left\"><table><tr><td>");
w_printlnf(wdesc, "[<a href=\"%s/\">Home</a>] ", HTTP_URL(NULL));
w_println(wdesc, "[<a href=\"#\" onclick=\"history.back()\">Back</a>] ");
w_println(wdesc,
"[<a href=\"#\" onclick=\"history.forward()\">Forward</a>] ");
w_println(wdesc,
"[<a href=\"#\" onclick=\"location.reload()\">Refresh</a>]</td></tr>");
w_println(wdesc,
"<tr><td><a href=\"http://validator.w3.org/check/referer\">"
"<img src=\"http://www.w3.org/Icons/valid-html401\" alt=\"Valid HTML 4.0.1!\" height=\"31\" width=\"88\">");
w_printlnf(wdesc,
"</a> <a href=\"http://jigsaw.w3.org/css-validator/validator?uri=%s\">",
HTTP_URL(NULL));
w_println(wdesc,
"<img width=\"88\" height=\"31\" src=\"http://jigsaw.w3.org/css-validator/images/vcss\" alt=\"Valid CSS!\"></a>");
w_println(wdesc, "</td></tr></table></td>");
w_println(wdesc,
"<td class=\"footer-right\"><table><tr><td><b>1stMud Server Project Ring</b></td></tr>");
w_println(wdesc,
"<tr><td>[ <a href=\"http://C.webring.com/wrman?ring=1stmudserverproj;addsite\">Join</a>");
w_println(wdesc,
" | <a href=\"http://C.webring.com/hub?ring=1stmudserverproj;id=3;hub\">List</a> | ");
w_println(wdesc,
"<a href=\"http://C.webring.com/go?ring=1stmudserverproj;id=3;random\">Random</a> | ");
w_println(wdesc,
"<b><a href=\"http://C.webring.com/go?ring=1stmudserverproj;id=3;prev\"><< Prev</a>");
w_println(wdesc,
"| <a href=\"http://C.webring.com/go?ring=1stmudserverproj;id=3;next\">Next >></a>");
w_println(wdesc, "</b> ]</td></tr></table></td>");
w_printlnf(wdesc,
"</tr></table></div><div class=\"addr\"><span>© <a href=\"mailto:%s@%s?re:%s\">%s@%s</a>",
UNAME, HOSTNAME, mud_info.name, UNAME, HOSTNAME);
w_println(wdesc, "</span></div></div></body></html>");
}
void print_file(WebDescriptor * wdesc, char *filename)
{
FileData *fp;
char buf[MSL];
int c;
int num = 0;
if ((fp = f_open(filename, "r")) != NULL)
{
while (!f_eof(fp))
{
while ((buf[num] = f_getc(fp)) != EOF && buf[num] != '\n'
&& buf[num] != '\r' && num < (MSL - 2))
num++;
c = f_getc(fp);
if ((c != '\n' && c != '\r') || c == buf[num])
f_ungetc(c, fp);
buf[num] = '\0';
w_println(wdesc, buf);
num = 0;
}
f_close(fp);
}
}
char *format_obj_to_html(ObjData * obj)
{
AffectData *paf;
static char output[MSL * 5];
char buf[MSL * 5];
output[0] = '\0';
if (NullStr(obj->description))
return output;
if (IsObjStat(obj, ITEM_INVIS))
strcat(output, "(Invis) ");
if (IsObjStat(obj, ITEM_DARK))
strcat(output, "(Dark) ");
if (IsObjStat(obj, ITEM_EVIL))
strcat(output, "(Red Aura) ");
if (IsObjStat(obj, ITEM_BLESS))
strcat(output, "(Blue Aura) ");
if (IsObjStat(obj, ITEM_MAGIC))
strcat(output, "(Magical) ");
if (IsObjStat(obj, ITEM_GLOW))
strcat(output, "(Glowing) ");
if (IsObjStat(obj, ITEM_HUM))
strcat(output, "(Humming) ");
if (obj->item_type == ITEM_WEAPON)
{
for (paf = obj->affect_first; paf; paf = paf->next)
{
if (IsSet(paf->bitvector, WEAPON_FLAMING))
strcat(output, "(Flaming) ");
if (IsSet(paf->bitvector, WEAPON_FROST))
strcat(output, "(Frost) ");
if (IsSet(paf->bitvector, WEAPON_VAMPIRIC))
strcat(output, "(Vampiric) ");
if (IsSet(paf->bitvector, WEAPON_SHOCKING))
strcat(output, "(Shocking) ");
if (IsSet(paf->bitvector, WEAPON_POISON))
strcat(output, "(Poison) ");
if (IsSet(paf->bitvector, WEAPON_SHARP))
strcat(output, "(Sharp) ");
if (IsSet(paf->bitvector, WEAPON_VORPAL))
strcat(output, "(Vorpal) ");
}
}
if (IsObjStat(obj, ITEM_AUCTIONED))
strcat(output, "(Auctioned) ");
if (obj->condition <= 9 && obj->condition >= 0)
strcat(output, "(Ruined) ");
else if (obj->condition >= 10 && obj->condition <= 24)
strcat(output, "(Broken) ");
if (obj->description != NULL)
{
sprintf(buf, "<a href='%s'>%s</a><br>",
HTTP_URL(OBJ_URL_PREFIX "/%ld", obj->pIndexData->vnum),
html_colorconv(obj->description));
strcat(output, buf);
}
return output;
}
char *show_list_to_html(ObjData * list)
{
static char output[MSL * 6];
const char **prgpstrShow;
int *prgnShow;
char *pstrShow;
ObjData *obj;
int nShow;
int iShow;
int count;
char temp[MSL];
bool found;
count = 0;
for (obj = list; obj != NULL; obj = obj->next_content)
count++;
alloc_mem(prgpstrShow, const char *, count);
alloc_mem(prgnShow, int, count);
nShow = 0;
output[0] = '\0';
for (obj = list; obj != NULL; obj = obj->next_content)
{
if (obj->wear_loc == WEAR_NONE)
{
pstrShow = format_obj_to_html(obj);
found = false;
for (iShow = nShow - 1; iShow >= 0; iShow--)
{
if (!str_cmp(prgpstrShow[iShow], pstrShow))
{
prgnShow[iShow]++;
found = true;
break;
}
}
if (!found)
{
prgpstrShow[nShow] = str_dup(pstrShow);
prgnShow[nShow] = 1;
nShow++;
}
}
}
for (iShow = 0; iShow < nShow; iShow++)
{
if (NullStr(prgpstrShow[iShow]))
{
free_string(prgpstrShow[iShow]);
continue;
}
if (prgnShow[iShow] != 1)
{
sprintf(temp, "(%2d) ", prgnShow[iShow]);
strcat(output, temp);
}
else
strcat(output, " ");
sprintf(temp, "%s<br>", prgpstrShow[iShow]);
strcat(output, temp);
free_string(prgpstrShow[iShow]);
if (strlen(output) > 5500)
{
strcat(output, " (More stuff not shown)<br>");
break;
}
}
free_mem(prgpstrShow);
free_mem(prgnShow);
return output;
}
char *show_char_to_html_0(CharData * victim)
{
static char buf[MSL * 6];
char temp[MSL];
buf[0] = '\0';
if (IsAffected(victim, AFF_INVISIBLE))
strcat(buf, "(Invis) ");
if (victim->invis_level >= LEVEL_IMMORTAL)
strcat(buf, "(Wizi) ");
if (IsAffected(victim, AFF_HIDE))
strcat(buf, "(Hide) ");
if (IsAffected(victim, AFF_CHARM))
strcat(buf, "(Charmed) ");
if (IsAffected(victim, AFF_PASS_DOOR))
strcat(buf, "(Translucent) ");
if (IsAffected(victim, AFF_FAERIE_FIRE))
strcat(buf, "(Pink Aura) ");
if (IsEvil(victim))
strcat(buf, "(Red Aura) ");
if (IsGood(victim))
strcat(buf, "(Golden Aura) ");
if (IsAffected(victim, AFF_SANCTUARY))
strcat(buf, "(White Aura) ");
if (!IsNPC(victim) && !victim->desc)
strcat(buf, "(Linkdead) ");
if (!IsNPC(victim))
{
if (IsSet(victim->comm, COMM_AFK))
strcat(buf, "*AFK* ");
if (victim->war)
strcat(buf, "(War) ");
if (!IsNPC(victim) && IsSet(victim->act, PLR_OUTLAW))
strcat(buf, "(OUTLAW) ");
if (IsSet(victim->comm, COMM_QUIET))
strcat(buf, "[QUIET] ");
if (victim->desc && victim->desc->editor != ED_NONE)
strcat(buf, "[OLC] ");
if (victim->pcdata->in_progress != NULL)
strcat(buf, "[Note] ");
if (IsQuester(victim))
strcat(buf, "[Q] ");
}
if (victim->level > 0)
{
long vict_condition;
if (victim->max_hit > 0)
vict_condition = victim->hit * 100 / victim->max_hit;
else
vict_condition = -1;
if (vict_condition < 0)
strcat(buf, "(DEAD) ");
else if (vict_condition < 33)
strcat(buf, "(Wounded) ");
}
if (victim->position == (IsNPC(victim) ? victim->start_pos : POS_STANDING)
&& !NullStr(victim->long_descr))
{
if (IsNPC(victim))
{
sprintf(temp, "<a href='%s'>%s</a>",
HTTP_URL(CHAR_URL_PREFIX "/%ld",
victim->pIndexData->vnum),
html_colorconv(victim->long_descr));
strcat(buf, temp);
}
return (buf);
}
if (IsNPC(victim))
{
sprintf(temp, "<a href='%s'>%s</a>",
HTTP_URL(CHAR_URL_PREFIX "/%ld", victim->pIndexData->vnum),
html_colorconv(victim->short_descr));
strcat(buf, temp);
}
else
{
strcat(buf, victim->name);
}
switch (victim->position)
{
case POS_DEAD:
strcat(buf, " is DEAD!!");
break;
case POS_MORTAL:
strcat(buf, " is mortally wounded.");
break;
case POS_INCAP:
strcat(buf, " is incapacitated.");
break;
case POS_STUNNED:
strcat(buf, " is lying here stunned.");
break;
case POS_SLEEPING:
if (victim->on != NULL)
{
if (IsSet(victim->on->value[2], SLEEP_AT))
{
sprintf(temp, " is sleeping at %s.",
victim->on->short_descr);
strcat(buf, temp);
}
else if (IsSet(victim->on->value[2], SLEEP_ON))
{
sprintf(temp, " is sleeping on %s.",
victim->on->short_descr);
strcat(buf, temp);
}
else
{
sprintf(temp, " is sleeping in %s.",
victim->on->short_descr);
strcat(buf, temp);
}
}
else
strcat(buf, " is sleeping here.");
break;
case POS_RESTING:
if (victim->on != NULL)
{
if (IsSet(victim->on->value[2], REST_AT))
{
sprintf(temp, " is resting at %s.",
victim->on->short_descr);
strcat(buf, temp);
}
else if (IsSet(victim->on->value[2], REST_ON))
{
sprintf(temp, " is resting on %s.",
victim->on->short_descr);
strcat(buf, temp);
}
else
{
sprintf(temp, " is resting in %s.",
victim->on->short_descr);
strcat(buf, temp);
}
}
else
strcat(buf, " is resting here.");
break;
case POS_SITTING:
if (victim->on != NULL)
{
if (IsSet(victim->on->value[2], SIT_AT))
{
sprintf(temp, " is sitting at %s.",
victim->on->short_descr);
strcat(buf, temp);
}
else if (IsSet(victim->on->value[2], SIT_ON))
{
sprintf(temp, " is sitting on %s.",
victim->on->short_descr);
strcat(buf, temp);
}
else
{
sprintf(temp, " is sitting in %s.",
victim->on->short_descr);
strcat(buf, temp);
}
}
else
strcat(buf, " is sitting here.");
break;
case POS_STANDING:
if (victim->on != NULL)
{
if (IsSet(victim->on->value[2], STAND_AT))
{
sprintf(temp, " is standing at %s.",
victim->on->short_descr);
strcat(buf, temp);
}
else if (IsSet(victim->on->value[2], STAND_ON))
{
sprintf(temp, " is standing on %s.",
victim->on->short_descr);
strcat(buf, temp);
}
else
{
sprintf(temp, " is standing in %s.",
victim->on->short_descr);
strcat(buf, temp);
}
}
strcat(buf, " is here.");
break;
case POS_FIGHTING:
strcat(buf, " is here, fighting ");
if (victim->fighting == NULL)
strcat(buf, "thin air??");
else if (victim->in_room == victim->fighting->in_room)
{
strcat(buf,
IsNPC(victim) ? victim->fighting->
short_descr : victim->fighting->name);
strcat(buf, ".");
}
else
strcat(buf, "someone who left??");
break;
default:
break;
}
return (buf);
}
char *show_char_to_html(CharData * list)
{
CharData *rch;
static char output[MSL * 10];
output[0] = '\0';
for (rch = list; rch != NULL; rch = rch->next_in_room)
{
if (rch->invis_level >= LEVEL_IMMORTAL)
continue;
strcat(output, show_char_to_html_0(rch));
strcat(output, "<br>");
}
return (output);
}
Web_Fun(HandleMemoryRequest)
{
int sn, count_spell = 0, count_skill = 0;
for (sn = 0; sn < top_skill; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (skill_table[sn].spell_fun != spell_null)
count_spell += 1;
else
count_skill += 1;
}
print_header(wdesc, "Technical Info");
w_println(wdesc, "<table><tr>");
w_printlnf(wdesc, "<table><tr><td>Version</td><td>%s</td></tr>",
MUDSTRING);
w_println(wdesc, "<tr><td>Compiled on</td><td>" __DATE__ "</td><tr>");
w_printlnf(wdesc, "<td>Affects</td> <td>%d</td></tr>", top_affect);
w_printlnf(wdesc, "<tr><td>Areas</td> <td>%d</td></tr>", top_area);
w_printlnf(wdesc, "<tr><td>Extra Descriptions</td> <td>%d</td></tr>",
top_ed);
w_printlnf(wdesc, "<tr><td>Exits</td> <td>%d</td></tr>", top_exit);
w_printlnf(wdesc, "<tr><td>Helps</td> <td>%d</td></tr>", top_help);
w_printlnf(wdesc, "<tr><td>Socials</td> <td>%d</td></tr>", top_social);
w_printlnf(wdesc, "<tr><td>Spells</td> <td>%d</td></tr>", count_spell);
w_printlnf(wdesc, "<tr><td>Spell Groups</td><td>%d</td></tr>", top_group);
w_printlnf(wdesc, "<tr><td>Skills</td> <td>%d</td></tr>", count_skill);
w_printlnf(wdesc, "<tr><td>Mobiles</td> <td>%d (%d in use)</td></tr>",
top_char_index, mobile_count);
w_printlnf(wdesc, "<tr><td>Objects</td> <td>%d (%d in use)</td></tr>",
top_obj_index, top_obj);
w_printlnf(wdesc, "<tr><td>Resets</td> <td>%d</td></tr>", top_reset);
w_printlnf(wdesc, "<tr><td>Rooms</td> <td>%d (%d explorable)</td></tr>",
top_room_index, top_explored);
w_printlnf(wdesc, "<tr><td>Shops</td> <td>%d</td></tr>", top_shop);
w_printlnf(wdesc, "<tr><td>Number of Players</td><td>%d</td></tr>",
pfiles.count);
w_printlnf(wdesc, "<tr><td>Races</td><td>%d</td></tr>", top_race);
w_printlnf(wdesc, "<tr><td>Programs (mob,obj,room)</td><td>%d</td></tr>",
top_mprog + top_oprog + top_rprog);
w_printlnf(wdesc, "<tr><td>Bans</td><td>%d</td></tr>", top_ban);
w_printlnf(wdesc, "<tr><td>Deities</td><td>%d</td></tr>", top_deity);
w_printlnf(wdesc, "<tr><td>Clans</td><td>%d (%d members)</td></tr>",
top_clan, top_mbr);
w_printlnf(wdesc, "<tr><td>Commands</td><td>%d</td></tr>", top_cmd);
w_printlnf(wdesc, "<tr><td>Classes</td><td>%d</td></tr>", top_class);
w_printlnf(wdesc, "<tr><td>Channels</td><td>%d</td></tr>", top_channel);
w_printlnf(wdesc, "<tr><td>Notes</td><td>%d</td></tr>", top_note);
w_printlnf(wdesc, "<tr><td>MSP Sounds</td><td>%d</td></tr>", top_msp);
w_printlnf(wdesc, "<tr><td>String Space</td><td>%d (%s)</td></tr>",
nAllocString, fsize(sAllocString));
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
Web_Fun(HandleRulesRequest)
{
HelpData *pHelp;
print_header(wdesc, "Rules");
w_println(wdesc, "<p>");
if ((pHelp = help_lookup("RULES")) != NULL)
{
w_println(wdesc, html_colorconv(help_text(pHelp->text)));
}
else
w_println(wdesc, "There are no rules!! Anarchy!!");
w_println(wdesc, "</p>");
print_footer(wdesc);
return true;
}
Web_Fun(HandleCreditsRequest)
{
HelpData *pHelp;
print_header(wdesc, "Credits");
if ((pHelp = help_lookup("DIKU")) != NULL)
{
w_println(wdesc, "<hr><p>");
w_println(wdesc, html_colorconv(help_text(pHelp->text)));
w_println(wdesc, "</p>");
}
if ((pHelp = help_lookup("MERC")) != NULL)
{
w_println(wdesc, "<hr><p>");
w_println(wdesc, html_colorconv(help_text(pHelp->text)));
w_println(wdesc, "</p>");
}
if ((pHelp = help_lookup("ROM CREDITS")) != NULL)
{
w_println(wdesc, "<hr><p>");
w_println(wdesc, html_colorconv(help_text(pHelp->text)));
w_println(wdesc, "</p>");
}
if ((pHelp = help_lookup("1STMUD CREDITS")) != NULL)
{
w_println(wdesc, "<hr><p>");
w_println(wdesc, html_colorconv(help_text(pHelp->text)));
w_println(wdesc, "</p>");
}
else
{
w_printlnf(wdesc, "<hr><table><tr><td>%s (%s) design by:</td>",
mud_info.name, MUDSTRING);
w_printlnf(wdesc,
"<td>Markanth</td><td><markanth@firstmud.com></td></tr>");
}
print_footer(wdesc);
return true;
}
Web_Fun(HandleAreaRequest)
{
AreaData *pArea;
int count = 0;
print_header(wdesc, "Areas");
w_println(wdesc, "<table>");
w_println(wdesc, "<tr>");
w_println(wdesc, "<th>Low/High Level</th>");
w_println(wdesc, "<th>Author</th>");
w_println(wdesc, "<th>Area Name</th></tr>");
for (pArea = area_first_sorted; pArea; pArea = pArea->next_sort)
{
if (!IsSet(pArea->area_flags, AREA_CLOSED | AREA_PLAYER_HOMES))
{
w_println(wdesc, "<tr>");
if (!NullStr(pArea->lvl_comment))
w_printlnf(wdesc, "<td>%s</td>", pArea->lvl_comment);
else
w_printlnf(wdesc, "<td>%03d %03d</td>", pArea->min_level,
pArea->max_level);
w_printlnf(wdesc, "<td>%s</td>", pArea->credits);
w_printlnf(wdesc, "<td>%s</td></tr>", pArea->name);
count++;
}
}
w_println(wdesc, "</table>");
w_printlnf(wdesc, "<p>Areas Found: %d.</p>", count);
print_footer(wdesc);
return true;
}
Web_Fun(HandleSpellsRequest)
{
int gn;
int sn, i;
int tn;
RaceData *race;
bool *displayed;
int past_default = true;
char buf[MSL];
char buf2[MSL];
char buf3[MSL];
alloc_mem(displayed, bool, top_skill);
memset(displayed, false, top_skill);
print_header(wdesc, "Spells and Skills");
for (gn = 0; gn < top_group; gn++)
{
if (group_table[gn].name == NULL)
break;
if (!str_cmp(group_table[gn].name, "rom basics"))
{
w_println(wdesc, "<H3>Basic Skills</H3>");
w_println(wdesc,
"All players receive the <I>basic</I> skills for their class.<br>");
w_println(wdesc, "<table><tr>");
w_println(wdesc, "<td>Basic Group</td>");
w_println(wdesc, "<td>Skills Included</td></tr>");
}
if (!str_cmp(group_table[gn].name, "mage default"))
{
past_default = false;
w_println(wdesc, "</table>");
w_println(wdesc, "<H3>Default Skill/Spell Groups</H3>");
w_println(wdesc,
"Players receive the <I>default</I> skills and spell groups if they bypass customization.<br>");
w_println(wdesc, "<table><tr>");
w_println(wdesc, "<td>Default Group</td>");
w_println(wdesc, "<td>Skills Included</td>");
w_println(wdesc, "<td>Skill/Spell Groups Included</td></tr>");
}
if (!str_cmp(group_table[gn].name, "weaponsmaster"))
{
past_default = true;
w_println(wdesc, "</table>");
w_println(wdesc, "<H3>Other Skill/Spell Groups</H3>");
w_println(wdesc, "Players may gain these skills and spells.<br>");
w_println(wdesc, "<table><tr>");
w_println(wdesc, "<td>Skill/Spell Group</td>");
w_println(wdesc, "<td>Skills/Spells Included</td></tr>");
}
under_line(buf3, group_table[gn].name);
w_printlnf(wdesc, "<tr><td><a name='%s'>%s</a></td><td>", buf3,
group_table[gn].name);
buf[0] = '\0';
for (sn = 0; sn < MAX_IN_GROUP; sn++)
{
if (group_table[gn].spells[sn] == NULL)
break;
tn = skill_lookup(group_table[gn].spells[sn]);
if (tn != -1)
{
sprintf(buf2, "%s, ", group_table[gn].spells[sn]);
strcat(buf, buf2);
displayed[tn] = true;
}
}
if (!NullStr(buf) && (strlen(buf) > 2))
buf[(strlen(buf) - 2)] = '\0';
else
strcpy(buf, "None");
if (!past_default)
{
w_printlnf(wdesc, "%s</td><td>", buf);
buf[0] = '\0';
for (sn = 0; sn < MAX_IN_GROUP; sn++)
{
if (group_table[gn].spells[sn] == NULL)
break;
tn = skill_lookup(group_table[gn].spells[sn]);
if (tn == -1)
{
under_line(buf3, group_table[gn].spells[sn]);
sprintf(buf2, "<a href='#%s'>%s</a>, ", buf3,
group_table[gn].spells[sn]);
strcat(buf, buf2);
}
else
{
displayed[tn] = true;
}
}
if (!NullStr(buf) && (strlen(buf) > 2))
buf[(strlen(buf) - 2)] = '\0';
else
strcpy(buf, "None");
}
w_printlnf(wdesc, "%s</td></tr>", buf);
}
w_println(wdesc, "</table>");
w_println(wdesc, "<H3>Other Skills and Spells</H3>");
w_println(wdesc,
"The following skills and spells are available to various mortals.<br>");
w_println(wdesc, "<table><tr><td>");
buf[0] = '\0';
for (sn = 1; sn < top_skill; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (!displayed[sn] && (min_class_level(sn) < ANGEL))
{
sprintf(buf2, "%s, ", skill_table[sn].name);
strcat(buf, buf2);
displayed[sn] = true;
}
}
if (!NullStr(buf) && (strlen(buf) > 2))
buf[(strlen(buf) - 2)] = '\0';
else
strcpy(buf, "None");
w_printlnf(wdesc, "%s</td></tr>", buf);
w_println(wdesc, "</table>");
w_printlnf(wdesc,
"<p>To view skills in class specific tables, visit the <a href='%s'>Classes</a> section.</p>",
HTTP_URL(CLASS_URL_PREFIX));
w_println(wdesc, "<H3><a NAME='RaceSkills'>Race Skills</a></H3>");
w_println(wdesc, "The following skills and spells are race specific.");
w_println(wdesc, "<table><tr>");
w_println(wdesc, "<td>Race</td>");
w_println(wdesc, "<td>Skills</td></tr>");
for (race = race_first; race; race = race->next)
{
if (!race->pc_race)
continue;
w_printlnf(wdesc, "<tr><td>%s</td><td>", race->name);
buf[0] = '\0';
for (sn = 1; sn < top_skill; sn++)
{
if (skill_table[sn].name == NULL)
break;
for (i = 0; i < MAX_RACE_SKILL; i++)
{
if (race->skills[i] == NULL)
break;
if (skill_lookup(race->skills[i]) == sn)
{
sprintf(buf2, "%s, ", skill_table[sn].name);
strcat(buf, buf2);
displayed[sn] = true;
}
}
}
if (!NullStr(buf) && (strlen(buf) > 2))
buf[(strlen(buf) - 2)] = '\0';
else
strcpy(buf, "None");
w_printlnf(wdesc, "%s</td></tr>", buf);
}
w_println(wdesc, "</table>");
w_println(wdesc, "<H3>Immortal Skills and Spells</H3>");
w_println(wdesc,
"The following skills and spells are available to various immortals.");
w_println(wdesc, "This list includes some spells under development.<br>");
w_println(wdesc, "<table><tr>");
w_println(wdesc, "<td>Spells</td></tr>");
w_println(wdesc, "<tr><td>");
buf[0] = '\0';
for (sn = 1; sn < top_skill; sn++)
{
if (skill_table[sn].name == NULL)
break;
if (!displayed[sn])
{
sprintf(buf2, "%s, ", skill_table[sn].name);
strcat(buf, buf2);
displayed[sn] = true;
}
}
if (!NullStr(buf) && (strlen(buf) > 2))
buf[(strlen(buf) - 2)] = '\0';
else
strcpy(buf, "None");
w_printlnf(wdesc, "%s</td></tr>", buf);
w_println(wdesc, "</table>");
print_footer(wdesc);
free_mem(displayed);
return true;
}
Web_Fun(HandleWhoRequest)
{
CharData *wch;
print_header(wdesc, "Players currently");
w_println(wdesc, "<table><tr>");
w_println(wdesc,
"<th>Level</th><th>Race</th><th>Class</th><th>Clan</th>");
w_println(wdesc, "<th>Name</th></tr>");
for (wch = player_first; wch != NULL; wch = wch->next_player)
{
if (wch->invis_level >= LEVEL_IMMORTAL
|| wch->incog_level >= LEVEL_IMMORTAL)
continue;
w_println(wdesc, "<tr>");
if (NullStr(wch->pcdata->who_descr))
{
w_printlnf(wdesc, "<td>%d</td>", wch->level);
w_printlnf(wdesc, "<td><a href='%s'>%s</a></td>",
HTTP_URL(RACE_URL_PREFIX "/%s", wch->race->name),
wch->race->name);
w_printlnf(wdesc, "<td>%s</td>", class_short(wch));
}
else
{
w_printlnf(wdesc, "<td colspan=3>%s</td>",
html_colorconv(wch->pcdata->who_descr));
}
if (is_clan(wch))
{
w_printlnf(wdesc, "<td><a href='%s'>%s</a></td>",
HTTP_URL(CLAN_URL_PREFIX "/%s", CharClan(wch)->name),
html_colorconv(CharClan(wch)->who_name));
}
else
w_println(wdesc, "<td></td>");
w_println(wdesc, "<td>");
if (NullStr(wch->pcdata->email))
w_println(wdesc, wch->name);
else
w_printlnf(wdesc, "<a href=\"mailto://%s?subject=%s\">%s</a>",
wch->pcdata->email, wch->name);
w_println(wdesc, html_colorconv(wch->pcdata->title));
w_println(wdesc, "</td></tr>");
}
w_println(wdesc, "</table><br>");
print_footer(wdesc);
return true;
}
const char *stat_type_name[MAX_GAMESTAT + 1][2] = {
{"GENERAL STATS", "general"},
{"PLAYER KILLERS", "pkill"},
{"MOB KILLERS", "mkill"},
{"PK DEATHS", "pkdead"},
{"MOB DEATHS", "mdead"}
};
Web_Fun(HandleStatsRequest)
{
int pos;
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Stats");
w_println(wdesc, "<ul>");
for (pos = 0; pos <= MAX_GAMESTAT; pos++)
{
w_printlnf(wdesc, "<li><a href='%s'>%s</a>",
HTTP_URL(STAT_URL_PREFIX "/%s",
stat_type_name[pos][1]),
stat_type_name[pos][0]);
}
w_println(wdesc, "</ul>");
print_footer(wdesc);
return true;
}
else
{
if (!str_cmp("general", wdesc->buf))
{
print_header(wdesc, "General Stats");
w_println(wdesc, "<table><tr>");
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Logins",
mud_info.stats.logins);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Quests",
mud_info.stats.quests);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>",
"Quests Complete", mud_info.stats.qcomplete);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Levels",
mud_info.stats.levels);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>", "Newbies",
mud_info.stats.newbies);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Deletions",
mud_info.stats.deletions);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>",
"Mob Deaths", mud_info.stats.mobdeaths);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Auctions",
mud_info.stats.auctions);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>",
"Auctions Sold", mud_info.stats.aucsold);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Player Deaths",
mud_info.stats.pdied);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>",
"Player Kills", mud_info.stats.pkill);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Notes",
mud_info.stats.notes);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>", "Remorts",
mud_info.stats.remorts);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Wars",
mud_info.stats.wars);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>",
"Global Quests", mud_info.stats.gquests);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Connections",
mud_info.stats.connections);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>",
"Connects this Boot", mud_info.stats.boot_connects);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Online Record",
mud_info.stats.online);
w_printlnf(wdesc, "</tr><tr><td>%s</td><td>%ld</td>", "Web Hits",
mud_info.stats.web_requests);
w_printlnf(wdesc, "<td>%s</td><td>%ld</td>", "Channel Messages",
mud_info.stats.chan_msgs);
w_println(wdesc, "</tr></table>");
w_printlnf(wdesc, "<p>Stats since: %s</p>",
timestr(current_time - mud_info.stats.lastupdate,
false));
print_footer(wdesc);
return true;
}
for (pos = 1; pos <= MAX_GAMESTAT; pos++)
{
if (!str_cmp(stat_type_name[pos][1], wdesc->buf))
{
Proto(int compare_stats, (const void *, const void *));
char temp[MSL];
StatData *curr;
StatData **top;
int count, loop;
bool found = false;
EXTERN int compare_type;
sprintf(temp, "Ranking of %s", stat_type_name[pos][0]);
print_header(wdesc, temp);
w_println(wdesc, "<table>");
alloc_mem(top, StatData *, top_stat);
count = 0;
compare_type = pos;
loop = 0;
pos = 0;
for (curr = stat_first; curr != NULL; curr = curr->next)
{
top[count] = curr;
count++;
found = true;
}
qsort(top, count, sizeof(*top), compare_stats);
w_println(wdesc,
"<tr><th>Rank</th><th>Name</th><th>Number</th>"
"<th>Rank</th><th>Name</th><th>Number</th></tr>");
for (loop = 0; loop < count; loop++)
{
if (loop >= 50)
break;
w_printlnf(wdesc,
"%s<td>%2d)</td><td>%-20s</td><td>%ld</td>",
pos == 0 ? "<tr>" : "", loop + 1,
top[loop]->name,
top[loop]->gamestat[compare_type]);
if (++pos % 2 == 0)
{
w_println(wdesc, "</tr>");
pos = 0;
}
}
if (!found)
w_println(wdesc,
"<tr><td colspan=3>No one found yet.</td></tr>");
w_println(wdesc, "</table>");
print_footer(wdesc);
free_mem(top);
return true;
}
}
}
return false;
}
Web_Fun(HandleCommandsRequest)
{
CmdData *i;
int pos = 0;
HelpData *pHelp;
int count = 0;
print_header(wdesc, "Commands");
w_println(wdesc, "<table>");
for (i = cmd_first_sorted; i; i = i->next_sort)
{
if (i->level >= LEVEL_IMMORTAL || i->category == CMDCAT_NOSHOW)
continue;
count = 0;
for (pHelp = help_first; pHelp; pHelp = pHelp->next)
{
count++;
if (is_name(i->name, pHelp->keyword))
break;
}
if (pHelp)
w_printlnf(wdesc, "%s<td><a href='%s'>%s</td>",
(pos == 0) ? "<tr>" : "",
HTTP_URL(HELP_URL_PREFIX "/%d", count), i->name);
else
w_printlnf(wdesc, "%s<td>%s</td>", (pos == 0) ? "<tr>" : "",
i->name);
if (++pos % 5 == 0)
{
w_println(wdesc, "</tr>");
pos = 0;
}
}
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
Web_Fun(HandleHelpsRequest)
{
HelpData *pHelp;
int pos = 0;
if (NullStr(wdesc->buf))
{
int count = 0;
print_header(wdesc, "Help Files");
w_println(wdesc, "<table>");
for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next)
{
count++;
if (pHelp->level <= MAX_MORTAL_LEVEL && pHelp->level >= 0)
{
const char *temp;
char wordkey[MSL];
temp = pHelp->keyword;
while (!NullStr(temp))
{
wordkey[0] = '\0';
temp = one_argument(temp, wordkey);
w_printlnf(wdesc, "%s<td><a href='%s'>%s</a></td>",
(pos == 0) ? "<tr>" : "",
HTTP_URL(HELP_URL_PREFIX "/%d", count),
wordkey);
if (++pos % 5 == 0)
{
w_println(wdesc, "</tr>");
pos = 0;
}
}
}
}
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
else
{
char temp[MIL];
pos = 0;
for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next)
{
pos++;
sprintf(temp, "%d", pos);
if (!str_cmp(wdesc->buf, temp))
{
print_header(wdesc, pHelp->keyword);
w_println(wdesc, "<table>");
w_printlnf(wdesc,
"<tr><td>[%d] %s<td><td>Category: %s</td></tr>",
pHelp->level, pHelp->keyword,
flag_string(help_types, pHelp->category));
w_printlnf(wdesc, "<tr><td colspan=\"2\">%s</td></tr>",
html_colorconv(fix_string(pHelp->text)));
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
}
}
print_header(wdesc, "Can't find help");
w_printlnf(wdesc, "<p>Can't find help %s</p>", wdesc->buf);
print_footer(wdesc);
return true;
return false;
}
Web_Fun(HandleDeityRequest)
{
DeityData *d;
int e;
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Deities");
w_println(wdesc,
"<table><tr><th>Name</th><th>Ethos</th><th>Description</th></tr>");
for (e = ETHOS_LAWFUL_GOOD; e != ETHOS_CHAOTIC_EVIL; e--)
for (d = deity_first; d; d = d->next)
{
if (d->ethos != (ethos_t) e)
continue;
w_printlnf(wdesc,
"<tr><td>%s</td><td>%s</td><td>%s</td></tr>",
d->name, flag_string(ethos_types, d->ethos),
d->desc);
}
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
else
{
for (d = deity_first; d; d = d->next)
{
if (!str_cmp(d->name, wdesc->buf))
{
HelpData *pHelp;
print_header(wdesc, d->name);
if ((pHelp = help_lookup(d->name)) != NULL)
{
w_printlnf(wdesc, "<p>%s</p><br>",
html_colorconv(pHelp->text));
}
else
w_println(wdesc, "<p>No Info Available</p><br>");
print_footer(wdesc);
return true;
}
}
}
return false;
}
Web_Fun(HandleRaceRequest)
{
RaceData *race;
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Races");
w_println(wdesc, "<table><tr>");
w_println(wdesc, "<th>Race</th>");
w_printlnf(wdesc,
"<th>Str</th><th>Int</th><th>Wis</th><th>Dex</th><th>Con</th>");
w_println(wdesc, "<th>Creation<br>Points</th></tr>");
for (race = race_first; race != NULL; race = race->next)
{
if (!race->pc_race)
continue;
w_println(wdesc, "<tr>");
w_printlnf(wdesc,
"<td><a href='%s" "'>%s</a></td>" LF "<td>%d</td>" LF
"<td>%d</td>" LF "<td>%d</td>" LF "<td>%d</td>" LF
"<td>%d</td><td align='center'>%d</td></tr>",
HTTP_URL(RACE_URL_PREFIX "/%s", race->name),
race->name, race->max_stats[STAT_STR],
race->max_stats[STAT_INT], race->max_stats[STAT_WIS],
race->max_stats[STAT_DEX], race->max_stats[STAT_CON],
race->points);
}
w_println(wdesc, "</table>");
w_printlnf(wdesc,
"<p>Creation points increase the amount of experience it takes to gain a level. Maximum a stat can go is 30.</p>");
w_printlnf(wdesc,
"<p>To view skills and spells available to each race, visit the <a href='%s'>Skill/Spell</a> section.</p>",
HTTP_URL("spells#RaceSkills"));
print_footer(wdesc);
return true;
}
else
{
for (race = race_first; race; race = race->next)
{
if (!str_cmp(race->name, wdesc->buf))
{
HelpData *pHelp;
print_header(wdesc, race->name);
if ((pHelp = help_lookup(race->name)) != NULL)
{
w_printlnf(wdesc, "<p>%s</p><br>",
html_colorconv(pHelp->text));
}
else
w_println(wdesc, "<p>No Info Available</p><br>");
print_footer(wdesc);
return true;
}
}
}
return false;
}
Web_Fun(HandleClanRequest)
{
ClanData *clan;
char i[MSL], j[MSL];
ClanMember *pmbr;
int e;
print_header(wdesc, "Clans");
w_println(wdesc, "<table>");
w_println(wdesc,
"<tr><th>Name</th><th>Ethos</th><th>Description</th><th>Leaders</th></tr>");
for (e = ETHOS_LAWFUL_GOOD; e != ETHOS_CHAOTIC_EVIL; e--)
for (clan = clan_first; clan; clan = clan->next)
{
if (clan->ethos != (ethos_t) e)
continue;
i[0] = '\0';
j[0] = '\0';
for (pmbr = mbr_first; pmbr != NULL; pmbr = pmbr->next)
{
if (pmbr->clan != clan || pmbr->rank != (MAX_RANK - 1))
continue;
sprintf(j, " %s,", pmbr->name);
strcat(i, j);
}
if (!NullStr(i))
{
i[strlen(i) - 1] = '\0';
w_printlnf(wdesc,
"<tr><td>%s%s</td><td>%s</td><td>%s</td><td>%s</td></tr>",
html_colorconv(clan->who_name),
flag_string(ethos_types, clan->ethos),
html_colorconv(clan->description), i);
}
else
w_printlnf(wdesc,
"<tr><td>%s</td><td>%s</td><td>%s</td><td>None</td></tr>",
html_colorconv(clan->who_name),
flag_string(ethos_types, clan->ethos),
html_colorconv(clan->description));
}
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
Web_Fun(HandleClassRequest)
{
int i;
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Classes");
w_println(wdesc, "<table>");
w_println(wdesc, "<tr><th>Name</th><th>Description</th></tr>");
for (i = 0; i < top_class; i++)
{
w_printlnf(wdesc,
"<tr><td><a href='%s'>%s</a>" "</td><td>%s</td></tr>",
HTTP_URL(CLASS_URL_PREFIX "/%s",
class_table[i].name[0]),
class_table[i].name[0], class_table[i].description);
}
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
else
{
for (i = 0; i < top_class; i++)
{
if (!str_cmp(class_table[i].name[0], wdesc->buf))
{
char buf3[MSL];
char skill_list[MAX_MORTAL_LEVEL + 1][MSL];
int snc, lev;
HelpData *pHelp;
print_header(wdesc, class_table[i].name[0]);
if ((pHelp = help_lookup(class_table[i].name[0])) != NULL)
{
w_printlnf(wdesc, "<table><tr><td>%s</td></tr></table>",
html_colorconv(pHelp->text));
}
w_println(wdesc, "<table>");
for (lev = 0; lev < MAX_MORTAL_LEVEL + 1; lev++)
skill_list[lev][0] = '\0';
for (snc = 0; snc < top_skill; snc++)
{
if (skill_table[snc].name == NULL)
break;
if ((lev = skill_table[snc].skill_level[i]) <=
MAX_MORTAL_LEVEL)
{
sprintf(buf3, "%s, ", skill_table[snc].name);
if (NullStr(skill_list[lev]))
sprintf(skill_list[lev],
"<tr><td>Level %d</td><td>%s", lev, buf3);
else
strcat(skill_list[lev], buf3);
}
}
for (lev = 0; lev < MAX_MORTAL_LEVEL + 1; lev++)
{
if (skill_list[lev][0] != '\0')
{
if (strlen(skill_list[lev]) > 2)
skill_list[lev][(strlen(skill_list[lev]) - 2)] =
'\0';
w_println(wdesc, skill_list[lev]);
w_println(wdesc, "</td></tr>");
}
}
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
}
}
return false;
}
Web_Fun(HandleNotesRequest)
{
int pos = 0;
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Notes");
w_println(wdesc, "<ul>");
for (pos = 0; pos < MAX_BOARD; pos++)
{
if (IsSet(boards[pos].flags, BOARD_NOWEB))
continue;
w_printlnf(wdesc, "<li><a href='%s'>%s</a>",
HTTP_URL(NOTE_URL_PREFIX "/%s",
boards[pos].short_name),
boards[pos].short_name);
}
w_println(wdesc, "</ul>");
print_footer(wdesc);
return true;
}
else
{
for (pos = 0; pos < MAX_BOARD; pos++)
{
if (IsSet(boards[pos].flags, BOARD_NOWEB))
continue;
if (!str_cmp(boards[pos].short_name, wdesc->buf))
{
BoardData *board = &boards[pos];
NoteData *pnote;
char buf2[MSL * 5];
sprintf(buf2, "Notes on %s Board", board->short_name);
print_header(wdesc, buf2);
for (pnote = board->note_first; pnote != NULL;
pnote = pnote->next)
{
if (!is_name("all", pnote->to_list))
continue;
w_printlnf(wdesc,
"<table><tr><td>From: %s</td><td>To: %s</td></tr><tr><td>Subject: %s</td>"
"<td>Date: %s</td></tr>", pnote->sender,
pnote->to_list, pnote->subject, pnote->date);
w_printlnf(wdesc,
"<tr><td colspan=2><hr>%s<hr></td><tr></table><br>",
html_colorconv(pnote->text));
}
print_footer(wdesc);
return true;
}
}
}
return false;
}
Web_Fun(HandleObjsRequest)
{
ObjIndex *pObj;
if (!NullStr(wdesc->buf))
{
if (!is_number(wdesc->buf))
{
return false;
}
if ((pObj = get_obj_index(atov(wdesc->buf))) != NULL)
{
print_header(wdesc, strip_color(pObj->short_descr));
w_printlnf(wdesc, "<p>%s<br>", html_colorconv(pObj->short_descr));
w_printlnf(wdesc, "%s<br>", html_colorconv(pObj->description));
w_printlnf(wdesc, "Material: %s<br>", pObj->material);
w_printlnf(wdesc, "Type: %s<br></p>",
flag_string(type_flags, pObj->item_type));
print_footer(wdesc);
return true;
}
}
return false;
}
Web_Fun(HandleMobsRequest)
{
CharIndex *pMob;
if (!NullStr(wdesc->buf))
{
if (!is_number(wdesc->buf))
{
return false;
}
if ((pMob = get_char_index(atov(wdesc->buf))) != NULL)
{
print_header(wdesc, strip_color(pMob->short_descr));
w_printlnf(wdesc, "<p>%s<br>", html_colorconv(pMob->short_descr));
w_printlnf(wdesc, "%s<br>", html_colorconv(pMob->description));
w_printlnf(wdesc, "Race: %s<br>", pMob->race->name);
w_printlnf(wdesc, "Sex: %s<br>",
flag_string(sex_flags, pMob->sex));
w_printlnf(wdesc, "Alignment: %d<br>", pMob->alignment);
w_println(wdesc, "</p>");
print_footer(wdesc);
return true;
}
}
return false;
}
char *make_exit_link(ExitData * pexit, int door)
{
return FORMATF("<a href='%s'>%s</a>",
HTTP_URL(ROOM_URL_PREFIX "/%ld", pexit->u1.to_room->vnum),
dir_name[door]);
}
void HandleRoomExit(WebDescriptor * wdesc, const char *td1, const char *td2,
const char *td3)
{
w_printlnf(wdesc,
"<td align=\"right\">%s</td><td align=\"center\">%s</td><td align=\"left\">%s</td></tr><tr>",
td1, td2, td3);
}
Web_Fun(HandleRoomsRequest)
{
RoomIndex *pRoom;
vnum_t vnum;
if (NullStr(wdesc->buf))
{
vnum = ROOM_VNUM_TEMPLE;
}
else
{
if (!is_number(wdesc->buf))
{
return false;
}
vnum = atov(wdesc->buf);
}
if ((pRoom = get_room_index(vnum)) != NULL)
{
if (!IsSet(pRoom->area->area_flags, AREA_CLOSED | AREA_PLAYER_HOMES))
{
ExitData *pexit, *pexit2;
int door, d;
bool found = false;
const int dirs[MAX_DIR] =
{ DIR_UP, DIR_NORTH, DIR_EAST, DIR_WEST, DIR_SOUTH,
DIR_DOWN
};
print_header(wdesc, pRoom->name);
w_println(wdesc, "<table><tr><td alig=\"left\">");
w_println(wdesc, html_colorconv(pRoom->name));
w_printlnf(wdesc, "</td><td align=\"right\">%s",
pRoom->area->name);
w_printlnf(wdesc, "</td></tr><tr><td align=\"left\">");
w_println(wdesc, html_colorconv(pRoom->description));
w_println(wdesc, "</td><td align=\"right\"><table><tr>");
for (d = 0; d < MAX_DIR; d++)
{
door = dirs[d];
if ((pexit = pRoom->exit[door]) != NULL
&& pexit->u1.to_room != NULL)
{
switch (door)
{
default:
HandleRoomExit(wdesc, "",
make_exit_link(pexit, door), "");
break;
case DIR_EAST:
if (!found)
{
if ((pexit2 = pRoom->exit[rev_dir[door]])
&& pexit2->u1.to_room)
{
HandleRoomExit(wdesc,
make_exit_link(pexit,
door), "",
make_exit_link(pexit2,
rev_dir
[door]));
}
else
HandleRoomExit(wdesc,
make_exit_link(pexit,
door), "",
"");
found = true;
}
break;
case DIR_WEST:
if (!found)
{
if ((pexit2 = pRoom->exit[rev_dir[door]])
&& pexit2->u1.to_room)
{
HandleRoomExit(wdesc,
make_exit_link(pexit2,
rev_dir
[door]), "",
make_exit_link(pexit,
door));
}
else
HandleRoomExit(wdesc, "", "",
make_exit_link(pexit,
door));
found = true;
}
break;
}
}
else
w_println(wdesc, "<td colspan=\"3\"></td></tr><tr>");
}
w_printlnf(wdesc,
"</tr></table></tr><tr><td colspan=\"2\">%s</td>",
show_list_to_html(pRoom->content_first));
w_printlnf(wdesc, "</tr><tr><td colspan=\"2\">%s</td>",
show_char_to_html(pRoom->person_first));
w_println(wdesc, "</tr></table>");
print_footer(wdesc);
return true;
}
}
return false;
}
Web_Fun(HandleChangesRequest)
{
int i;
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Recent Changes");
w_println(wdesc, "<table><tr><th>Date</th><th>Change</th></tr>");
for (i = 0; i < top_change; i++)
{
w_printlnf(wdesc, "<tr><td>%d)</td>", i + 1);
w_printlnf(wdesc, "<td><I>%s</I></td><td>%s</td></tr>",
str_time(change_table[i].time, -1, "%D"),
html_colorconv(change_table[i].change));
}
w_println(wdesc, "</table>");
w_printlnf(wdesc, "<p>%d changes found.</p>", top_change);
w_printlnf(wdesc, "<p>Check <a href=\"%s\">old</a> changes.</p>\n",
HTTP_URL(CHANGE_URL_PREFIX "/old"));
print_footer(wdesc);
return true;
}
else if (!str_prefix("old", wdesc->buf))
{
struct dirent **clist;
int i = 0, o;
int count = 0;
if (!str_cmp(wdesc->buf, "old") || !str_cmp(wdesc->buf, "old/"))
{
print_header(wdesc, "Changes History");
o = scandir(DATA_DIR "oldchanges/", &clist, 0, alphasort);
for (i = 0; i != o; i++)
{
if (!str_prefix("changes", clist[i]->d_name))
{
if (count == 0)
{
w_println(wdesc, "<ul>");
}
w_printlnf(wdesc, "<li><a href=\"%s\">%s</a>\n",
HTTP_URL(CHANGE_URL_PREFIX "/old/%s",
clist[i]->d_name), clist[i]->d_name);
count++;
}
}
if (count == 0)
w_println(wdesc, "<li>No old changes available.</ul>");
else
w_println(wdesc, "</ul>");
print_footer(wdesc);
return true;
}
wdesc->buf = get_next(wdesc->buf, wdesc->baseurl);
if (!NullStr(wdesc->buf))
{
o = scandir(DATA_DIR "oldchanges/", &clist, 0, alphasort);
for (i = 0; i != o; i++)
{
if (!str_prefix("changes.", clist[i]->d_name)
&& !str_cmp(wdesc->buf, clist[i]->d_name))
{
ChangeData *old_change_table = NULL, old_change_zero;
int top_old_change = 0, c;
DataTable *old_change_data_table = change_data_table;
char file[MIL];
sprintf(file, DATA_DIR "oldchanges/%s", clist[i]->d_name);
rw_table(act_read, file, ChangeData, old_change);
count++;
print_header(wdesc, FORMATF("Changes History %d"));
w_println(wdesc, "<table>");
w_printf(wdesc,
"<tr><th>Date</th><th>Change</th></tr>\n");
for (c = 0; c < top_old_change; c++)
{
w_printlnf(wdesc, "<tr><td>%d)</td>", c + 1);
w_printlnf(wdesc,
"<td><I>%s</I></td><td>%s</td></tr>",
str_time(old_change_table[c].time, -1,
"%D"),
html_colorconv(old_change_table
[c].change));
free_string(old_change_table[c].change);
free_string(old_change_table[c].coder);
}
w_println(wdesc, "</table>");
w_printlnf(wdesc, "<p>%d changes found.</p>",
top_old_change);
free_mem(old_change_table);
print_footer(wdesc);
return true;
}
}
}
}
return false;
}
Web_Fun(HandleSocialsRequest)
{
SocialData *iSocial;
int i = 0;
print_header(wdesc, "Socials");
w_println(wdesc, "<table><tr>");
for (iSocial = social_first; iSocial; iSocial = iSocial->next)
w_printlnf(wdesc, "%s<td>%s</td>", i++ % 5 == 0 ? "</tr><tr>" : "",
iSocial->name);
w_printlnf(wdesc, "%s</table>", i % 5 != 0 ? "</tr>" : "");
print_footer(wdesc);
return true;
}
crs_t crs_lookup(const char *name)
{
switch (strswitch(name, "copyover", "reboot", "shutdown", NULL))
{
default:
return CRS_NONE;
case 1:
return CRS_COPYOVER;
case 2:
return CRS_REBOOT;
case 3:
return CRS_SHUTDOWN;
}
}
void web_login_menu(WebDescriptor * wdesc, WebpassData * info)
{
w_printlnf(wdesc,
"<hr><p>Welcome %s! You security level is %d.</p><ul><li><a href=\"%s\">Change password</a>",
info->name, info->level,
HTTP_URL(LOGIN_URL_PREFIX "/changepass"));
w_println(wdesc, "</ul><hr>");
}
Web_Fun(HandleImmRequest)
{
WebpassData *info;
if ((info = get_name_password(wdesc, LEVEL_IMMORTAL)) != NULL)
{
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Immortal Info Page");
web_login_menu(wdesc, info);
w_printlnf(wdesc,
"<ul><li><a href='%s'>Skill Debug List</a></li>",
HTTP_URL(ADMIN_URL_PREFIX "/skdebug"));
w_printlnf(wdesc, "<li><a href='%s'>Log Files</a></li>",
HTTP_URL(ADMIN_URL_PREFIX "/log"));
w_printlnf(wdesc,
"<li><a href=\"%s\">Immortal Help Files</a></li>",
HTTP_URL(ADMIN_URL_PREFIX "/ihelps"));
w_printlnf(wdesc, "<li><a href=\"%s\">Webserver Users</a></li>",
HTTP_URL(ADMIN_URL_PREFIX "/users"));
w_printlnf(wdesc,
"<li>Game Control<ul><li><a href=\"%s\">Copyover</a></li>",
HTTP_URL(ADMIN_URL_PREFIX "/copyover"));
w_printlnf(wdesc,
"<li><a href=\"%s\">Reboot</a></li><li><a href=\"%s\">Shutdown</a></li></ul>",
HTTP_URL(ADMIN_URL_PREFIX "/reboot"),
HTTP_URL(ADMIN_URL_PREFIX "/shutdown"));
w_println(wdesc, "<hr>");
print_footer(wdesc);
return true;
}
else
{
crs_t stat;
if (!str_prefix("skdebug", wdesc->buf))
{
int i, sn;
print_header(wdesc, "Skill List");
w_println(wdesc, "<table><tr><td>Skill Name</td>");
for (i = 0; i < top_class; i++)
w_printlnf(wdesc, "<td>%s</td>", class_table[i].name[0]);
w_println(wdesc, "</tr>");
for (sn = 0; sn < top_skill; sn++)
{
w_printlnf(wdesc, "<tr><td>%s</td>",
skill_table[sn].name);
for (i = 0; i < top_class; i++)
{
if (skill_table[sn].skill_level[i] >= LEVEL_IMMORTAL)
w_println(wdesc, "<td>---</td>");
else
w_printlnf(wdesc, "<td>%d</td>",
skill_table[sn].skill_level[i]);
}
w_println(wdesc, "</tr>");
}
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
else if (!str_prefix("users", wdesc->buf))
{
WebpassData *pwd;
print_header(wdesc, "WebServer Users");
if (!wpwd_first)
w_println(wdesc, "<p><B>No users at this time.</B></p>");
else
{
w_printlnf(wdesc,
"<table><tr><th>Name</th><th>Level</th></tr>");
for (pwd = wpwd_first; pwd; pwd = pwd->next)
w_printlnf(wdesc,
"<tr><td><a href=\"%s\">%s</a></td><td>%d</td></tr>",
HTTP_URL(LOGIN_URL_PREFIX "/changepass"),
pwd->name, pwd->level);
w_println(wdesc, "</table>");
}
print_footer(wdesc);
return true;
}
else if (!str_prefix("log", wdesc->buf))
{
char buf2[MSL];
struct dirent **Dir;
int o, i;
wdesc->buf = get_next(wdesc->buf, wdesc->baseurl);
if (NullStr(wdesc->buf))
{
char buff[MSL];
int count = 0;
print_header(wdesc, "Log Files");
w_println(wdesc, "<table><tr>");
o = scandir(LOG_DIR, &Dir, 0, alphasort);
for (i = 0; i != o; i++)
{
if (!str_suffix(".log", Dir[i]->d_name))
{
strcpy(buff, Dir[i]->d_name);
buff[strlen(buff) - 4] = '\0';
w_printlnf(wdesc,
"%s<td><a href='%s'>%s</a></td>",
count % 5 == 0 ? "</tr><tr>" : "",
HTTP_URL(ADMIN_URL_PREFIX "/log/%s",
buff), Dir[i]->d_name);
count++;
}
}
w_printlnf(wdesc, "%s</table>",
count % 5 != 0 ? "</tr>" : "");
print_footer(wdesc);
return true;
}
else
{
o = scandir(LOG_DIR, &Dir, 0, alphasort);
for (i = 0; i != o; i++)
{
if (!str_suffix(".log", Dir[i]->d_name))
{
strcpy(buf2, Dir[i]->d_name);
buf2[strlen(buf2) - 4] = '\0';
if (!str_cmp(buf2, wdesc->buf))
{
print_header(wdesc, buf2);
w_println(wdesc, "<p class=\"pre\">");
sprintf(buf2, LOG_DIR "%s", Dir[i]->d_name);
print_file(wdesc, buf2);
w_println(wdesc, "</p>");
print_footer(wdesc);
return true;
}
}
}
}
return false;
}
else if (!str_prefix("ihelps", wdesc->buf))
{
HelpData *pHelp;
int count = 0, check = 0;
print_header(wdesc, "Immortal Help Files");
w_println(wdesc, "<table>");
for (pHelp = help_first; pHelp != NULL; pHelp = pHelp->next)
{
count++;
if (pHelp->level >= LEVEL_IMMORTAL || pHelp->level < 0)
{
const char *temp2;
char wordkey[MSL];
temp2 = pHelp->keyword;
while (!NullStr(temp2))
{
wordkey[0] = NUL;
temp2 = one_argument(temp2, wordkey);
w_printlnf(wdesc,
"%s<td><a href=\"%s\">%s</a></td>\n",
(check == 0) ? "<tr>" : "",
HTTP_URL(HELP_URL_PREFIX "/%d", count),
wordkey);
if (++check % 5 == 0)
{
w_print(wdesc, "</tr>");
check = 0;
}
}
}
}
w_println(wdesc, "</table>");
print_footer(wdesc);
return true;
}
else if ((stat = crs_lookup(wdesc->buf)) != CRS_NONE)
{
Proto(const char *crs_type_name, (crs_t));
ProtoNoR(void crs_fun, (crs_t));
meta_refresh = 5;
meta_location = HTTP_URL(NULL);
print_header(wdesc,
FORMATF("Sending %s Request...",
crs_type_name(stat)));
w_printlnf(wdesc, "Sending %s Request now... please wait.",
crs_type_name(stat));
print_footer(wdesc);
crs_info.timer = 1;
crs_info.status = stat;
replace_str(&crs_info.who, "an admin web request");
crs_fun(stat);
}
}
return false;
}
else
{
print_header(wdesc, "Invalid Username/Password");
w_printlnf(wdesc,
"<p>You're Username and Password should be your,"
" Character name on the mud, and the password you set\n"
" with the 'webpass' command. Each field is Case Sensitive.</p>");
print_footer(wdesc);
return true;
}
}
Web_Fun(HandlePlayersRequest)
{
WebpassData *info;
if ((info = get_name_password(wdesc, 1)))
{
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Players Page");
w_printlnf(wdesc,
"<blockquote>Welcome %s, I'm glad you were able to logon!"
" In a continuing effort to bring players of %s"
" closer together, you"
" can now mark your place on our website. Choose one of the options below."
"</blockquote>", info->name, mud_info.name);
web_login_menu(wdesc, info);
print_footer(wdesc);
return true;
}
else
{
if (!str_prefix("changepass", wdesc->buf))
{
WebpassData *wp;
char *opass, *npass, *cpass, *uname;
if (!str_cmp(wdesc->buf, "changepass")
|| !str_cmp(wdesc->buf, "changepass/"))
{
print_header(wdesc,
FORMATF("Change password for %s",
info->name));
w_printlnf(wdesc, "<form method=\"get\" action=\"%s\">",
HTTP_URL(LOGIN_URL_PREFIX "/changepass/%s",
info->name));
w_println(wdesc,
"<table><tr><td>Old Password</td><td><input maxLength=\"50\" size=\"35\" name=\"oldpwd\"></td></tr>");
w_println(wdesc,
"<tr><td>New Password</td><td><input maxLength=\"50\" size=\"35\" name=\"newpwd\"></td></tr>");
w_println(wdesc,
"<tr><td>Confirm Password</td><td><input maxLenght=\"50\" size=\"35\" name=\"confirmpwd\"></td></tr>");
w_println(wdesc,
"<tr><td><input type=\"submit\" value=\"Submit\" />");
w_println(wdesc,
"</td><td><input type=\"reset\" value=\"Clear Form\" />");
w_println(wdesc, "</td></tr></table>");
w_printlnf(wdesc,
"<input type=\"hidden\" name=\"player\" value=\"%s\">",
info->name);
w_println(wdesc, "</form>");
print_footer(wdesc);
return true;
}
opass = substr(wdesc->buf, "oldpwd=", "&");
npass = substr(wdesc->buf, "newpwd=", "&");
cpass = substr(wdesc->buf, "confirmpwd=", "&");
uname = substr(wdesc->buf, "player=", "&");
if (NullStr(opass) || NullStr(npass) || NullStr(cpass)
|| NullStr(uname))
{
http_status(wdesc, 500);
send_content(wdesc, CONTENT_HTML);
w_println(wdesc, "Internal Server Error.");
return true;
}
for (wp = wpwd_first; wp; wp = wp->next)
{
if (!str_cmp(uname, wp->name))
{
Base64Decode(opass, (unsigned char *) wp->name, MIL);
Base64Decode(npass, (unsigned char *) wp->name, MIL);
Base64Decode(cpass, (unsigned char *) wp->name, MIL);
meta_refresh = 10;
meta_location =
HTTP_URL(get_prev(wdesc->path, wdesc->baseurl));
if (info->level < MAX_LEVEL
&& str_casecmp(wp->passw, crypt(opass, wp->name)))
{
print_header(wdesc, "Old password doesn't match");
w_println(wdesc,
"The old password provided does not match.");
print_footer(wdesc);
return true;
}
if (str_casecmp(npass, cpass))
{
print_header(wdesc, "New passwords don't match");
w_println(wdesc,
"The new password does not match the confirmed password.");
print_footer(wdesc);
return true;
}
print_header(wdesc, "Password changed");
w_printlnf(wdesc, "<p>Password changed for '%s'.",
wp->name);
print_footer(wdesc);
return true;
}
}
}
}
}
else
{
print_header(wdesc, "Invalid Username/Password");
w_printlnf(wdesc,
"<p>You're Username and Password should be your,"
" Character name on the mud, and the password you set\n"
" with the 'webpass' command. Each field is Case Sensitive.</p>\n");
print_footer(wdesc);
return true;
}
return false;
}
Web_Fun(HandleHistoryRequest)
{
int i;
bool found = false;
print_header(wdesc, "Channel History");
w_println(wdesc, "<p class=\"pre\">");
for (i = (www_index + 1) % 20; i != www_index; i = (i + 1) % 20)
{
if (!NullStr(www_history[i]))
{
found = true;
w_printlnf(wdesc, "%s", strip_color(www_history[i]));
}
}
if (!NullStr(www_history[www_index]))
{
w_printlnf(wdesc, "%s", strip_color(www_history[www_index]));
found = true;
}
if (!found)
w_println(wdesc, "None.");
else
w_printlnf(wdesc, LF "Current time: %s.",
str_time(-1, -1, "%I:%M:%S %p"));
w_println(wdesc, "</p>");
print_footer(wdesc);
return true;
}
Web_Fun(HandleIndexRequest)
{
print_header(wdesc, NULL);
w_println(wdesc,
"<img src=\"http://www.firstmud.com/images/firstmud_greet.jpg\" alt=\"Welcome to 1stMud\">");
w_printlnf(wdesc, "<p>Current time is %s.</p>", str_time(-1, -1, NULL));
w_printlnf(wdesc, "<p>%s started up at %s (%s ago).</p>", mud_info.name,
str_time(boot_time, -1, NULL),
timestr(current_time - boot_time, false));
w_printlnf(wdesc,
"<p>The in game time is %d o'clock %s, Day of %s, %s the Month of %s, year %d.</p>",
(time_info.hour % (HOURS_IN_DAY / 2) ==
0) ? (HOURS_IN_DAY / 2) : time_info.hour % (HOURS_IN_DAY / 2),
time_info.hour >= (HOURS_IN_DAY / 2) ? "pm" : "am",
day_name[(time_info.day + 1) % DAYS_IN_WEEK],
ordinal_string(time_info.day + 1), month_name[time_info.month],
time_info.year);
w_printlnf(wdesc,
"<p>Connect to %s: <a href='telnet://%s:%d/'>telnet://%s:%d/"
"</a></p>", mud_info.name, HOSTNAME, mainport, HOSTNAME,
mainport);
if (crs_info.timer > -1 && crs_info.status != CRS_NONE)
w_printlnf(wdesc, "<p>%s</p>", crs_sprintf(true, false));
else if (mud_info.last_copyover)
w_printlnf(wdesc, "<p>Last copyover was %s ago.</p>",
timestr(current_time - mud_info.last_copyover, false));
if (mud_info.longest_uptime)
w_printlnf(wdesc, "<p>Longest uptime was %s.</p>",
timestr(mud_info.longest_uptime, false));
if (war_info.status == WAR_OFF)
w_printlnf(wdesc, "<p>The next global war starts in %s.",
intstr(war_info.timer, "minute"));
else
w_printlnf(wdesc,
"<p>There is %s left in the %s war for levels %d to %d.</p>",
intstr(war_info.timer, "minute"),
wartype_name(war_info.wartype, false), war_info.min_level,
war_info.max_level);
if (gquest_info.running == GQUEST_OFF)
w_printlnf(wdesc, "<p>The next global quest starts in %s.",
intstr(gquest_info.timer, "minute"));
else
w_printlnf(wdesc,
"<p>There is %s left in the global quest for levels %s to %d (%d targets).",
intstr(gquest_info.timer, "minute"), gquest_info.minlevel,
gquest_info.maxlevel, gquest_info.mob_count);
if (auction_first)
{
AuctionData *auc, *auc_next;
w_println(wdesc, "<p><h4>Auction - Current List of Inventory</h4>");
w_println(wdesc,
"<table><th>Num</th><th>Seller</th><th>Buyer</th><th>Item Description Lvl</th><th>Last Bid</th><th>Time</th></tr>");
for (auc = auction_first; auc; auc = auc_next)
{
auc_next = auc->next;
if (!auc->item)
{
reset_auc(auc, true);
continue;
}
w_printlnf(wdesc,
"<tr><td>%d</td><td>- %s</td><td>%s</td><td>%s</td><td>%d</td><td>%ld%s</td><td>%s</td></tr>",
auc->number, GetName(auc->owner),
auc->high_bidder ? GetName(auc->high_bidder) : "None",
auc->number, html_colorconv(auc->item->short_descr),
auc->item->level, auc->bid, auc_type(auc->type, true),
format_pulse(auc->status));
}
w_println(wdesc, "</table></p>");
}
w_printlnf(wdesc,
"<p>Visit the " MUDSTRING " Homepage at "
"<a href=\"http://www.firstmud.com/\">http://www.firstmud.com/</a>.</p>");
w_printlnf(wdesc,
"<p>%s Admin email: <a href=\"mailto:%s@%s?%s Homepage\">%s@%s</a></p>",
mud_info.name, UNAME, HOSTNAME, mud_info.name, UNAME,
HOSTNAME);
print_footer(wdesc);
return true;
}
Web_Fun(HandleUnknownRequest)
{
http_error_code = 400;
print_header(wdesc, "Error");
w_printlnf(wdesc, "<p>Unknown url '%s'.</p>", wdesc->path);
w_printf(wdesc,
"<p>For a list of url's this web server handles see the <a href=\"%s\">Index</a>.</p>\n",
HTTP_URL(NULL));
print_footer(wdesc);
return true;
}
Web_Fun(HandleNameGenRequest)
{
NameProfile *nl;
int count;
if (!name_profile_first)
{
print_header(wdesc, "Name Generator");
w_println(wdesc,
"<p>Random name generation is currently unavailable.</p>");
print_footer(wdesc);
return true;
}
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Name Generator");
w_println(wdesc, "<p>Pick a name profile:</p><ul>");
for (count = 0, nl = name_profile_first; nl; nl = nl->next, count++)
{
w_printlnf(wdesc, "<li><a href=\"%s\">%s</a>",
HTTP_URL(NAMEGEN_URL_PREFIX "/%d", count), nl->title);
}
w_printlnf(wdesc, "</ul>");
print_footer(wdesc);
return true;
}
else
{
for (count = 0, nl = name_profile_first; nl; nl = nl->next, count++)
{
if (!str_cmp(FORMATF("%d", count), wdesc->buf))
{
int i;
print_header(wdesc,
FORMATF("%s Names", capitalize(nl->title)));
w_println(wdesc, "<table><tr><td><ul>");
for (i = 0; i < 20; i++)
w_printlnf(wdesc, "<li>%s</li>", capitalize(genname(nl)));
w_println(wdesc, "</ul></td><td><ul>");
for (i = 0; i < 20; i++)
w_printlnf(wdesc, "<li>%s</li>", capitalize(genname(nl)));
w_println(wdesc, "</ul></td><td><ul>");
for (i = 0; i < 20; i++)
w_printlnf(wdesc, "<li>%s</li>", capitalize(genname(nl)));
w_println(wdesc, "</ul></td></tr></table>");
print_footer(wdesc);
return true;
}
}
}
return false;
}
Web_Fun(HandleLyricsRequest)
{
int i;
if (NullStr(wdesc->buf))
{
print_header(wdesc, "Lyrics");
w_println(wdesc, "<p>Please choose a song:</p><ul>");
for (i = 0; i < top_song; i++)
{
w_printlnf(wdesc, "<li><a href=\"%s\">%s</a> by %s</li>",
HTTP_URL(SONG_URL_PREFIX "/%d", i), song_table[i].name,
song_table[i].group);
}
w_println(wdesc, "</ul>");
print_footer(wdesc);
return true;
}
else
{
for (i = 0; i < top_song; i++)
{
if (!str_cmp(FORMATF("%d", i), wdesc->buf))
{
int j;
print_header(wdesc,
FORMATF("Lyrics for %s by %s",
song_table[i].name,
song_table[i].group));
w_printlnf(wdesc, "<p class=\"pre\">");
for (j = 0; j < song_table[i].lines; j++)
w_println(wdesc, song_table[i].lyrics[j]);
w_println(wdesc, "</p>");
print_footer(wdesc);
return true;
}
}
}
return false;
}
#ifndef DISABLE_I3
Web_Fun(HandleI3Request)
{
I3_MUD *mud;
int mudcount;
print_header(wdesc, "InterMUD3");
if (i3mud_first == NULL)
{
w_println(wdesc, "<p>There are no muds to list!?</p>");
print_footer(wdesc);
return true;
}
w_println(wdesc,
"<table><tr><th>Name</th><th>Type</th><th>Mudlib</th><th>Address</th><th>Port</th></tr>");
for (mudcount = 0, 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 (mud->status == 0)
continue;
mudcount++;
switch (mud->status)
{
case -1:
if (NullStr(mud->web))
w_printlnf(wdesc,
"<tr><td>%s</td><td>%s</td><td>%s</td><td>%s</td><td>%d</td></tr>",
mud->name, mud->mud_type, mud->mudlib,
mud->ipaddress, mud->player_port);
else
w_printlnf(wdesc,
"<tr><td><a href=\"%s\">%s</a></td><td>%s</td><td>%s</td><td>%s</td><td>%d</td></tr>",
mud->web, mud->name, mud->mud_type,
mud->mudlib, mud->ipaddress, mud->player_port);
break;
case 0:
w_printlnf(wdesc, "<tr><td colspan=\"5\">%s (down)</td></tr>",
mud->name);
break;
default:
w_printlnf(wdesc,
"<tr><td colspan=\"5\">%s (rebooting, back in %d seconds)</td></tr>",
mud->name, mud->status);
break;
}
}
w_printlnf(wdesc,
"<tr><td colspan=\"5\"><hr>%d total muds listed.</td></tr></table>",
mudcount);
print_footer(wdesc);
return true;
}
#endif
bool web_is_connected(void)
{
return (web_control != INVALID_SOCKET);
}
void update_web_server(void)
{
SOCKET max_fd;
WebDescriptor *current, *next;
fd_set readfds;
static struct timeval ZERO_TIME = {
0, 0
};
const char ENDREQUEST[5] = {
13, 10, 13, 10, 0
}
;
if (!web_is_connected())
return;
FD_ZERO(&readfds);
FD_SET(web_control, &readfds);
max_fd = web_control;
for (current = webdesc_first; current; current = current->next)
{
FD_SET(current->fd, &readfds);
if (max_fd < current->fd)
max_fd = current->fd;
}
select(max_fd + 1, &readfds, NULL, NULL, &ZERO_TIME);
if (FD_ISSET(web_control, &readfds))
{
socklen_t size;
struct sockaddr_in sock;
current = new_webdesc();
size = sizeof(sock);
current->request[0] = '\0';
if ((current->fd = accept(web_control, (SOCKADDR *) & sock, &size)) ==
INVALID_SOCKET)
{
socket_error("web-accept");
free_webdesc(current);
FD_CLR(web_control, &readfds);
return;
}
current->their_addr = ntohl(sock.sin_addr.s_addr);
Link(current, webdesc, next, prev);
}
for (current = webdesc_first; current; current = current->next)
{
if (FD_ISSET(current->fd, &readfds))
{
char buf[MIL];
int numbytes;
if ((numbytes = recv(current->fd, buf, sizeof(buf), 0)) == -1)
{
socket_error("web-read");
continue;
}
buf[numbytes] = '\0';
strcat(current->request, buf);
}
}
for (current = webdesc_first; current; current = next)
{
next = current->next;
if (strstr(current->request, "HTTP/1.")
&& strstr(current->request, ENDREQUEST))
handle_web_request(current);
else if (!strstr(current->request, "HTTP/1.")
&& strchr(current->request, '\n'))
handle_web_request(current);
else
{
continue;
}
closesocket(current->fd);
UnLink(current, webdesc, next, prev);
free_webdesc(current);
}
}
const struct request_type request_table[] = {
{"unknown", NULL, HandleUnknownRequest, false, false},
{"index", "Home", HandleIndexRequest, false, false},
{"online", "Online", HandleWhoRequest, false, false},
{"tech", "Tech", HandleMemoryRequest, false, false},
{"areas", "Areas", HandleAreaRequest, false, false},
{"spells", "Spells", HandleSpellsRequest, false, false},
{"rules", "Rules", HandleRulesRequest, false, false},
{"credits", "Credits", HandleCreditsRequest, false, false},
{"socials", "Socials", HandleSocialsRequest, false, false},
{HELP_URL_PREFIX, "Helps", HandleHelpsRequest, false, true},
{NOTE_URL_PREFIX, "Notes", HandleNotesRequest, false, true},
{RACE_URL_PREFIX, "Races", HandleRaceRequest, false, false},
{DEITY_URL_PREFIX, "Deities", HandleDeityRequest, false, false},
{CMD_URL_PREFIX, "Commands", HandleCommandsRequest, false, true},
{CLAN_URL_PREFIX, "Clans", HandleClanRequest, false, false},
{CLASS_URL_PREFIX, "Classes", HandleClassRequest, false, true},
{"history", "History", HandleHistoryRequest, false, false},
{STAT_URL_PREFIX, "Stats", HandleStatsRequest, false, true},
{CHANGE_URL_PREFIX, "Changes", HandleChangesRequest, false, true},
{ROOM_URL_PREFIX, "Explore", HandleRoomsRequest, false, true},
{NAMEGEN_URL_PREFIX, "Name Generator", HandleNameGenRequest, false, true},
{SONG_URL_PREFIX, "Song Lyrics", HandleLyricsRequest, false, true},
#ifndef DISABLE_I3
{"i3", "InterMUD3", HandleI3Request, false, true},
#endif
{OBJ_URL_PREFIX, NULL, HandleObjsRequest, false, true},
{CHAR_URL_PREFIX, NULL, HandleMobsRequest, false, true},
{ADMIN_URL_PREFIX, "Admin", HandleImmRequest, true, true},
{LOGIN_URL_PREFIX, "Login", HandlePlayersRequest, true, true},
{NULL, NULL, NULL, false, false}
};
void format_req(WebDescriptor * wdesc)
{
char temp[MSL];
wdesc->stuff = str_dup(first_arg(wdesc->request, temp, false));
first_arg(wdesc->stuff, temp, false);
if (temp[0] == '/')
wdesc->path = str_dup(&temp[1]);
else
wdesc->path = str_dup(temp);
wdesc->buf = get_next(wdesc->path, wdesc->baseurl);
return;
}
void handle_web_request(WebDescriptor * wdesc)
{
int i;
strcpy(crash_info.logline, "handle_web_request");
if (!strstr(wdesc->request, "GET"))
{
http_status(wdesc, 501);
send_content(wdesc, CONTENT_HTML);
w_println(wdesc, "Not Implemented");
return;
}
format_req(wdesc);
if (NullStr(wdesc->path))
{
HandleIndexRequest(wdesc);
mud_info.stats.web_requests++;
return;
}
for (i = 0; request_table[i].fun != NULL; i++)
{
if (request_table[i].secure && !strstr(wdesc->request, "HTTP/1."))
break;
if (!str_prefix(request_table[i].req, wdesc->path))
{
if ((*request_table[i].fun) (wdesc))
{
logf("WebServer: '%s' requested.", wdesc->path);
mud_info.stats.web_requests++;
return;
}
else
break;
}
}
logf("WebServer: unknown request '%s'.", wdesc->path);
HandleUnknownRequest(wdesc);
strcpy(crash_info.logline, "N/A");
}
void shutdown_web_server(void)
{
WebDescriptor *current, *next;
if (!web_is_connected())
return;
#ifdef WIN32
if (crs_info.status == CRS_COPYOVER)
return;
#endif
for (current = webdesc_first; current; current = next)
{
next = current->next;
closesocket(current->fd);
UnLink(current, webdesc, next, prev);
free_webdesc(current);
}
log_string("Closing webserver...");
closesocket(web_control);
web_control = INVALID_SOCKET;
}
#endif