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