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