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