* All OS-level includes are now included from webcit.h instead of from
[citadel.git] / webcit / paging.c
1 /*
2  * $Id$
3  *
4  * Functions which implement the chat and paging facilities.
5  */
6
7 #include "webcit.h"
8
9 /*
10  * display the form for paging (x-messaging) another user
11  */
12 void display_page(void)
13 {
14         char recp[SIZ];
15
16         strcpy(recp, bstr("recp"));
17
18         output_headers(1, 1, 2, 0, 0, 0, 0);
19         wprintf("<div id=\"banner\">\n"
20                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
21                 "<SPAN CLASS=\"titlebar\">Send instant message</SPAN>"
22                 "</TD></TR></TABLE>\n"
23                 "</div>\n<div id=\"content\">\n"
24         );
25                                                                                                                              
26         wprintf("<div id=\"fix_scrollbar_bug\">"
27                 "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
28
29         wprintf("Send an instant message to: ");
30         escputs(recp);
31         wprintf("<br>\n");
32
33         wprintf("<FORM METHOD=\"POST\" ACTION=\"/page_user\">\n");
34
35         wprintf("<TABLE border=0 width=100%%><TR><TD>\n");
36
37         wprintf("<INPUT TYPE=\"hidden\" NAME=\"recp\" VALUE=\"");
38         escputs(recp);
39         wprintf("\">\n");
40
41         wprintf("<INPUT TYPE=\"hidden\" NAME=\"closewin\" VALUE=\"");
42         escputs(bstr("closewin"));
43         wprintf("\">\n");
44
45         wprintf("Enter message text:<br />");
46
47         wprintf("<TEXTAREA NAME=\"msgtext\" wrap=soft ROWS=5 COLS=40 "
48                 "WIDTH=40></TEXTAREA>\n");
49
50         wprintf("</TD></TR></TABLE><br />\n");
51
52         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Send message\">");
53         wprintf("<br /><A HREF=\"javascript:window.close();\"Cancel</A>\n");
54
55         wprintf("</FORM></CENTER>\n");
56         wprintf("</td></tr></table></div>\n");
57         wDumpContent(1);
58 }
59
60 /*
61  * page another user
62  */
63 void page_user(void)
64 {
65         char recp[SIZ];
66         char sc[SIZ];
67         char buf[SIZ];
68         char closewin[SIZ];
69
70         output_headers(1, 1, 2, 0, 0, 0, 0);
71         wprintf("<div id=\"banner\">\n"
72                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
73                 "<SPAN CLASS=\"titlebar\">Add or edit an event</SPAN>"
74                 "</TD></TR></TABLE>\n"
75                 "</div>\n<div id=\"content\">\n"
76         );
77                                                                                                                              
78         strcpy(recp, bstr("recp"));
79         strcpy(sc, bstr("sc"));
80         strcpy(closewin, bstr("closewin"));
81
82         if (strcmp(sc, "Send message")) {
83                 wprintf("<EM>Message was not sent.</EM><br />\n");
84         } else {
85                 serv_printf("SEXP %s|-", recp);
86                 serv_getln(buf, sizeof buf);
87
88                 if (buf[0] == '4') {
89                         text_to_server(bstr("msgtext"), 0);
90                         serv_puts("000");
91                         wprintf("<EM>Message has been sent to ");
92                         escputs(recp);
93                         wprintf(".</EM><br />\n");
94                 }
95                 else {
96                         wprintf("<EM>%s</EM><br />\n", &buf[4]);
97                 }
98         }
99         
100         if (!strcasecmp(closewin, "yes")) {
101                 wprintf("<CENTER><A HREF=\"javascript:window.close();\">"
102                         "[ close window ]</A></CENTER>\n");
103         }
104
105         wDumpContent(1);
106 }
107
108
109
110 /*
111  * multiuser chat
112  */
113 void do_chat(void)
114 {
115         char buf[SIZ];
116
117         /* First, check to make sure we're still allowed in this room. */
118         serv_printf("GOTO %s", WC->wc_roomname);
119         serv_getln(buf, sizeof buf);
120         if (buf[0] != '2') {
121                 smart_goto("_BASEROOM_");
122                 return;
123         }
124
125         /* If the chat socket is still open from a previous chat,
126          * close it -- because it might be stale or in the wrong room.
127          */
128         if (WC->chat_sock < 0) {
129                 close(WC->chat_sock);
130                 WC->chat_sock = (-1);
131         }
132
133         /* WebCit Chat works by having transmit, receive, and refresh
134          * frames.  Load the frameset.
135          */
136         do_template("chatframeset");
137         return;
138 }
139
140
141 /*
142  *
143  */
144 void page_popup(void)
145 {
146         char buf[SIZ];
147         char pagefrom[SIZ];
148
149         while (serv_puts("GEXP"), serv_getln(buf, sizeof buf), buf[0]=='1') {
150
151                 extract_token(pagefrom, &buf[4], 3, '|', sizeof pagefrom);
152
153                 wprintf("<table border=1 bgcolor=\"#880000\"><tr><td>");
154                 wprintf("<span class=\"titlebar\">Instant message from ");
155                 escputs(pagefrom);
156                 wprintf("</span></td></tr><tr><td><font color=\"#FFFFFF\">");
157                 fmout(NULL, "LEFT");
158                 wprintf("</font></td></tr>"
159                         "<tr><td><div align=center><font color=\"#FFFFFF\">"
160                         "<a href=\"javascript:hide_page_popup()\">[ close window ]</a>"
161                         "</font></div>"
162                         "</td></tr>"
163                         "</table>\n");
164         }
165
166         WC->HaveInstantMessages = 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_getln(buf, sizeof buf);
202                 if (buf[0] == '2') {
203                         serv_printf("USER %s", WC->wc_username);
204                         serv_getln(buf, sizeof buf);
205                         if (buf[0] == '3') {
206                                 serv_printf("PASS %s", WC->wc_password);
207                                 serv_getln(buf, sizeof buf);
208                                 if (buf[0] == '2') {
209                                         serv_printf("GOTO %s", WC->wc_roomname);
210                                         serv_getln(buf, sizeof buf);
211                                         if (buf[0] == '2') {
212                                                 serv_puts("CHAT");
213                                                 serv_getln(buf, sizeof 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; charset=utf-8\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_getln(buf, sizeof 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', sizeof buf);
324                         extract_token(cl_user, buf, 0, '|', sizeof cl_user);
325                         extract_token(cl_text, buf, 1, '|', sizeof cl_text);
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; charset=utf-8\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