/* 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.
*
* Now... On to the installation!
*/
/*
* 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.
* - Started work on web interface to help files, allowing them to be browsed
* from a web browser rather than being in MUD to read them.
* - 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()
* - Created a sorta "virtual" web directory for the webserver files to be
* actually served. This contains the usual images dir if any images are
* needed to be served from a central repository rather than generated.
* Be warned though! It WON'T follow any symlinks, I'll add that later
* with the stat function.. (maybe :)
*
* Future Possbile additions:
* - Access to general boards though web interface, prolly prevent posting but
* being able to browse and read notes to 'all' would be allowed
*/
/* Smaug 1.4 addition by Christopher Aaron Haslage (Yakkov) 9/9/99
*
* This is my first code release, I am happy... Okay, here is the skinny:
* Everything has been simplified, the HTML is external, so your webpage
* builders can build the webpages themselves. The directory is /web
*
* You can also edit web.h for file names and such as well.
*
* Everything was set at default when entered, change the pages to suit.
*
* Any questions, feel free to e-mail kilokahn@terrabox.com
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include "mud.h"
#include "web.h"
#define SECURE_WEB "../web/staff_html"
#define SECURE_URL "/staffarea" /* The secure URL. http://mud.is.here:5502SECURE_URL */
#define WEB_IMAGES "../web/images" /* for http://mud.is.here:port/images/blah.stuff */
#define AUTH_DOMAIN "Telnet Interface Staff Area" /* Secure Area Description (tell me where this is used) */
#define MAXDATA 1024
#define WEB_PASS_FILE SYSTEM_DIR "webpass.dat" /* Web Password Storage */
/*
* Added a few extra items to make it easier to customize and save time
* when making the HTML for the certain areas. -- Chris Haslage - 5/99
*/
#define WEBAUTHOR "<link rev=\"made\" href=\"mailto:kilokahn@eriecoast.com\">\n"
#define WEBBODY "<body bgcolor=\"#000000\" text=\"#ffffff\">\n"
void Base64Decode args((char *bufcoded,unsigned char *bufplain,int outbufsize));
typedef struct web_descriptor WEB_DESCRIPTOR;
struct web_descriptor {
int fd;
char request[MAXDATA*2];
struct sockaddr_in their_addr;
int sin_size;
WEB_DESCRIPTOR *next;
bool valid;
bool keepalive;
};
typedef struct web_password WEB_PASS;
struct web_password
{
WEB_PASS *next;
char *username;
char *password;
};
WEB_PASS *web_passwords;
WEB_DESCRIPTOR *web_desc_free;
void web_colourconv( char *buffer, const char *txt);
/*
* Content type stuff
* This should let us use multiple filetypes
* behind the server (graphics, html, text etc..)
* all based on suffix matching
*/
#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;
};
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 },
{ "", CONTENT_TEXT }
};
/* FUNCTION DEFS */
int send_buf (int fd, const char* buf);
void handle_web_request (WEB_DESCRIPTOR *wdesc);
void handle_web_who_request (WEB_DESCRIPTOR *wdesc);
void handle_web_main (WEB_DESCRIPTOR *wdesc);
void handle_web_unfound (WEB_DESCRIPTOR *wdesc);
void handle_web_wizlist (WEB_DESCRIPTOR *wdesc);
void handle_images (WEB_DESCRIPTOR *wdesc, char *path);
void handle_web_about (WEB_DESCRIPTOR *wdesc);
void handle_who_routine (WEB_DESCRIPTOR *wdesc);
void show_web_file (char *filename, WEB_DESCRIPTOR *wdesc);
bool check_web_pass (char *username, char *password);
void handle_secure_web (WEB_DESCRIPTOR *wdesc, char *username, char *password, char *path);
void save_webpass ( void );
WEB_DESCRIPTOR * new_web_desc (void);
void free_web_desc (WEB_DESCRIPTOR *desc);
/* The mark of the end of a HTTP/1.x request */
const char ENDREQUEST[5] = { 13, 10, 13, 10, 0 }; /* (CRLFCRLF) */
/* Externs */
int top_web_desc;
/* Locals */
WEB_DESCRIPTOR *web_descs;
int sockfd;
bool init_web(int port)
{
struct sockaddr_in my_addr;
char buf[1024];
web_descs = NULL;
web_desc_free = NULL;
sprintf(buf, "Attaching Internal Web Server to Port %d", port);
log_string(buf);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
log_string("----> Web Server: Error getting socket");
perror("web-socket");
sprintf(buf, "Web server (%d) : Failed initialization - Error getting socket", port);
// wiznet(buf, NULL, NULL, WIZ_WEB, 0, 0);
return FALSE;
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port);
my_addr.sin_addr.s_addr = htons(INADDR_ANY);
bzero(&(my_addr.sin_zero),8);
if((bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr))) == -1)
{
log_string("----> Web Server: Error binding socket");
perror("web-bind");
sprintf(buf, "Web server (%d) : Failed initialization - Error binding socket", port);
// wiznet(buf, NULL, NULL, WIZ_WEB, 0, 0);
return FALSE;
}
/* Only listen for 5 connects at once, do we really need more? */
listen(sockfd, 5);
sprintf(buf, "Web server: Initalization complete. Servering on port %d.", port);
// wiznet(buf, NULL, NULL, WIZ_WEB, 0, 0);
// sys_data.webup = TRUE;
return TRUE;
}
struct timeval ZERO_TIME = { 0, 0 };
void handle_web(void)
{
int max_fd;
WEB_DESCRIPTOR *current, *prev=NULL, *next;
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
/* it *will* be atleast sockfd */
max_fd = sockfd;
/* add in all the current web descriptors */
for(current=web_descs; current ; current = current->next)
{
FD_SET(current->fd, &readfds);
if(max_fd < current->fd)
max_fd = current->fd;
}
/* Wait for ONE descriptor to have activity */
select(max_fd+1, &readfds, NULL, NULL, &ZERO_TIME);
if(FD_ISSET(sockfd, &readfds))
{
/* NEW CONNECTION -- INIT & ADD TO LIST */
current = new_web_desc();
current->sin_size = sizeof(struct sockaddr_in);
current->request[0] = '\0';
if((current->fd = accept(sockfd, (struct sockaddr *)&(current->their_addr), &(current->sin_size))) == -1)
{
log_string("----> Web Server: Error accepting connection");
perror("web-accept");
free_web_desc(current);
FD_CLR(sockfd, &readfds);
return;
}
current->next = web_descs;
web_descs = current;
/* END ADDING NEW DESC */
}
/* DATA IN! */
for(prev = NULL, current=web_descs; current != NULL; current = next)
{
next = current->next;
if (FD_ISSET(current->fd, &readfds)) /* We Got Data! */
{
char buf[MAXDATA];
int numbytes;
if((numbytes=read(current->fd,buf,sizeof(buf))) == -1)
{
perror("web-read");
if(prev)
prev->next = next;
else
web_descs = next;
free_web_desc(current);
continue;
}
buf[numbytes] = '\0';
strcat(current->request,buf);
}
prev = current;
} /* DONE WITH DATA IN */
/* DATA OUT */
/* Hmm we want to delay this if possible, to prevent it prematurely */
for(prev= NULL, current=web_descs; current != NULL; current = next )
{
next = current->next;
if(strstr(current->request, "HTTP/1.") /* 1.x request (vernum on FIRST LINE) */
&& strstr(current->request, ENDREQUEST))
{
handle_web_request(current);
}
else if(!strstr(current->request, "HTTP/1.")
&& strchr(current->request, '\n')) /* HTTP/0.9 (no ver number) */
{
handle_web_request(current);
}
else
{
prev = current;
continue; /* Don't have full request yet! */
}
if(current->keepalive)
{
prev = current;
continue;
}
close(current->fd);
if(!prev)
{
web_descs = current->next;
}
else
{
prev->next = current->next;
}
free_web_desc(current);
} /* END DATA-OUT */
}
/* Generic Utility Function */
int send_buf(int fd, const char* buf)
{
return send(fd, buf, strlen(buf), 0);
}
int determine_type(char *path)
{
int i;
for(i=0 ; *content_types[i].suffix ; i++)
{
if(!str_suffix(content_types[i].suffix, path))
return content_types[i].type;
}
/* If we dunno, we'll use plain text then */
return CONTENT_TEXT;
}
void send_200OK(WEB_DESCRIPTOR *wdesc)
{
send_buf(wdesc->fd,"HTTP/1.1 200 OK\n");
}
void send_404UNFOUND(WEB_DESCRIPTOR *wdesc)
{
send_buf(wdesc->fd, "HTTP/1.1 404 Not Found\n");
}
void send_401UNAUTHORISED(WEB_DESCRIPTOR *wdesc, char *realm)
{
char buf[MAX_INPUT_LENGTH];
sprintf(buf, "WWW-Authenticate: Basic realm=\"%s\"\n", realm);
send_buf(wdesc->fd,"HTTP/1.1 401 Unauthorised\n");
send_buf(wdesc->fd, buf);
}
void send_content(WEB_DESCRIPTOR *wdesc, int type)
{
switch(type)
{
case CONTENT_HTML:
send_buf(wdesc->fd,"Content-type: text/html\n\n");
break;
default:
case CONTENT_TEXT:
send_buf(wdesc->fd,"Content-type: text/plain\n\n");
break;
case CONTENT_GIF:
send_buf(wdesc->fd,"Content-type: image/gif\n\n");
break;
case CONTENT_WAV:
send_buf(wdesc->fd,"Content-type: audio/x-wav\n\n");
break;
case CONTENT_GZIP:
send_buf(wdesc->fd,"Content-type: application/x-zip-compressed\n\n");
break;
case CONTENT_VRML:
send_buf(wdesc->fd,"Content-type: x-world/x-vrml\n\n");
break;
case CONTENT_CLASS:
/* send_buf(wdesc->fd,"Content-type: application/octect-stream\n\n"); */
send_buf(wdesc->fd,"Content-type: application/octet-stream\n\n");
break;
}
}
void handle_web_request(WEB_DESCRIPTOR *wdesc)
{
char buf[MAX_STRING_LENGTH];
char path[MAX_STRING_LENGTH];
char *stuff;
int addr;
stuff = one_argument(wdesc->request, path);
one_argument(stuff, path);
/* process request */
/* are we using HTTP/1.x? If so, write out header stuff.. */
if(!strstr(wdesc->request, "GET"))
{
send_buf(wdesc->fd,"HTTP/1.1 501 Not Implemented");
return;
}
else if(strstr(wdesc->request, "HTTP/1."))
{
/* Check for and handle secure area access */
if(!str_prefix(SECURE_URL, path))
{
char *where;
char encoded[MAX_INPUT_LENGTH];
char username[MAX_INPUT_LENGTH];
char *password = "";
username[0]='\0';
encoded[0]='\0';
where = strstr(stuff, "Authorization: Basic");
if(!where)
send_401UNAUTHORISED(wdesc, AUTH_DOMAIN);
else
{
where += strlen("Authorization: Basic");
where++;
for(password = encoded; *where && !isspace(*where);
where++, password++)
*password = *where;
*password = '\0';
Base64Decode(encoded, username, MAX_INPUT_LENGTH);
for(password = username; *password && *password != ':';
password++);
if(*password == ':')
{
*password = '\0';
password++;
}
}
if(!check_web_pass(username, password))
{
handle_secure_web(wdesc, "", "", path+strlen(SECURE_URL));
return;
}
else
{
handle_secure_web(wdesc, username, password, path+strlen(SECURE_URL));
return;
}
}
}
addr = ntohl( wdesc->their_addr.sin_addr.s_addr );
sprintf(buf, "Web - Request for %s recived from %d.%d.%d.%d",
path, ( addr >> 24 ) & 0xFF, ( addr >> 16 ) & 0xFF,
( addr >> 8 ) & 0xFF, ( addr ) & 0xFF);
// wiznet(buf,NULL,NULL,WIZ_WEB,0,0);
/* Handle the actual request */
if(!str_cmp(path, "/wholist") || !str_cmp(path, "/wholist.html"))
{
handle_web_who_request(wdesc);
if (sysdata.webcounter==TRUE)
{
log_string("Telnet Interface Hit: WHOLIST");
}
}
else if(!str_cmp(path, "/") || !str_cmp(path, "/index.html"))
{
handle_web_main(wdesc);
if (sysdata.webcounter==TRUE)
{
log_string("Telnet Interface Hit: INDEX");
}
}
else if(!str_cmp(path, "/wizlist") || !str_cmp(path, "/wizlist.html"))
{
handle_web_wizlist(wdesc);
if (sysdata.webcounter==TRUE)
{
log_string("Telnet Interface Hit: WIZLIST");
}
}
else if(!str_cmp(path, "/about") || !str_cmp(path, "/about.html"))
{
handle_web_about(wdesc);
if (sysdata.webcounter==TRUE)
{
log_string("Telnet Interface Hit: ABOUT");
}
}
else if(!str_prefix("/images/", path))
{
handle_images(wdesc, path+strlen("/images"));
}
else if(!str_prefix(SECURE_URL, path))
{
handle_secure_web(wdesc, "", "", path);
}
else
handle_web_unfound(wdesc);
}
void shutdown_web (void)
{
WEB_DESCRIPTOR *current,*next;
/* Close All Current Connections */
for(current=web_descs; current != NULL; current = next) {
next = current->next;
close(current->fd);
free_web_desc(current);
}
/* Stop Listening */
close(sockfd);
// sys_data.webup = FALSE;
}
void handle_web_main(WEB_DESCRIPTOR *wdesc)
{
send_200OK(wdesc);
send_content(wdesc, CONTENT_HTML);
show_web_file(PUB_INDEX, wdesc);
}
void handle_web_unfound(WEB_DESCRIPTOR *wdesc)
{
send_404UNFOUND(wdesc);
send_content(wdesc, CONTENT_HTML);
show_web_file(PUB_ERROR, wdesc);
return;
}
void handle_web_wizlist(WEB_DESCRIPTOR *wdesc)
{
char buf[MAX_STRING_LENGTH];
char colbuf[2*MAX_STRING_LENGTH];
FILE *fp;
int num = 0;
char let;
send_200OK(wdesc);
send_content(wdesc, CONTENT_HTML);
show_web_file(PUB_WIZLIST_H, wdesc);
if ( (fp = fopen( WEBWIZ_FILE, "r" )) != NULL )
{
while ( !feof(fp) )
{
while ( (let = fgetc(fp)) != EOF
&& num < (MAX_STRING_LENGTH-2))
{
if(let != '\r')
buf[num++] = let;
}
}
buf[num]='\0';
fclose(fp);
}
else
sprintf(buf, "Error opening Staff list Data file<br>\n\r");
web_colourconv(colbuf, buf);
send_buf(wdesc->fd, colbuf);
show_web_file(PUB_WIZLIST_F, wdesc);
}
/*
* Many thanks to Altrag who contributed this function! --GW
*/
char *text2html(const char *ip)
{
static struct
{
const char *text;
const char *html;
int tlen, hlen;
} convert_table[] =
{ { "<", "<" }, { ">", ">" }, { "&", "&" }, { "\"", """ },
{ " ", " " }, { NULL, NULL } };
static char buf[MAX_STRING_LENGTH*2];/* Safety here .. --GW */
char *bp = buf;
int i;
if (!convert_table[0].tlen)
{
for (i = 0; convert_table[i].text; ++i)
{
convert_table[i].tlen = strlen(convert_table[i].text);
convert_table[i].hlen = strlen(convert_table[i].html);
}
}
while (*ip)
{
for (i = 0; convert_table[i].text; ++i)
if (!strncmp(ip, convert_table[i].text, convert_table[i].tlen))
break;
if (convert_table[i].text)
{
strcpy(bp, convert_table[i].html);
bp += convert_table[i].hlen;
ip += convert_table[i].tlen;
}
else
*bp++ = *ip++;
}
*bp = '\0';
return buf;
}
char *parse_quotes(char *arg)
{
int str;
for ( str = 0; arg[str] != '\0'; str++ )
{
if ( arg[str] == '*' )
arg[str] = '"';
}
return arg;
}
void handle_web_who_request(WEB_DESCRIPTOR *wdesc)
{
send_200OK(wdesc);
send_content(wdesc, CONTENT_HTML);
show_web_file(PUB_WHOLIST_H, wdesc);
do_who(NULL,"");
handle_who_routine(wdesc);
show_web_file(PUB_WHOLIST_F, wdesc);
}
void handle_web_about(WEB_DESCRIPTOR *wdesc)
{
send_200OK(wdesc);
send_content(wdesc, CONTENT_HTML);
show_web_file(PUB_ABOUT, wdesc);
}
WEB_DESCRIPTOR *new_web_desc(void)
{
WEB_DESCRIPTOR *desc;
if(web_desc_free == NULL)
{
CREATE(desc, WEB_DESCRIPTOR, 1);
top_web_desc++;
}
else
{
desc = web_desc_free;
web_desc_free = web_desc_free->next;
}
desc->keepalive = FALSE;
desc->next = NULL;
return desc;
}
void free_web_desc(WEB_DESCRIPTOR *desc)
{
desc->next = web_desc_free;
web_desc_free = desc;
}
void handle_images(WEB_DESCRIPTOR *wdesc, char *path)
{
char buf[MAX_STRING_LENGTH];
char file[MAX_INPUT_LENGTH];
int type, fd;
void *buffer;
if(!str_cmp(path, "") || !str_cmp(path, "/"))
sprintf(file, "%s%s", WEB_IMAGES, "/index.html");
else
sprintf(file, "%s%s", WEB_IMAGES, path);
if(file[strlen(file)-2]=='/')
{
strcat(file, "index.html");
}
/* Work out the filetype so we know what we are doing */
type = determine_type(file);
fclose(fpReserve);
if((fd=open(file, O_RDONLY | O_NONBLOCK )) == -1)
{
send_404UNFOUND(wdesc);
send_content(wdesc, CONTENT_HTML);
sprintf(buf,
"<HTML><HEAD>\n" WEBAUTHOR
"<TITLE>%s Telnet Interface -- URL Not Found</TITLE>\n"
"</HEAD>\n\r" WEBBODY
"<center><b><font size=+3>%s Telnet Interface</b></font>\n"
"<br><b><font size=+3>URL Not Found</b></font>\n"
"<P>The URL, %s, that you requested could not be found.\n\r"
"<P><a href=\"./\">Go Back to the %s Telnet Interface</a>\n"
"</center></body></html>\n",
sysdata.mud_name, sysdata.mud_name, path, sysdata.mud_name );
send_buf(wdesc->fd, buf);
}
else
{
int readlen=0;
buffer = malloc(1024);
send_200OK(wdesc);
send_content(wdesc, type);
while((readlen = read(fd, buffer, 1024)) > 0)
send(wdesc->fd, buffer, readlen, 0);
close(fd);
free(buffer);
}
fpReserve = fopen(NULL_FILE, "r");
return;
}
void handle_secure_web(WEB_DESCRIPTOR *wdesc, char *username,
char *password, char *path)
{
char file[MAX_INPUT_LENGTH];
int type, fd;
void *buffer;
if(username[0]=='\0' || password[0]=='\0')
{
send_401UNAUTHORISED(wdesc, "Telnet Interface Staff Area");
return;
}
if (sysdata.webcounter==TRUE)
{
log_string("Telnet Interface Hit: STAFF AREA");
}
if(!str_cmp(path, "") || !str_cmp(path, "/"))
sprintf(file, "%s%s", SECURE_WEB, "/index.html");
else
sprintf(file, "%s%s", SECURE_WEB, path);
if(file[strlen(file)-2]=='/')
{
strcat(file, "index.html");
}
/* Work out the filetype so we know what we are doing */
type = determine_type(file);
fclose(fpReserve);
if((fd=open(file, O_RDONLY | O_NONBLOCK )) == -1)
{
send_404UNFOUND(wdesc);
send_content(wdesc, CONTENT_HTML);
show_web_file(STA_ERROR, wdesc);
}
else
{
int readlen=0;
buffer = malloc(1024);
send_200OK(wdesc);
send_content(wdesc, type);
while((readlen = read(fd, buffer, 1024)) > 0)
send(wdesc->fd, buffer, readlen, 0);
close(fd);
free(buffer);
}
fpReserve = fopen(NULL_FILE, "r");
return;
}
bool check_web_pass(char *username, char *password)
{
WEB_PASS *current;
for(current = web_passwords ; current ; current = current->next)
if(!str_cmp(current->username, username))
if(!str_cmp(current->password, crypt(password, "yt")))
return TRUE;
return FALSE;
}
bool change_web_pass(char *username, char *newpass)
{
WEB_PASS *current, *new;
for(current = web_passwords ; current ; current = current->next)
if(!str_cmp(current->username, username))
break;
if(!current)
{
log_string("Creating new webpass entry...");
CREATE(new, WEB_PASS, 1);
new->username = str_dup(username);
new->password = str_dup("");
new->next = web_passwords;
web_passwords = new;
}
else
new = current;
STRFREE(new->password);
new->password = str_dup(crypt(newpass, "yt"));
save_webpass();
return TRUE;
}
void do_changewebpass(CHAR_DATA *ch, char *argument)
{
char buf[MAX_INPUT_LENGTH];
argument = one_argument(argument, buf);
if(change_web_pass(ch->name, buf))
{
send_to_char("Web password set.\n\r", ch);
}
else
{
send_to_char("There was a problem setting the web password.\n\r", ch);
}
return;
}
void save_webpass()
{
FILE *fpWebPass;
WEB_PASS *current;
if( ( fpWebPass = fopen( WEB_PASS_FILE, "w" ) ) )
{
log_string("Saving web passes");
for(current = web_passwords ; current ; current = current->next)
fprintf(fpWebPass, "WebPass %s~\n%s~\n", current->username, current->password);
fprintf(fpWebPass, "$0\n");
fclose(fpWebPass);
}
fpReserve = fopen( NULL_FILE, "r" );
}
void load_webpass()
{
FILE *fpWebPass;
fclose(fpReserve);
if( ( fpWebPass = fopen( WEB_PASS_FILE, "r" ) ) )
{
WEB_PASS *new;
char *word;
for( word = fread_word(fpWebPass) ; str_cmp(word, "$0") ; )
{
CREATE(new, WEB_PASS, 1);
new->username = fread_string(fpWebPass);
new->password = fread_string(fpWebPass);
new->next = web_passwords;
web_passwords = new;
word = fread_word(fpWebPass);
}
fclose(fpWebPass);
}
fpReserve = fopen( NULL_FILE, "r" );
}
void release_web_desc(int desc)
{
WEB_DESCRIPTOR *current;
for(current=web_descs; current ; current = current->next)
{
if(current->fd == desc)
{
current->keepalive = FALSE;
return;
}
}
}
int web_colour( char type, char *string )
{
char code[ 50 ];
char *p = '\0';
switch( type )
{
default:
// sprintf( code, "" );
break;
case 'Y':
sprintf( code, "</font><font color=#FFFF00>");
break;
case 'y':
sprintf( code, "</font><font color=#FFFF00>");
break;
case 'x':
sprintf( code, "</font><font color=#000000>" );
break;
case 'b':
sprintf( code, "</font><font color=#00007F>" );
break;
case 'c':
sprintf( code, "</font><font color=#007F7F>" );
break;
case 'g':
sprintf( code, "</font><font color=#007F00>" );
break;
case 'r':
sprintf( code, "</font><font color=#7F0000>" );
break;
case 'w':
sprintf( code, "</font><font color=#BFBFBF>" );
break;
case 'B':
sprintf( code, "</font><font color=#0000FF>" );
break;
case 'C':
sprintf( code, "</font><font color=#00FFFF>" );
break;
case 'G':
sprintf( code, "</font><font color=#00FF00>" );
break;
case 'R':
sprintf( code, "</font><font color=#FF0000>" );
break;
case 'W':
sprintf( code, "</font><font color=#FFFFFF>" );
break;
case 'z':
sprintf( code, "</font><font color=#7F7F7F>" );
break;
case 'O':
sprintf( code, "</font><font color=#7F7F00>" );
break;
case 'p':
sprintf( code, "</font><font color=#7F007F>" );
break;
case 'P':
sprintf( code, "</font><font color=#FF00FF>" );
break;
case '/':
sprintf( code, "<br>" );
break;
case '{':
sprintf( code, "%c", '{' );
break;
case '-':
sprintf( code, "%c", '~' );
break;
}
p = code;
while( *p != '\0' )
{
*string = *p++;
*++string = '\0';
}
return( strlen( code ) );
}
void web_colourconv( char *buffer, const char *txt)
{
const char *point;
int skip = 0;
if( txt )
{
for( point = txt ; *point ; point++ )
{
if( *point == '&' )
{
point++;
skip = web_colour( *point, buffer );
while( skip-- > 0 )
++buffer;
continue;
}
*buffer = *point;
*++buffer = '\0';
}
*buffer = '\0';
}
return;
}
/*
* This was added because of webmasters complaining on how they don't
* know how to code. So web.h was added as well as extra directories
* in ../web (public_html and staff_html). [readme.txt in ../web]
*
* The file: *.tih means 'Telnet Interface Header' (for beginning
* the html files) and *.tif 'Telnet Interface Footer' (for ending
* the html files). The middle is filled in with generated code.
*
* -- Christopher Aaron Haslage (Yakkov) -- 6/3/99 (No Help Needed)
*/
void show_web_file(char *filename, WEB_DESCRIPTOR *wdesc )
{
char buf[MAX_STRING_LENGTH];
FILE *fp;
int num = 0;
char let;
if ( (fp = fopen( filename, "r" )) != NULL )
{
while ( !feof(fp) )
{
while ( (let = fgetc(fp)) != EOF
&& num < (MAX_STRING_LENGTH-2))
{
if(let != '\r')
buf[num++] = let;
}
}
buf[num]='\0';
fclose(fp);
}
else
sprintf(buf, "\n\r<P><font color=red>\n"
"ERROR: Missing or corrupted file in the Telnet Interface!\n"
"</font><font color=white><P>\n\r");
send_buf(wdesc->fd, buf);
}
void handle_who_routine(WEB_DESCRIPTOR *wdesc)
{
FILE *fp;
char buf[MAX_STRING_LENGTH], col_buf[MAX_STRING_LENGTH];
int c;
int num = 0;
if ( (fp = fopen( WHO_FILE, "r" )) != NULL )
{
while ( !feof(fp) )
{
while ((buf[num]=fgetc(fp)) != EOF
&& buf[num] != '\n'
&& buf[num] != '\r'
&& num < (MAX_STRING_LENGTH-2))
num++;
c = fgetc(fp);
if ( (c != '\n' && c != '\r') || c == buf[num] )
ungetc(c, fp);
buf[num++] = '\n';
buf[num ] = '\0';
if ( strlen(buf) > 32000 )
{
bug("Strlen Greater then 32000: show_file",0);
buf[32000] = '\0';
}
num = 0;
web_colourconv(col_buf, buf);
send_buf(wdesc->fd,col_buf);
// send_buf(wdesc->fd,"<BR>");
}
fclose(fp);
}
return;
}