/* * IMC2 - an inter-mud communications protocol * * webclient.c: CGI interface to webserver.c * * Copyright (C) 1996,1997 Oliver Jowett <oliver@jowett.manawatu.planet.co.nz> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file COPYING); if not, write to the * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * */ /* Consider this alpha code. 'nuff said */ #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <sys/un.h> #include <string.h> #include <signal.h> #include <errno.h> #define PAGE "http://www.toof.net/~imc/webclient.cgi" #define SOCKET "/home/imc/webserver-socket" #define EMAIL "oliver@jowett.manawatu.planet.co.nz" int listflag; int whoflag; int infoflag; char *mudname; int invalid; int color; char retrypath[1000]; void showerror(void) { printf("<html>\n" "<head>\n" "<link rev=\"made\" href=\"mailto:" EMAIL "\">\n" "<meta name=\"robots\" content=\"noindex\">\n" "<title>Error</title>\n" "</head>\n" "<body>\n" "<h1>Error</h1>\n" "<p>An error occured when reading from the IMC interface server.\n" "The server may be down, or your query may be invalid.\n" "You may want to <a href=\"%s\">try again</a> later.\n" "<hr>\n" "<p>Return to the <a href=\"" PAGE "?type=list\">IMC list page</a>.\n" "<p>Please contact <a href=\"mailto:" EMAIL "\">" EMAIL "</a> " "with any problems with this gateway.\n" "</body>\n" "</html>\n", retrypath); } void showinternalerror(void) { printf("<html>\n" "<head>\n" "<link rev=\"made\" href=\"mailto:" EMAIL "\">\n" "<meta name=\"robots\" content=\"noindex\">\n" "<title>Internal error</title>\n" "</head>\n" "<body>\n" "<h1>Internal Error</h1>\n" "<p>An internal error occured within the CGI software.\n" "The server may be overloaded. You may want to " "<a href=\"%s\">try again</a> later.\n" "<hr>\n" "<p>Return to the <a href=\"" PAGE "?type=list\">IMC list page</a>.\n" "<p>Please contact <a href=\"mailto:" EMAIL "\">" EMAIL "</a> " "with any problems with this gateway.\n" "</body>\n" "</html>\n", retrypath); } struct conv_type { char *imc; char *mud; }; struct conv_type color_table[]= { { "~~", "~" }, /* escape raw tildes */ { "~b", "</font><font color=#0000DF>" }, /* blue */ { "~g", "</font><font color=#00DF00>" }, /* green */ { "~r", "</font><font color=#DF0000>" }, /* red */ { "~y", "</font><font color=#DFDF00>" }, /* yellow */ { "~m", "</font><font color=#DF00DF>" }, /* magenta */ { "~c", "</font><font color=#00DFDF>" }, /* cyan */ { "~w", "</font><font color=#DFDFDF>" }, /* white */ { "~D", "</font><font color=#6F6F6F>" }, /* grey */ { "~B", "</font><font color=#0000FF>" }, /* lt. blue */ { "~G", "</font><font color=#00FF00>" }, /* lt. green */ { "~R", "</font><font color=#FF0000>" }, /* lt. red */ { "~Y", "</font><font color=#FFFF00>" }, /* lt. yellow */ { "~M", "</font><font color=#FF00FF>" }, /* lt. magenta */ { "~C", "</font><font color=#00FFFF>" }, /* lt. cyan */ { "~W", "</font><font color=#FFFFFF>" }, /* lt. white */ { "~!", "</font><font color=#DFDFDF>" }, /* reset */ { "~d", "</font><font color=#DFDFDF>" }, /* default */ }; struct conv_type nocolor_table[]= { { "~~", "~" }, /* escape raw tildes */ { "~b", "" }, /* blue */ { "~g", "" }, /* green */ { "~r", "" }, /* red */ { "~y", "" }, /* yellow */ { "~m", "" }, /* magenta */ { "~c", "" }, /* cyan */ { "~w", "" }, /* white */ { "~D", "" }, /* grey */ { "~B", "" }, /* lt. blue */ { "~G", "" }, /* lt. green */ { "~R", "" }, /* lt. red */ { "~Y", "" }, /* lt. yellow */ { "~M", "" }, /* lt. magenta */ { "~C", "" }, /* lt. cyan */ { "~W", "" }, /* lt. white */ { "~!", "" }, /* reset */ { "~d", "" }, /* default */ }; #define numtrans (sizeof(color_table)/sizeof(color_table[0])) int handled_alarm; void alarm_handler(int sig) { handled_alarm=1; } void readfromserver(int fd) { char result[20000]; int r=0; handled_alarm=0; alarm(30); while (r<19999) { int i; i=read(fd, result+r, 19999-r); if (i<0) { #ifndef NO_EINTR if (errno==EINTR) break; #endif showerror(); return; } if (!i) { result[r]=0; break; } r+=i; } alarm(0); if (!r || handled_alarm) { printf("<html>\n" "<head>\n" "<link rev=\"made\" href=\"mailto:" EMAIL "\">\n" "<meta name=\"robots\" content=\"noindex\">\n" "<title>Timeout</title>\n" "</head>\n" "<body>\n" "<h1>Timeout</h1>\n" "<p>No response was received from the specified mud within\n" "30 seconds. The mud may be down, or the network may be having\n" "problems. You may want to <a href=\"%s\">try again</a> later.\n" "<hr>\n" "<p>Return to the <a href=\"" PAGE "?type=list\">IMC list page</a>.\n" "<p>Please contact <a href=\"mailto:" EMAIL "\">" EMAIL "</a> " "with any problems with this gateway.\n" "</body>\n" "</html>\n", retrypath); } else if (whoflag || infoflag) { char *in; struct conv_type *trans_table; printf("<html>\n" "<head>\n" "<link rev=\"made\" href=\"mailto:" EMAIL "\">\n" "<meta name=\"robots\" content=\"noindex\">\n" "<meta http-equiv=\"refresh\" content=\"900\">\n" "<title>%s %s</title>\n" "</head>\n" "<body%s>\n" "<h1>Results</h1>\n" "<pre>%s\n", whoflag ? "Results for RWHO" : "Info on", mudname, color ? " bgcolor=#000000 text=#FFFFFF" : "", color ? "<font color=#DFDFDF>" : ""); trans_table = color ? color_table : nocolor_table; for (in=result; *in; ) { if (*in=='&') { printf("&"); in++; continue; } else if (*in=='<') { printf("<"); in++; continue; } else if (*in=='>') { printf(">"); in++; continue; } else if (*in=='~') { int i, l; for (i=0; i<numtrans; i++) { l=strlen(trans_table[i].imc); if (l && !strncmp(in, trans_table[i].imc, l)) break; } if (i!=numtrans) /* match */ { printf(trans_table[i].mud); in+=l; continue; } } else if (*in=='\r') { in++; continue; } putchar(*in++); } printf("%s</pre><hr>\n" "<p>Return to the <a href=\"" PAGE "?type=list\">IMC list page</a>.\n" "<p>Please contact <a href=\"mailto:" EMAIL "\">" EMAIL "</a> " "with any problems with this gateway.\n" "</body></html>\n", color ? "</font>" : ""); } else /* list */ { char name[100], version[100]; int i, count, ping; char *in; printf("<html>\n" "<head>\n" "<link rev=\"made\" href=\"mailto:" EMAIL "\">\n" "<meta name=\"robots\" content=\"noindex\">\n" "<meta http-equiv=\"refresh\" content=\"600\">\n" "<title>IMC List</title>\n" "</head>\n" "<body>\n" "<h1>Active muds on IMC</h1>\n" "<hr>\n" "<p>Select a mud below to get information on.\n" "<p><form action=\"" PAGE "\" method=\"get\">\n" "Query type: <select name=\"type\" size=1>\n" "<p><option>Help\n" "<option selected>Who\n" "<option>Info\n" "</select>\n" "<p><input type=\"checkbox\" name=\"color\" value=\"yes\" checked>" "Use color in output\n<p>"); in=result; while(1) { i=sscanf(in, "%s %s %d\n%n", name, version, &ping, &count); if (i<3) break; in+=count; printf("<input type=\"radio\" name=\"mud\" value=\"%s\">%-20s %s<br>\n", name, name, version); } printf("<p><input type=\"submit\" value=\"Send request\">\n" "</form><hr>\n" "<p>Please contact <a href=\"mailto:" EMAIL "\">" EMAIL "</a> " "with any problems with this gateway.\n" "<p>Go to the <a href=\"http://www.toof.net/~imc/\">" "IMC2 homepage</a>.\n" "</body></html>\n"); } } /* parse the input */ char x2c(const char *what) { char digit; digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0')); digit *= 16; digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0')); return(digit); } void parse_value(const char *name, const char *value) { if (!strcasecmp(name, "type")) { if (!strcasecmp(value, "list")) listflag=1; else if (!strcasecmp(value, "who")) whoflag=1; else if (!strcasecmp(value, "info")) infoflag=1; else invalid=1; } else if (!strcasecmp(name, "mud")) mudname=strdup(value); else if (!strcasecmp(name, "color")) color=!strcasecmp(value, "yes"); else invalid=1; } void parse(const char *string) { char buf1[100], buf2[100]; char *out=buf1; int state=0; while (*string) { switch(*string) { case '%': *out++=x2c(string); string+=3; break; case '+': *out++=' '; string++; break; case '=': if (state==0) { *out=0; out=buf2; state=1; } else *out++='='; string++; break; case '&': if (state==0) { *out=0; parse_value(buf1, out); } else { *out=0; parse_value(buf1, buf2); out=buf1; state=0; } string++; break; default: *out++=*string++; break; } } if (state==1) { *out=0; parse_value(buf1, buf2); out=buf1; state=0; } } void main(int argc, char *argv[]) { int fd; struct sockaddr_un sa; char buf[200]; char *temp; signal(SIGPIPE, SIG_IGN); signal(SIGALRM, alarm_handler); printf("Content-type: text/html\n\n"); temp=getenv("QUERY_STRING"); if (!temp) { invalid=1; sprintf(retrypath, "%s?type=list", PAGE); } else { sprintf(retrypath, "%s?%s", PAGE, temp); parse(temp); } if (invalid || ((whoflag || infoflag) && !mudname)) { showerror(); exit(1); } if (!whoflag && !listflag && !infoflag) listflag=1; fd=socket(AF_UNIX, SOCK_STREAM, 0); /* DOH! and again */ if (fd<0) { showinternalerror(); exit(1); } sa.sun_family=AF_UNIX; strcpy(sa.sun_path, SOCKET); if (connect(fd, (struct sockaddr *)&sa, sizeof(sa))<0) { showerror(); exit(1); } sprintf(buf, "%s%s%s\n", listflag ? "list" : (whoflag ? "who" : "info"), listflag ? "" : " ", listflag ? "" : mudname); if (write(fd, buf, strlen(buf))<0) { showerror(); exit(1); } readfromserver(fd); close(fd); exit(0); }