* Made the chat screen totally kick-ass sweet. The flickering reload
[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(3);
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(3);
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
121         output_headers(3);
122
123         wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#000077\"><TR><TD>"
124                 "<SPAN CLASS=\"titlebar\">"
125                 "<IMG SRC=\"/static/chat-icon.gif\" WIDTH=16 HEIGHT=16 ALIGN=MIDDLE>"
126         );
127         escputs(WC->wc_roomname);
128         wprintf(": real-time chat</SPAN>\n"
129                 "</TD></TR></TABLE>\n"
130
131                 "<IFRAME WIDTH=100%% HEIGHT=200 SRC=\"about:blank\" "
132                 "NAME=\"chat_transcript\">\n"
133                 "<!-- Alternate content for non-supporting browsers -->\n"
134                 "If you are seeing this message, your browser does not contain\n"
135                 "the IFRAME support required for the chat window.  Please upgrade\n"
136                 "to a supported browser, such as\n"
137                 "<A HREF=\"http://www.mozilla.org\">Mozilla</A>.\n"
138                 "</IFRAME>\n"
139
140                 "<IFRAME WIDTH=100%% HEIGHT=1 SRC=\"/chat_recv\" "
141                 "NAME=\"chat_recv\">\n"
142                 "</IFRAME>"
143
144                 "<BR>\n"
145
146                 "<IFRAME WIDTH=100%% HEIGHT=60 SRC=\"/chat_send\" "
147                 "NAME=\"chat_send\">\n"
148                 "</IFRAME>\n"
149         );
150         wDumpContent(1);
151 }
152
153
154 /*
155  *
156  */
157 void page_popup(void)
158 {
159         char buf[SIZ];
160         char pagefrom[SIZ];
161
162         /* suppress express message check, do headers but no frames */
163         output_headers(0x08 | 0x03);
164
165         while (serv_puts("GEXP"), serv_gets(buf), buf[0]=='1') {
166
167                 extract(pagefrom, &buf[4], 3);
168
169                 wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#007700\"><TR><TD>");
170                 wprintf("<SPAN CLASS=\"titlebar\">Instant message from ");
171                 escputs(pagefrom);
172                 wprintf("</SPAN></TD></TR></TABLE>\n");
173                 
174                 fmout(NULL, "LEFT");
175         }
176
177         wprintf("<CENTER>");
178         wprintf("<A HREF=\"/display_page&closewin=yes&recp=");
179         urlescputs(pagefrom);
180         wprintf("\">[ reply ]</A>&nbsp;&nbsp;&nbsp;\n");
181
182         wprintf("<A HREF=\"javascript:window.close();\">"
183                 "[ close window ]</A></B>\n"
184                 "</CENTER>");
185
186         wDumpContent(1);
187         WC->HaveExpressMessages = 0;
188 }
189
190
191
192 /*
193  * Support function for chat -- make sure the chat socket is connected
194  * and in chat mode.
195  */
196 int setup_chat_socket(void) {
197         char buf[SIZ];
198         int i;
199         int good_chatmode = 0;
200
201         if (WC->chat_sock < 0) {
202
203                 if (!strcasecmp(ctdlhost, "uds")) {
204                         /* unix domain socket */
205                         sprintf(buf, "%s/citadel.socket", ctdlport);
206                         WC->chat_sock = uds_connectsock(buf);
207                 }
208                 else {
209                         /* tcp socket */
210                         WC->chat_sock = tcp_connectsock(ctdlhost, ctdlport);
211                 }
212
213                 if (WC->chat_sock < 0) {
214                         return(errno);
215                 }
216
217                 /* Temporarily swap the serv and chat sockets during chat talk */
218                 i = WC->serv_sock;
219                 WC->serv_sock = WC->chat_sock;
220                 WC->chat_sock = i;
221
222                 serv_gets(buf);
223                 if (buf[0] == '2') {
224                         serv_printf("USER %s", WC->wc_username);
225                         serv_gets(buf);
226                         if (buf[0] == '3') {
227                                 serv_printf("PASS %s", WC->wc_password);
228                                 serv_gets(buf);
229                                 if (buf[0] == '2') {
230                                         serv_printf("GOTO %s", WC->wc_roomname);
231                                         serv_gets(buf);
232                                         if (buf[0] == '2') {
233                                                 serv_puts("CHAT");
234                                                 serv_gets(buf);
235                                                 if (buf[0] == '8') {
236                                                         good_chatmode = 1;
237                                                 }
238                                         }
239                                 }
240                         }
241                 }
242
243                 /* Unswap the sockets. */
244                 i = WC->serv_sock;
245                 WC->serv_sock = WC->chat_sock;
246                 WC->chat_sock = i;
247
248                 if (!good_chatmode) close(WC->serv_sock);
249
250         }
251         return(0);
252 }
253
254
255
256 /*
257  * Receiving side of the chat window.  This is implemented in a
258  * tiny hidden IFRAME that just does JavaScript writes to
259  * other frames whenever it refreshes and finds new data.
260  */
261 void chat_recv(void) {
262         int i;
263         struct pollfd pf;
264         int got_data = 0;
265         int end_chat_now = 0;
266         char buf[SIZ];
267         char cl_user[SIZ];
268         char cl_text[SIZ];
269         char *output_data = NULL;
270
271         output_headers(0);
272
273         wprintf("Content-type: text/html\n");
274         wprintf("\n");
275         wprintf("<HTML>\n"
276                 "<HEAD>\n"
277                 "<META HTTP-EQUIV=\"refresh\" CONTENT=\"3\">\n"
278                 "</HEAD>\n"
279
280                 "<BODY BGCOLOR=\"#FFFFFF\">\n"
281         );
282
283         if (setup_chat_socket() != 0) {
284                 wprintf("Error setting up chat socket</BODY></HTML>\n");
285                 wDumpContent(0);
286                 return;
287         }
288
289         /*
290          * See if there is any chat data waiting.
291          */
292         output_data = strdup("");
293         do {
294                 got_data = 0;
295                 pf.fd = WC->chat_sock;
296                 pf.events = POLLIN;
297                 pf.revents = 0;
298                 if (poll(&pf, 1, 1) > 0) if (pf.revents & POLLIN) {
299                         ++got_data;
300
301                         /* Temporarily swap the serv and chat sockets during chat talk */
302                         i = WC->serv_sock;
303                         WC->serv_sock = WC->chat_sock;
304                         WC->chat_sock = i;
305         
306                         serv_gets(buf);
307
308                         if (!strcmp(buf, "000")) {
309                                 strcpy(buf, ":|exiting chat mode");
310                                 end_chat_now = 1;
311                         }
312                         
313                         /* Unswap the sockets. */
314                         i = WC->serv_sock;
315                         WC->serv_sock = WC->chat_sock;
316                         WC->chat_sock = i;
317
318                         /* Append our output data */
319                         output_data = realloc(output_data, strlen(output_data) + strlen(buf) + 4);
320                         strcat(output_data, buf);
321                         strcat(output_data, "\n");
322                 }
323
324         } while ( (got_data) && (!end_chat_now) );
325
326         if (end_chat_now) {
327                 close(WC->chat_sock);
328                 WC->chat_sock = (-1);
329                 wprintf("<IMG SRC=\"/static/blank.gif\" onLoad=\"parent.location.replace('/display_main_menu');\">\n");
330         }
331
332         if (strlen(output_data) > 0) {
333
334                 if (output_data[strlen(output_data)-1] == '\n') {
335                         output_data[strlen(output_data)-1] = 0;
336                 }
337
338                 /* Output our fun to the other frame. */
339                 wprintf("<IMG SRC=\"/static/blank.gif\" WIDTH=1 HEIGHT=1\n"
340                         "onLoad=\" \n"
341                 );
342
343                 for (i=0; i<num_tokens(output_data, '\n'); ++i) {
344                         extract_token(buf, output_data, i, '\n');
345                         extract_token(cl_user, buf, 0, '|');
346                         extract_token(cl_text, buf, 1, '|');
347
348                         wprintf("parent.chat_transcript.document.write('");
349                         wprintf("<FONT SIZE=-1><B>");
350                         jsescputs(cl_user);
351                         wprintf(":</B> ");
352                         jsescputs(cl_text);
353                         wprintf("</FONT><BR>");
354                         wprintf("'); \n");
355                 }
356
357                 wprintf("parent.chat_transcript.scrollTo(999999,999999);\">\n");
358         }
359
360         free(output_data);
361
362         wprintf("</BODY></HTML>\n");
363         wDumpContent(0);
364 }
365
366
367 /*
368  * sending side of the chat window
369  */
370 void chat_send(void) {
371         int i;
372         char send_this[SIZ];
373
374         output_headers(0);
375         wprintf("Content-type: text/html\n");
376         wprintf("\n");
377         wprintf("<HTML>"
378                 "<BODY onLoad=\"document.chatsendform.send_this.focus();\" >"
379         );
380
381         if (bstr("send_this") != NULL) {
382                 strcpy(send_this, bstr("send_this"));
383         }
384         else {
385                 strcpy(send_this, "");
386         }
387
388         if (bstr("sendbutton") != NULL) {
389
390                 if (!strcasecmp(bstr("sendbutton"), "Help")) {
391                         strcpy(send_this, "/help");
392                 }
393
394                 if (!strcasecmp(bstr("sendbutton"), "Exit")) {
395                         strcpy(send_this, "/quit");
396                 }
397
398                 if (setup_chat_socket() != 0) {
399                         wprintf("Error setting up chat socket</BODY></HTML>\n");
400                         wDumpContent(0);
401                         return;
402                 }
403
404                 /* Temporarily swap the serv and chat sockets during chat talk */
405                 i = WC->serv_sock;
406                 WC->serv_sock = WC->chat_sock;
407                 WC->chat_sock = i;
408
409                 serv_puts(send_this);
410
411                 /* Unswap the sockets. */
412                 i = WC->serv_sock;
413                 WC->serv_sock = WC->chat_sock;
414                 WC->chat_sock = i;
415
416         }
417
418         wprintf("<FORM METHOD=\"POST\" ACTION=\"/chat_send\" NAME=\"chatsendform\">\n");
419         wprintf("<INPUT TYPE=\"text\" SIZE=\"80\" MAXLENGTH=\"80\" NAME=\"send_this\">\n");
420         wprintf("<INPUT TYPE=\"submit\" NAME=\"sendbutton\" VALUE=\"Send\">\n");
421         wprintf("<INPUT TYPE=\"submit\" NAME=\"sendbutton\" VALUE=\"Help\">\n");
422         wprintf("<INPUT TYPE=\"submit\" NAME=\"sendbutton\" VALUE=\"Exit\">\n");
423         wprintf("</FORM>\n");
424
425         wprintf("</BODY></HTML>\n");
426         wDumpContent(0);
427 }
428
429