]> code.citadel.org Git - citadel.git/blob - webcit/webcit.c
oooh, lotsa good stuff
[citadel.git] / webcit / webcit.c
1 /*
2  * webcit.c
3  *
4  * This is the actual program called by the webserver.  It maintains a
5  * persistent session to the Citadel server, handling HTTP WebCit requests as
6  * they arrive and presenting a user interface.
7  */
8
9 #include <stdlib.h>
10 #include <unistd.h>
11 #include <stdio.h>
12 #include <ctype.h>
13 #include <string.h>
14 #include <errno.h>
15 #include <sys/stat.h>
16 #include <stdarg.h>
17 #include "webcit.h"
18
19 int wc_session;
20 char wc_host[256];
21 char wc_port[256];
22 char wc_username[256];
23 char wc_password[256];
24 char wc_roomname[256];
25 int TransactionCount = 0;
26 int connected = 0;
27 int logged_in = 0;
28
29 struct webcontent *wlist = NULL;
30 struct webcontent *wlast = NULL;
31
32
33 void wprintf(const char *format, ...) {   
34         va_list arg_ptr;   
35         struct webcontent *wptr;
36
37         wptr = (struct webcontent *)malloc(sizeof(struct webcontent));
38         wptr->next = NULL;
39         if (wlist == NULL) {
40                 wlist = wptr;
41                 wlast = wptr;
42                 }
43         else {
44                 wlast->next = wptr;
45                 wlast = wptr;
46                 }
47   
48         va_start(arg_ptr, format);   
49         vsprintf(wptr->w_data, format, arg_ptr);   
50         va_end(arg_ptr);   
51   
52         }
53
54 int wContentLength() {
55         struct webcontent *wptr;
56         int len = 0;
57
58         for (wptr = wlist; wptr != NULL; wptr = wptr->next) {
59                 len = len + strlen(wptr->w_data);
60                 }
61
62         return(len);
63         }
64
65 void wDumpContent() {
66         struct webcontent *wptr;
67
68         printf("Content-type: text/html\n");
69         printf("Content-length: %d\n", wContentLength());
70         printf("\n");
71
72         while (wlist != NULL) {
73                 fwrite(wlist->w_data, strlen(wlist->w_data), 1, stdout);
74                 wptr = wlist->next;
75                 free(wlist);
76                 wlist = wptr;
77                 }
78         wlast = NULL;
79         }
80
81 void getz(char *buf) {
82         if (fgets(buf, 256, stdin) == NULL) strcpy(buf, "");
83         else {
84                 while ((strlen(buf)>0)&&(!isprint(buf[strlen(buf)-1])))
85                         buf[strlen(buf)-1] = 0;
86                 }
87         }
88
89 /*
90  * Output all that important stuff that the browser will want to see
91  */
92 void output_headers() {
93         printf("Server: %s\n", SERVER);
94         printf("Connection: close\n");
95         printf("Set-cookie: wc_session=%d\n", wc_session);
96         if (strlen(wc_host)>0) printf("Set-cookie: wc_host=%s\n", wc_host);
97         if (strlen(wc_port)>0) printf("Set-cookie: wc_port=%s\n", wc_port);
98         if (strlen(wc_username)>0) printf("Set-cookie: wc_username=%s\n",
99                 wc_username);
100         if (strlen(wc_password)>0) printf("Set-cookie: wc_password=%s\n",
101                 wc_password);
102         if (strlen(wc_roomname)>0) printf("Set-cookie: wc_roomname=%s\n",
103                 wc_roomname);
104         }
105
106 void output_static(char *what) {
107         char buf[256];
108         FILE *fp;
109         struct stat statbuf;
110         off_t bytes;
111
112         sprintf(buf, "static/%s", what);
113         fp = fopen(buf, "rb");
114         if (fp == NULL) {
115                 printf("HTTP/1.0 404 %s\n", strerror(errno));
116                 output_headers();
117                 printf("Content-Type: text/plain\n");
118                 sprintf(buf, "%s: %s\n", what, strerror(errno));
119                 printf("Content-length: %d\n", strlen(buf));
120                 printf("\n");
121                 fwrite(buf, strlen(buf), 1, stdout);
122                 }
123         else {
124                 printf("HTTP/1.0 200 OK\n");
125                 output_headers();
126
127                 if (!strncasecmp(&what[strlen(what)-4], ".gif", 4))
128                         printf("Content-type: image/gif\n");
129                 else
130                         printf("Content-type: junk/data\n");
131
132                 fstat(fileno(fp), &statbuf);
133                 bytes = statbuf.st_size;
134                 printf("Content-length: %d\n", bytes);
135                 printf("\n");
136                 while (bytes--) {
137                         putc(getc(fp), stdout);
138                         }
139                 fclose(fp);
140                 }
141         }
142
143
144 void session_loop() {
145         char cmd[256];
146         char buf[256];
147         int a;
148
149         /* We stuff these with the values coming from the client cookies,
150          * so we can use them to reconnect a timed out session if we have to.
151          */
152         char c_host[256];
153         char c_port[256];
154         char c_username[256];
155         char c_password[256];
156         char c_roomname[256];
157
158         strcpy(c_host, DEFAULT_HOST);
159         strcpy(c_port, DEFAULT_PORT);
160         strcpy(c_username, "");
161         strcpy(c_password, "");
162         strcpy(c_roomname, "");
163
164         getz(cmd);
165         fprintf(stderr, "Cmd: %s\n", cmd);
166         fflush(stderr);
167
168         do {
169                 getz(buf);
170
171                 if (!strncasecmp(buf, "Cookie: wc_host=", 16))
172                         strcpy(c_host, &buf[16]);
173                 if (!strncasecmp(buf, "Cookie: wc_port=", 16))
174                         strcpy(c_port, &buf[16]);
175                 if (!strncasecmp(buf, "Cookie: wc_username=", 20))
176                         strcpy(c_username, &buf[20]);
177                 if (!strncasecmp(buf, "Cookie: wc_password=", 20))
178                         strcpy(c_password, &buf[20]);
179                 if (!strncasecmp(buf, "Cookie: wc_roomname=", 20))
180                         strcpy(c_roomname, &buf[20]);
181
182                 } while(strlen(buf)>0);
183
184         ++TransactionCount;
185
186         /*
187          * If we're not connected to a Citadel server, try to hook up the
188          * connection now.  Preference is given to the host and port specified
189          * by browser cookies, if cookies have been supplied.
190          */
191         if (!connected) {
192                 serv_sock = connectsock(c_host, c_port, "tcp");
193                 connected = 1;
194                 strcpy(wc_host, c_host);
195                 strcpy(wc_port, c_port);
196                 }
197
198         /*
199          * If we're not logged in, but we have username and password cookies
200          * supplied by the browser, try using them to log in.
201          */
202         if ((!logged_in)&&(strlen(c_username)>0)&&(strlen(c_password)>0)) {
203                 serv_printf("USER %s", c_username);
204                 serv_gets(buf);
205                 if (buf[0]=='3') {
206                         serv_printf("PASS %s", c_password);
207                         serv_gets(buf);
208                         if (buf[0]=='2') {
209                                 logged_in = 1;
210                                 strcpy(wc_username, c_username);
211                                 strcpy(wc_password, c_password);
212                                 }
213                         }
214                 }
215
216         /*
217          * If we don't have a current room, but a cookie specifying the
218          * current room is supplied, make an effort to go there.
219          */
220         if ((strlen(wc_roomname)==0) && (strlen(c_roomname)>0) ) {
221                 serv_printf("GOTO %s", c_roomname);
222                 serv_gets(buf);
223                 if (buf[0]=='2') {
224                         strcpy(wc_roomname, c_roomname);
225                         }
226                 }
227
228         if (!strncasecmp(cmd, "GET /static/", 12)) {
229                 strcpy(buf, &cmd[12]);
230                 for (a=0; a<strlen(buf); ++a) if (isspace(buf[a])) buf[a]=0;
231                 output_static(buf);
232                 }
233
234         else if (!logged_in) {
235                 display_login_page();
236                 }
237
238         else {
239                 printf("HTTP/1.0 200 OK\n");
240                 output_headers();
241         
242                 wprintf("<HTML><HEAD><TITLE>WebCit</TITLE></HEAD><BODY>\n");
243                 wprintf("TransactionCount is %d<HR>\n", TransactionCount);
244                 wprintf("You're in session %d<BR>\n", wc_session);
245                 wprintf("</BODY></HTML>\n");
246                 wDumpContent();
247                 }
248
249         fflush(stdout);
250         }
251
252
253
254 int main(int argc, char *argv[]) {
255
256         if (argc != 2) {
257                 printf("%s: usage: %s <session_id>\n", argv[0], argv[0]);
258                 exit(1);
259                 }
260
261         wc_session = atoi(argv[1]);
262         strcpy(wc_host, "");
263         strcpy(wc_port, "");
264         strcpy(wc_username, "");
265         strcpy(wc_password, "");
266         strcpy(wc_roomname, "");
267
268         while (1) {
269                 session_loop();
270                 }
271
272         exit(0);
273         }