all: webserver webcit
+
+
webserver: webserver.o context_loop.o
- cc webserver.o context_loop.o -lpthread -o webserver
+ cc webserver.o context_loop.o \
+ -lpthread -o webserver
webserver.o: webserver.c webcit.h
- cc -c webserver.c
+ cc -c -D_REENTRANT webserver.c
context_loop.o: context_loop.c webcit.h
- cc -c context_loop.c
+ cc -c -D_REENTRANT context_loop.c
+
-webcit: webcit.o
- cc webcit.o -o webcit
+
+webcit: webcit.o auth.o tcp_sockets.o
+ cc webcit.o auth.o tcp_sockets.o -o webcit
webcit.o: webcit.c webcit.h
cc -c webcit.c
+
+auth.o: auth.c webcit.h
+ cc -c auth.c
+
+tcp_sockets.o: tcp_sockets.c webcit.h
+ cc -c tcp_sockets.c
--- /dev/null
+/*
+ * auth.c
+ *
+ * This file contains code which relates to authentication of users to Citadel.
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <errno.h>
+#include "webcit.h"
+
+void display_login_page() {
+
+ printf("HTTP/1.0 200 OK\n");
+ output_headers();
+
+ wprintf("<HTML><HEAD><TITLE>Please log in</TITLE></HEAD><BODY>\n");
+ wprintf("<TABLE border=0><TR><TD>\n");
+ wprintf("<IMG SRC=\"/static/velma.gif\">\n");
+ wprintf("</TD><TD>");
+ wprintf("<H1>"Velma"</H1><H2>(next generation WebCit)</H2>");
+ wprintf("Please log in...\n");
+ wprintf("</TD></TR></TABLE>\n");
+ wprintf("</BODY></HTML>\n");
+
+ wDumpContent();
+ }
--- /dev/null
+/*
+ * tcp_sockets.c
+ *
+ * TCP socket module for WebCit
+ *
+ * version 1.3
+ *
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdarg.h>
+#include "webcit.h"
+
+char server_is_local = 0;
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+extern int errno;
+
+int serv_sock;
+
+#ifndef DONT_PROTO_HTONS
+u_short htons();
+#endif
+u_long inet_addr();
+
+
+void timeout() {
+ printf("\rConnection timed out.\n");
+ exit(3);
+ }
+
+int connectsock(host,service,protocol)
+char *host;
+char *service;
+char *protocol; {
+ struct hostent *phe;
+ struct servent *pse;
+ struct protoent *ppe;
+ struct sockaddr_in sin;
+ int s,type;
+
+ bzero((char *)&sin,sizeof(sin));
+ sin.sin_family = AF_INET;
+
+ pse=getservbyname(service,protocol);
+ if (pse) {
+ sin.sin_port = pse->s_port;
+ }
+ else if ((sin.sin_port = htons((u_short)atoi(service))) == 0) {
+ fprintf(stderr,"can't get %s service entry: %s\n",
+ service,strerror(errno));
+ return(-1);
+ }
+
+ phe=gethostbyname(host);
+ if (phe) {
+ bcopy(phe->h_addr,(char *)&sin.sin_addr,phe->h_length);
+ }
+ else if ((sin.sin_addr.s_addr = inet_addr(host))==INADDR_NONE) {
+ fprintf(stderr,"can't get %s host entry: %s\n",
+ host,strerror(errno));
+ return(-1);
+ }
+
+ if ((ppe=getprotobyname(protocol))==0) {
+ fprintf(stderr,"can't get %s protocol entry: %s\n",
+ protocol,strerror(errno));
+ return(-1);
+ }
+
+ if (!strcmp(protocol,"udp"))
+ type = SOCK_DGRAM;
+ else
+ type = SOCK_STREAM;
+
+ s = socket(PF_INET,type,ppe->p_proto);
+ if (s<0) {
+ fprintf(stderr,"can't create socket: %s\n",strerror(errno));
+ return(-1);
+ }
+
+
+ signal(SIGALRM,timeout);
+ alarm(30);
+
+ if (connect(s,(struct sockaddr *)&sin,sizeof(sin))<0) {
+ fprintf(stderr,"can't connect to %s.%s: %s\n",
+ host,service,strerror(errno));
+ return(-1);
+ }
+
+ alarm(0);
+ signal(SIGALRM,SIG_IGN);
+
+ return(s);
+ }
+
+
+
+
+/*
+ * Input binary data from socket
+ */
+void serv_read(buf,bytes)
+char buf[];
+int bytes; {
+ int len,rlen;
+
+ len = 0;
+ while(len<bytes) {
+ rlen = read(serv_sock,&buf[len],bytes-len);
+ if (rlen<1) {
+ printf("Network error - connection terminated.\n");
+ printf("%s\n", strerror(errno));
+ exit(3);
+ }
+ len = len + rlen;
+ }
+ }
+
+
+/*
+ * input string from pipe
+ */
+void serv_gets(strbuf)
+char strbuf[]; {
+ int ch,len,rlen;
+ char buf[2];
+
+ len = 0;
+ strcpy(strbuf,"");
+ do {
+ serv_read(&buf[0], 1);
+ ch = buf[0];
+ strbuf[len++] = ch;
+ } while((ch!=10)&&(ch!=13)&&(ch!=0)&&(len<255));
+ strbuf[len-1] = 0;
+ }
+
+
+
+/*
+ * Attach to a Citadel server
+ */
+void attach_to_server(argc,argv)
+int argc;
+char *argv[]; {
+ if (argc==1) {
+ server_is_local = 1;
+ serv_sock = connectsock("localhost","citadel","tcp");
+ }
+ if (argc==2) {
+ serv_sock = connectsock(argv[1],"citadel","tcp");
+ if ( (!strcmp(argv[1],"localhost"))
+ || (!strcmp(argv[1],"127.0.0.1")) ) server_is_local = 1;
+ }
+ if (argc>=3) serv_sock = connectsock(argv[1],argv[2],"tcp");
+
+ if (serv_sock < 0) exit(errno);
+ }
+
+
+/*
+ * send binary to server
+ */
+void serv_write(buf, nbytes)
+char buf[];
+int nbytes; {
+ int bytes_written = 0;
+ int retval;
+ while (bytes_written < nbytes) {
+ retval = write(serv_sock, &buf[bytes_written],
+ nbytes - bytes_written);
+ if (retval < 1) {
+ printf("Network error - connection terminated.\n");
+ printf("%s\n", strerror(errno));
+ exit(3);
+ }
+ bytes_written = bytes_written + retval;
+ }
+ }
+
+
+/*
+ * send line to server
+ */
+void serv_puts(string)
+char *string; {
+ char buf[256];
+
+ sprintf(buf,"%s\n",string);
+ serv_write(buf, strlen(buf));
+ }
+
+
+/*
+ * convenience function to send stuff to the server
+ */
+void serv_printf(const char *format, ...) {
+ va_list arg_ptr;
+ char buf[256];
+
+ va_start(arg_ptr, format);
+ vsprintf(buf, format, arg_ptr);
+ va_end(arg_ptr);
+
+ strcat(buf, "\n");
+ serv_write(buf, strlen(buf));
+ }
+
+
int wc_session;
char wc_host[256];
-int wc_port;
+char wc_port[256];
char wc_username[256];
char wc_password[256];
char wc_roomname[256];
int TransactionCount = 0;
+int connected = 0;
int logged_in = 0;
struct webcontent *wlist = NULL;
printf("Connection: close\n");
printf("Set-cookie: wc_session=%d\n", wc_session);
if (strlen(wc_host)>0) printf("Set-cookie: wc_host=%s\n", wc_host);
- if (wc_port != 0) printf("Set-cookie: wc_port=%d\n", wc_port);
+ if (strlen(wc_port)>0) printf("Set-cookie: wc_port=%s\n", wc_port);
if (strlen(wc_username)>0) printf("Set-cookie: wc_username=%s\n",
wc_username);
if (strlen(wc_password)>0) printf("Set-cookie: wc_password=%s\n",
char buf[256];
int a;
+ /* We stuff these with the values coming from the client cookies,
+ * so we can use them to reconnect a timed out session if we have to.
+ */
+ char c_host[256];
+ char c_port[256];
+ char c_username[256];
+ char c_password[256];
+ char c_roomname[256];
+
+ strcpy(c_host, DEFAULT_HOST);
+ strcpy(c_port, DEFAULT_PORT);
+ strcpy(c_username, "");
+ strcpy(c_password, "");
+ strcpy(c_roomname, "");
+
getz(cmd);
fprintf(stderr, "Cmd: %s\n", cmd);
fflush(stderr);
do {
getz(buf);
+
+ if (!strncasecmp(buf, "Cookie: wc_host=", 16))
+ strcpy(c_host, &buf[16]);
+ if (!strncasecmp(buf, "Cookie: wc_port=", 16))
+ strcpy(c_port, &buf[16]);
+ if (!strncasecmp(buf, "Cookie: wc_username=", 20))
+ strcpy(c_username, &buf[20]);
+ if (!strncasecmp(buf, "Cookie: wc_password=", 20))
+ strcpy(c_password, &buf[20]);
+ if (!strncasecmp(buf, "Cookie: wc_roomname=", 20))
+ strcpy(c_roomname, &buf[20]);
+
} while(strlen(buf)>0);
++TransactionCount;
+ /*
+ * If we're not connected to a Citadel server, try to hook up the
+ * connection now. Preference is given to the host and port specified
+ * by browser cookies, if cookies have been supplied.
+ */
+ if (!connected) {
+ serv_sock = connectsock(c_host, c_port, "tcp");
+ connected = 1;
+ strcpy(wc_host, c_host);
+ strcpy(wc_port, c_port);
+ }
+
+ /*
+ * If we're not logged in, but we have username and password cookies
+ * supplied by the browser, try using them to log in.
+ */
+ if ((!logged_in)&&(strlen(c_username)>0)&&(strlen(c_password)>0)) {
+ serv_printf("USER %s", c_username);
+ serv_gets(buf);
+ if (buf[0]=='3') {
+ serv_printf("PASS %s", c_password);
+ serv_gets(buf);
+ if (buf[0]=='2') {
+ logged_in = 1;
+ strcpy(wc_username, c_username);
+ strcpy(wc_password, c_password);
+ }
+ }
+ }
+
+ /*
+ * If we don't have a current room, but a cookie specifying the
+ * current room is supplied, make an effort to go there.
+ */
+ if ((strlen(wc_roomname)==0) && (strlen(c_roomname)>0) ) {
+ serv_printf("GOTO %s", c_roomname);
+ serv_gets(buf);
+ if (buf[0]=='2') {
+ strcpy(wc_roomname, c_roomname);
+ }
+ }
+
if (!strncasecmp(cmd, "GET /static/", 12)) {
strcpy(buf, &cmd[12]);
for (a=0; a<strlen(buf); ++a) if (isspace(buf[a])) buf[a]=0;
output_static(buf);
}
- else if (!strncasecmp(cmd, "GET /demographics", 17)) {
- printf("HTTP/1.0 200 OK\n");
- output_headers();
-
- wprintf("<HTML><HEAD><TITLE>Stuff</TITLE></HEAD><BODY>\n");
- wprintf("It's time to include an image...\n");
- wprintf("<IMG SRC=\"/static/netscape.gif\">\n");
- wprintf("...in the page.</BODY></HTML>\n");
- wDumpContent();
+ else if (!logged_in) {
+ display_login_page();
}
else {
wc_session = atoi(argv[1]);
strcpy(wc_host, "");
- wc_port = 0;
+ strcpy(wc_port, "");
strcpy(wc_username, "");
strcpy(wc_password, "");
strcpy(wc_roomname, "");
#define SLEEPING 180 /* TCP connection timeout */
#define PORT_NUM 32767 /* port number to listen on */
#define SERVER "WebCit v2.0 (Velma)" /* who's in da house */
+#define DEFAULT_HOST "uncnsrd.mt-kisco.ny.us"
+#define DEFAULT_PORT "504"
+
+extern char wc_host[256];
+extern char wc_port[256];
+extern char wc_username[256];
+extern char wc_password[256];
+extern char wc_roomname[256];
+extern int connected;
+extern int logged_in;
+extern int serv_sock;
struct webcontent {
struct webcontent *next;
char w_data[256];
};
+
+void serv_printf(const char *format, ...);