/**************************************************************************** * ResortMUD 4.0 Beta by Ntanel, Garinan, Badastaz, Josh, Digifuzz, Senir, * * Kratas, Scion, Shogar and Tagith. Special thanks to Thoric, Nivek, * * Altrag, Arlorn, Justice, Samson, Dace, HyperEye and Yakkov. * **************************************************************************** * Copyright (C) 1996 - 2001 Haslage Net Electronics: MudWorld * * of Lorain, Ohio - ALL RIGHTS RESERVED * * The text and pictures of this publication, or any part thereof, may not * * be reproduced or transmitted in any form or by any means, electronic or * * mechanical, includes photocopying, recording, storage in a information * * retrieval system, or otherwise, without the prior written or e-mail * * consent from the publisher. * **************************************************************************** * GREETING must mention ResortMUD programmers and the help file named * * CREDITS must remain completely intact as listed in the SMAUG 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. * * 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 :) * - Including a IMC web module to add the functionaility of the IMC webserver * code directly into the mud itself for use here, preventing the need for * the seperate server and client processes (I know it sorta depends on the * mud be FE never stays down for long..) * * 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 */ #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 "h/merc.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 "YakTalk 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 */ void Base64Decode( 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; socklen_t 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_wwwlist_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 if( !str_cmp( current->request, "IMC" ) ) { if( current->keepalive ) { prev = current; continue; } } 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, (unsigned char *)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 ); log_string( "Counter Hit on Telnet Interface Who List." ); } else if( !str_cmp( path, "/" ) || !str_cmp( path, "/index.html" ) ) { handle_web_main( wdesc ); log_string( "Counter Hit on Telnet Interface Index." ); } else if( !str_cmp( path, "/wizlist" ) || !str_cmp( path, "/wizlist.html" ) ) { handle_web_wizlist( wdesc ); log_string( "Counter Hit on Telnet Interface Wizlist." ); } /* else if(!str_cmp(path, "/about") || !str_cmp(path, "/about.html")) handle_web_about(wdesc); 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 if(!str_prefix("/wwwlist", path)) handle_wwwlist_request(wdesc); */ 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; } /* point 1 */ void handle_web_main( WEB_DESCRIPTOR * wdesc ) { send_200OK( wdesc ); send_content( wdesc, CONTENT_HTML ); show_web_file( PUB_INDEX, wdesc ); } /* point 2 */ void handle_web_unfound( WEB_DESCRIPTOR * wdesc ) { send_404UNFOUND( wdesc ); send_content( wdesc, CONTENT_HTML ); show_web_file( PUB_ERROR, wdesc ); return; } /* point 3 */ 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>\r\n" ); 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; } /* point 4 */ 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 ); } /* point 5 */ void handle_wwwlist_request( WEB_DESCRIPTOR * wdesc ) { send_200OK( wdesc ); send_content( wdesc, CONTENT_HTML ); show_web_file( PUB_WWWLIST_H, wdesc ); do_who( NULL, "www" ); handle_who_routine( wdesc ); show_web_file( PUB_WWWLIST_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 ); if( ( fd = open( file, O_RDONLY | O_NONBLOCK ) ) == -1 ) { send_404UNFOUND( wdesc ); send_content( wdesc, CONTENT_HTML ); sprintf( buf, "<HTML><HEAD>\n" "<TITLE>Telnet Interface -- URL Not Found</TITLE>\n" "</HEAD>\r\n" "<center><b><font size=+3>Telnet Interface</b></font>\n" "<br><b><font size=+3>URL Not Found</b></font>\n" "<P>The URL that you requested could not be found.\r\n" "</center></body></html>\n" ); } 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 ); } 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, "YakTalk Staff Area" ); return; } 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 ); 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 ); } 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, sha256_crypt( password ) ) ) 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( sha256_crypt( newpass ) ); 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.\r\n", ch ); } else { send_to_char( "There was a problem setting the web password.\r\n", 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 ); fpWebPass = NULL; } } void load_webpass( ) { FILE *fpWebPass; 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 ); } } 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 '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 'y': sprintf( code, "</font><font color=#FFFF00>" ); break; case 'Y': sprintf( code, "</font><font color=#FFFF00>" ); 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=#FFFF00>" ); 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 *word; */ char let; if( ( fp = fopen( filename, "r" ) ) != NULL ) { while( !feof( fp ) ) { /******************* for ( ; ; ) { word = feof( fp ) ? "End" : fread_word( fp ); fMatch = FALSE; switch ( UPPER(word[0]) ) { case '<': *******************/ /* if ( !strcmp( word, "<!-- CODE -->")) { word = feof ( fp ) ? "End" : fread_word( fp ); sprintf(buf, "\r\n<P><font color=red>\n" "CODE IS INSERTED HERE!\n" "</font><font color=white><P>\r\n"); send_buf(wdesc->fd, buf); } */ while( ( let = fgetc( fp ) ) != EOF && num < ( MAX_STRING_LENGTH - 2 ) ) { if( let != '\r' ) buf[num++] = let; } } buf[num] = '\0'; fclose( fp ); } else sprintf( buf, "\r\n<P><font color=red>\n" "ERROR: Missing or corrupted file in the Telnet Interface!\n" "</font><font color=white><P>\r\n" ); 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; }