* Cleaned up a bunch of unused cruft from the old layout
[citadel.git] / webcit / paging.c
1 /*
2  * $Id$
3  *
4  * Functions which implement the chat and paging facilities.
5  */
6
7 #include <ctype.h>
8 #include <stdlib.h>
9 #include <unistd.h>
10 #include <stdio.h>
11 #include <fcntl.h>
12 #include <signal.h>
13 #include <sys/types.h>
14 #include <sys/wait.h>
15 #include <sys/socket.h>
16 #include <sys/poll.h>
17 #include <sys/time.h>
18 #include <limits.h>
19 #include <netinet/in.h>
20 #include <netdb.h>
21 #include <string.h>
22 #include <pwd.h>
23 #include <errno.h>
24 #include <stdarg.h>
25 #include <pthread.h>
26 #include <signal.h>
27 #include "webcit.h"
28
29
30 /*
31  * display the form for paging (x-messaging) another user
32  */
33 void display_page(void)
34 {
35         char recp[SIZ];
36
37         strcpy(recp, bstr("recp"));
38
39         output_headers(1, 1, 0, 0, 0, 0, 0);
40
41         svprintf("BOXTITLE", WCS_STRING, "Page: %s", recp);
42         do_template("beginbox");
43
44         wprintf("<FORM METHOD=\"POST\" ACTION=\"/page_user\">\n");
45
46         wprintf("<TABLE border=0 width=100%%><TR><TD>\n");
47
48         wprintf("<INPUT TYPE=\"hidden\" NAME=\"recp\" VALUE=\"");
49         escputs(recp);
50         wprintf("\">\n");
51
52         wprintf("<INPUT TYPE=\"hidden\" NAME=\"closewin\" VALUE=\"");
53         escputs(bstr("closewin"));
54         wprintf("\">\n");
55
56         wprintf("Enter message text:<br />");
57
58         wprintf("<TEXTAREA NAME=\"msgtext\" wrap=soft ROWS=5 COLS=40 "
59                 "WIDTH=40></TEXTAREA>\n");
60
61         wprintf("</TD></TR></TABLE><br />\n");
62
63         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Send message\">");
64         wprintf("<br /><A HREF=\"javascript:window.close();\"Cancel</A>\n");
65
66         wprintf("</FORM></CENTER>\n");
67         do_template("endbox");
68         wDumpContent(1);
69 }
70
71 /*
72  * page another user
73  */
74 void page_user(void)
75 {
76         char recp[SIZ];
77         char sc[SIZ];
78         char buf[SIZ];
79         char closewin[SIZ];
80
81         output_headers(1, 1, 0, 0, 0, 0, 0);
82
83         strcpy(recp, bstr("recp"));
84         strcpy(sc, bstr("sc"));
85         strcpy(closewin, bstr("closewin"));
86
87         if (strcmp(sc, "Send message")) {
88                 wprintf("<EM>Message was not sent.</EM><br />\n");
89         } else {
90                 serv_printf("SEXP %s|-", recp);
91                 serv_gets(buf);
92
93                 if (buf[0] == '4') {
94                         text_to_server(bstr("msgtext"), 0);
95                         serv_puts("000");
96                         wprintf("<EM>Message has been sent to ");
97                         escputs(recp);
98                         wprintf(".</EM><br />\n");
99                 }
100                 else {
101                         wprintf("<EM>%s</EM><br />\n", &buf[4]);
102                 }
103         }
104         
105         if (!strcasecmp(closewin, "yes")) {
106                 wprintf("<CENTER><A HREF=\"javascript:window.close();\">"
107                         "[ close window ]</A></CENTER>\n");
108         }
109
110         wDumpContent(1);
111 }
112
113
114
115 /*
116  * multiuser chat
117  */
118 void do_chat(void)
119 {
120         char buf[SIZ];
121
122         /* First, check to make sure we're still allowed in this room. */
123         serv_printf("GOTO %s", WC->wc_roomname);
124         serv_gets(buf);
125         if (buf[0] != '2') {
126                 smart_goto("_BASEROOM_");
127                 return;
128         }
129
130         /* If the chat socket is still open from a previous chat,
131          * close it -- because it might be stale or in the wrong room.
132          */
133         if (WC->chat_sock < 0) {
134                 close(WC->chat_sock);
135                 WC->chat_sock = (-1);
136         }
137
138         /* WebCit Chat works by having transmit, receive, and refresh
139          * frames.  Load the frameset.
140          */
141         do_template("chatframeset");
142         return;
143 }
144
145
146 /*
147  *
148  */
149 void page_popup(void)
150 {
151         char buf[SIZ];
152         char pagefrom[SIZ];
153
154         while (serv_puts("GEXP"), serv_gets(buf), buf[0]=='1') {
155
156                 extract(pagefrom, &buf[4], 3);
157
158                 wprintf("<table border=1 bgcolor=\"#880000\"><tr><td>");
159                 wprintf("<span class=\"titlebar\">Instant message from ");
160                 escputs(pagefrom);
161                 wprintf("</span></td></tr><tr><td><font color=\"#FFFFFF\">");
162                 fmout(NULL, "LEFT");
163                 wprintf("</font></td></tr></table>\n");
164         }
165
166         WC->HaveExpressMessages = 0;
167 }
168
169
170
171 /*
172  * Support function for chat -- make sure the chat socket is connected
173  * and in chat mode.
174  */
175 int setup_chat_socket(void) {
176         char buf[SIZ];
177         int i;
178         int good_chatmode = 0;
179
180         if (WC->chat_sock < 0) {
181
182                 if (!strcasecmp(ctdlhost, "uds")) {
183                         /* unix domain socket */
184                         sprintf(buf, "%s/citadel.socket", ctdlport);
185                         WC->chat_sock = uds_connectsock(buf);
186                 }
187                 else {
188                         /* tcp socket */
189                         WC->chat_sock = tcp_connectsock(ctdlhost, ctdlport);
190                 }
191
192                 if (WC->chat_sock < 0) {
193                         return(errno);
194                 }
195
196                 /* Temporarily swap the serv and chat sockets during chat talk */
197                 i = WC->serv_sock;
198                 WC->serv_sock = WC->chat_sock;
199                 WC->chat_sock = i;
200
201                 serv_gets(buf);
202                 if (buf[0] == '2') {
203                         serv_printf("USER %s", WC->wc_username);
204                         serv_gets(buf);
205                         if (buf[0] == '3') {
206                                 serv_printf("PASS %s", WC->wc_password);
207                                 serv_gets(buf);
208                                 if (buf[0] == '2') {
209                                         serv_printf("GOTO %s", WC->wc_roomname);
210                                         serv_gets(buf);
211                                         if (buf[0] == '2') {
212                                                 serv_puts("CHAT");
213                                                 serv_gets(buf);
214                                                 if (buf[0] == '8') {
215                                                         good_chatmode = 1;
216                                                 }
217                                         }
218                                 }
219                         }
220                 }
221
222                 /* Unswap the sockets. */
223                 i = WC->serv_sock;
224                 WC->serv_sock = WC->chat_sock;
225                 WC->chat_sock = i;
226
227                 if (!good_chatmode) close(WC->serv_sock);
228
229         }
230         return(0);
231 }
232
233
234
235 /*
236  * Receiving side of the chat window.  This is implemented in a
237  * tiny hidden IFRAME that just does JavaScript writes to
238  * other frames whenever it refreshes and finds new data.
239  */
240 void chat_recv(void) {
241         int i;
242         struct pollfd pf;
243         int got_data = 0;
244         int end_chat_now = 0;
245         char buf[SIZ];
246         char cl_user[SIZ];
247         char cl_text[SIZ];
248         char *output_data = NULL;
249
250         output_headers(0, 0, 0, 0, 0, 0, 0);
251
252         wprintf("Content-type: text/html\n");
253         wprintf("\n");
254         wprintf("<html>\n"
255                 "<head>\n"
256                 "<meta http-equiv=\"refresh\" content=\"3\" />\n"
257                 "</head>\n"
258
259                 "<body bgcolor=\"#FFFFFF\">\n"
260         );
261
262         if (setup_chat_socket() != 0) {
263                 wprintf("Error setting up chat socket</BODY></HTML>\n");
264                 wDumpContent(0);
265                 return;
266         }
267
268         /*
269          * See if there is any chat data waiting.
270          */
271         output_data = strdup("");
272         do {
273                 got_data = 0;
274                 pf.fd = WC->chat_sock;
275                 pf.events = POLLIN;
276                 pf.revents = 0;
277                 if (poll(&pf, 1, 1) > 0) if (pf.revents & POLLIN) {
278                         ++got_data;
279
280                         /* Temporarily swap the serv and chat sockets during chat talk */
281                         i = WC->serv_sock;
282                         WC->serv_sock = WC->chat_sock;
283                         WC->chat_sock = i;
284         
285                         serv_gets(buf);
286
287                         if (!strcmp(buf, "000")) {
288                                 strcpy(buf, ":|exiting chat mode");
289                                 end_chat_now = 1;
290                         }
291                         
292                         /* Unswap the sockets. */
293                         i = WC->serv_sock;
294                         WC->serv_sock = WC->chat_sock;
295                         WC->chat_sock = i;
296
297                         /* Append our output data */
298                         output_data = realloc(output_data, strlen(output_data) + strlen(buf) + 4);
299                         strcat(output_data, buf);
300                         strcat(output_data, "\n");
301                 }
302
303         } while ( (got_data) && (!end_chat_now) );
304
305         if (end_chat_now) {
306                 close(WC->chat_sock);
307                 WC->chat_sock = (-1);
308                 wprintf("<IMG SRC=\"/static/blank.gif\" onLoad=\"parent.window.close();\">\n");
309         }
310
311         if (strlen(output_data) > 0) {
312
313                 if (output_data[strlen(output_data)-1] == '\n') {
314                         output_data[strlen(output_data)-1] = 0;
315                 }
316
317                 /* Output our fun to the other frame. */
318                 wprintf("<IMG SRC=\"/static/blank.gif\" WIDTH=1 HEIGHT=1\n"
319                         "onLoad=\" \n"
320                 );
321
322                 for (i=0; i<num_tokens(output_data, '\n'); ++i) {
323                         extract_token(buf, output_data, i, '\n');
324                         extract_token(cl_user, buf, 0, '|');
325                         extract_token(cl_text, buf, 1, '|');
326
327                         if (strcasecmp(cl_text, "NOOP")) {
328
329                                 wprintf("parent.chat_transcript.document.write('");
330         
331                                 if (strcasecmp(cl_user, WC->last_chat_user)) {
332                                         wprintf("<TABLE border=0 WIDTH=100%% "
333                                                 "CELLSPACING=1 CELLPADDING=0 "
334                                                 "BGCOLOR=&quot;#FFFFFF&quot;>"
335                                                 "<TR><TD></TR></TD></TABLE>"
336                                         );
337         
338                                 }
339
340                                 wprintf("<TABLE border=0 WIDTH=100%% "
341                                         "CELLSPACING=0 CELLPADDING=0 "
342                                         "BGCOLOR=&quot;#EEEEEE&quot;>");
343         
344                                 wprintf("<TR><TD>");
345         
346                                 if (!strcasecmp(cl_user, ":")) {
347                                         wprintf("<I>");
348                                 }
349
350                                 if (strcasecmp(cl_user, WC->last_chat_user)) {
351                                         wprintf("<B>");
352         
353                                         if (!strcasecmp(cl_user, WC->wc_username)) {
354                                                 wprintf("<FONT COLOR=&quot;#FF0000&quot;>");
355                                         }
356                                         else {
357                                                 wprintf("<FONT COLOR=&quot;#0000FF&quot;>");
358                                         }
359                                         jsescputs(cl_user);
360         
361                                         wprintf("</FONT>: </B>");
362                                 }
363                                 else {
364                                         wprintf("&nbsp;&nbsp;&nbsp;");
365                                 }
366                                 jsescputs(cl_text);
367                                 if (!strcasecmp(cl_user, ":")) {
368                                         wprintf("</I>");
369                                 }
370
371                                 wprintf("</TD></TR></TABLE>");
372                                 wprintf("'); \n");
373
374                                 strcpy(WC->last_chat_user, cl_user);
375                         }
376                 }
377
378                 wprintf("parent.chat_transcript.scrollTo(999999,999999);\">\n");
379         }
380
381         free(output_data);
382
383         wprintf("</BODY></HTML>\n");
384         wDumpContent(0);
385 }
386
387
388 /*
389  * sending side of the chat window
390  */
391 void chat_send(void) {
392         int i;
393         char send_this[SIZ];
394         char buf[SIZ];
395
396         output_headers(0, 0, 0, 0, 0, 0, 0);
397         wprintf("Content-type: text/html\n");
398         wprintf("\n");
399         wprintf("<HTML>"
400                 "<BODY onLoad=\"document.chatsendform.send_this.focus();\" >"
401         );
402
403         if (bstr("send_this") != NULL) {
404                 strcpy(send_this, bstr("send_this"));
405         }
406         else {
407                 strcpy(send_this, "");
408         }
409
410         if (bstr("sendbutton") != NULL) {
411
412                 if (!strcasecmp(bstr("sendbutton"), "Help")) {
413                         strcpy(send_this, "/help");
414                 }
415
416                 if (!strcasecmp(bstr("sendbutton"), "List Users")) {
417                         strcpy(send_this, "/who");
418                 }
419
420                 if (!strcasecmp(bstr("sendbutton"), "Exit")) {
421                         strcpy(send_this, "/quit");
422                 }
423
424                 if (setup_chat_socket() != 0) {
425                         wprintf("Error setting up chat socket</BODY></HTML>\n");
426                         wDumpContent(0);
427                         return;
428                 }
429
430                 /* Temporarily swap the serv and chat sockets during chat talk */
431                 i = WC->serv_sock;
432                 WC->serv_sock = WC->chat_sock;
433                 WC->chat_sock = i;
434
435                 while (strlen(send_this) > 0) {
436                         if (strlen(send_this) < 67) {
437                                 serv_puts(send_this);
438                                 strcpy(send_this, "");
439                         }
440                         else {
441                                 for (i=55; i<67; ++i) {
442                                         if (send_this[i] == ' ') break;
443                                 }
444                                 strncpy(buf, send_this, i);
445                                 buf[i] = 0;
446                                 strcpy(send_this, &send_this[i]);
447                                 serv_puts(buf);
448                         }
449                 }
450
451                 /* Unswap the sockets. */
452                 i = WC->serv_sock;
453                 WC->serv_sock = WC->chat_sock;
454                 WC->chat_sock = i;
455
456         }
457
458         wprintf("<FORM METHOD=\"POST\" ACTION=\"/chat_send\" NAME=\"chatsendform\">\n");
459         wprintf("<INPUT TYPE=\"text\" SIZE=\"80\" MAXLENGTH=\"%d\" "
460                 "NAME=\"send_this\">\n", SIZ-10);
461         wprintf("<br />");
462         wprintf("<INPUT TYPE=\"submit\" NAME=\"sendbutton\" VALUE=\"Send\">\n");
463         wprintf("<INPUT TYPE=\"submit\" NAME=\"sendbutton\" VALUE=\"Help\">\n");
464         wprintf("<INPUT TYPE=\"submit\" NAME=\"sendbutton\" VALUE=\"List Users\">\n");
465         wprintf("<INPUT TYPE=\"submit\" NAME=\"sendbutton\" VALUE=\"Exit\">\n");
466         wprintf("</FORM>\n");
467
468         wprintf("</BODY></HTML>\n");
469         wDumpContent(0);
470 }
471
472