move all source files to src/
[citadel.git] / webcit / src / paging.c
1 /*
2  * $Id$
3  */
4 /**
5  * \defgroup PageFunc Functions which implement the chat and paging facilities.
6  * \ingroup ClientPower
7  */
8 /*@{*/
9 #include "webcit.h"
10
11 /**
12  * \brief display the form for paging (x-messaging) another user
13  */
14 void display_page(void)
15 {
16         char recp[SIZ];
17
18         strcpy(recp, bstr("recp"));
19
20         output_headers(1, 1, 2, 0, 0, 0);
21         wprintf("<div id=\"banner\">\n"
22                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
23                 "<SPAN CLASS=\"titlebar\">");
24         wprintf(_("Send instant message"));
25         wprintf("</SPAN>"
26                 "</TD></TR></TABLE>\n"
27                 "</div>\n<div id=\"content\">\n"
28         );
29                                                                                                                              
30         wprintf("<div class=\"fix_scrollbar_bug\">"
31                 "<table border=0 width=100%% bgcolor=\"#ffffff\"><tr><td>\n");
32
33         wprintf(_("Send an instant message to: "));
34         escputs(recp);
35         wprintf("<br>\n");
36
37         wprintf("<FORM METHOD=\"POST\" action=\"page_user\">\n");
38
39         wprintf("<TABLE border=0 width=100%%><TR><TD>\n");
40
41         wprintf("<INPUT TYPE=\"hidden\" NAME=\"recp\" VALUE=\"");
42         escputs(recp);
43         wprintf("\">\n");
44
45         wprintf("<INPUT TYPE=\"hidden\" NAME=\"closewin\" VALUE=\"");
46         escputs(bstr("closewin"));
47         wprintf("\">\n");
48
49         wprintf(_("Enter message text:"));
50         wprintf("<br />");
51
52         wprintf("<TEXTAREA NAME=\"msgtext\" wrap=soft ROWS=5 COLS=40 "
53                 "WIDTH=40></TEXTAREA>\n");
54
55         wprintf("</TD></TR></TABLE><br />\n");
56
57         wprintf("<INPUT TYPE=\"submit\" NAME=\"send_button\" VALUE=\"%s\">", _("Send message"));
58         wprintf("<br /><a href=\"javascript:window.close();\"%s</A>\n", _("Cancel"));
59
60         wprintf("</FORM></CENTER>\n");
61         wprintf("</td></tr></table></div>\n");
62         wDumpContent(1);
63 }
64
65 /**
66  * \brief page another user
67  */
68 void page_user(void)
69 {
70         char recp[SIZ];
71         char buf[SIZ];
72         char closewin[SIZ];
73
74         output_headers(1, 1, 2, 0, 0, 0);
75         wprintf("<div id=\"banner\">\n"
76                 "<TABLE WIDTH=100%% BORDER=0 BGCOLOR=\"#444455\"><TR><TD>"
77                 "<SPAN CLASS=\"titlebar\">");
78         wprintf(_("Add or edit an event"));
79         wprintf("</SPAN>"
80                 "</TD></TR></TABLE>\n"
81                 "</div>\n<div id=\"content\">\n"
82         );
83                                                                                                                              
84         strcpy(recp, bstr("recp"));
85         strcpy(closewin, bstr("closewin"));
86
87         if (strlen(bstr("send_button")) == 0) {
88                 wprintf("<EM>");
89                 wprintf(_("Message was not sent."));
90                 wprintf("</EM><br />\n");
91         } else {
92                 serv_printf("SEXP %s|-", recp);
93                 serv_getln(buf, sizeof buf);
94
95                 if (buf[0] == '4') {
96                         text_to_server(bstr("msgtext"));
97                         serv_puts("000");
98                         wprintf("<EM>");
99                         wprintf(_("Message has been sent to "));
100                         escputs(recp);
101                         wprintf(".</EM><br />\n");
102                 }
103                 else {
104                         wprintf("<em>%s</em><br />\n", &buf[4]);
105                 }
106         }
107         
108         if (!strcasecmp(closewin, "yes")) {
109                 wprintf("<CENTER><a href=\"javascript:window.close();\">");
110                 wprintf(_("[ close window ]"));
111                 wprintf("</A></CENTER>\n");
112         }
113
114         wDumpContent(1);
115 }
116
117
118
119 /**
120  * \brief multiuser chat
121  */
122 void do_chat(void)
123 {
124         char buf[SIZ];
125
126         /** First, check to make sure we're still allowed in this room. */
127         serv_printf("GOTO %s", WC->wc_roomname);
128         serv_getln(buf, sizeof buf);
129         if (buf[0] != '2') {
130                 smart_goto("_BASEROOM_");
131                 return;
132         }
133
134         /**
135          * If the chat socket is still open from a previous chat,
136          * close it -- because it might be stale or in the wrong room.
137          */
138         if (WC->chat_sock < 0) {
139                 close(WC->chat_sock);
140                 WC->chat_sock = (-1);
141         }
142
143         /**
144          * WebCit Chat works by having transmit, receive, and refresh
145          * frames.  Load the frameset.  (This isn't AJAX but the headers
146          * output by begin_ajax_response() happen to be the ones we need.)
147          */
148         begin_ajax_response();
149         do_template("chatframeset");
150         end_ajax_response();
151         return;
152 }
153
154
155 /**
156  * \brief display page popup
157  * If there are instant messages waiting, and we notice that we haven't checked them in
158  * a while, it probably means that we need to open the instant messenger window.
159  */
160 void page_popup(void)
161 {
162         char buf[SIZ];
163
164         /** JavaScript function to alert the user that popups are probably blocked */
165         wprintf("<script type=\"text/javascript\">      "
166                 "function PopUpFailed() {       "
167                 " alert(\"%s\");        "
168                 "}      "
169                 "</script>\n",
170                 _("You have one or more instant messages waiting, but the Citadel Instant Messenger "
171                   "window failed to open.  This is probably because you have a popup blocker "
172                   "installed.  Please configure your popup blocker to allow popups from this site "
173                   "if you wish to receive instant messages.")
174         );
175
176         /** First, do the check as part of our page load. */
177         serv_puts("NOOP");
178         serv_getln(buf, sizeof buf);
179         if (buf[3] == '*') {
180                 if ((time(NULL) - WC->last_pager_check) > 60) {
181                         wprintf("<script type=\"text/javascript\">"
182                                 " var oWin = window.open('static/instant_messenger.html', "
183                                 " 'CTDL_MESSENGER', 'width=700,height=400');    "
184                                 " if (oWin==null || typeof(oWin)==\"undefined\") {      "
185                                 "  PopUpFailed();       "
186                                 " }     "
187                                 "</script>"
188                         );      
189                 }
190         }
191
192         /** Then schedule it to happen again a minute from now if the user is idle. */
193         wprintf("<script type=\"text/javascript\">      "
194                 " function HandleSslp(sslg_xmlresponse) {       "
195                 "  sslg_response = sslg_xmlresponse.responseText.substr(0, 1);  "
196                 "  if (sslg_response == 'Y') {  "
197                 "   var oWin = window.open('static/instant_messenger.html', 'CTDL_MESSENGER',   "
198                 "    'width=700,height=400');   "
199                 "   if (oWin==null || typeof(oWin)==\"undefined\") {    "
200                 "    PopUpFailed();     "
201                 "   }   "
202                 "  }    "
203                 " }     "
204                 " function CheckPager() {       "
205                 "  new Ajax.Request('sslg', { method: 'get', parameters: Math.random(), "
206                 "   onSuccess: HandleSslp } );  "
207                 " }     "
208                 " new PeriodicalExecuter(CheckPager, 30);       "
209                 "</script>      "
210         );
211 }
212
213
214
215 /**
216  * \brief Support function for chat
217  * make sure the chat socket is connected
218  * and in chat mode.
219  */
220 int setup_chat_socket(void) {
221         char buf[SIZ];
222         int i;
223         int good_chatmode = 0;
224
225         if (WC->chat_sock < 0) {
226
227                 if (!strcasecmp(ctdlhost, "uds")) {
228                         /** unix domain socket */
229                         sprintf(buf, "%s/citadel.socket", ctdlport);
230                         WC->chat_sock = uds_connectsock(buf);
231                 }
232                 else {
233                         /** tcp socket */
234                         WC->chat_sock = tcp_connectsock(ctdlhost, ctdlport);
235                 }
236
237                 if (WC->chat_sock < 0) {
238                         return(errno);
239                 }
240
241                 /** Temporarily swap the serv and chat sockets during chat talk */
242                 i = WC->serv_sock;
243                 WC->serv_sock = WC->chat_sock;
244                 WC->chat_sock = i;
245
246                 serv_getln(buf, sizeof buf);
247                 if (buf[0] == '2') {
248                         serv_printf("USER %s", WC->wc_username);
249                         serv_getln(buf, sizeof buf);
250                         if (buf[0] == '3') {
251                                 serv_printf("PASS %s", WC->wc_password);
252                                 serv_getln(buf, sizeof buf);
253                                 if (buf[0] == '2') {
254                                         serv_printf("GOTO %s", WC->wc_roomname);
255                                         serv_getln(buf, sizeof buf);
256                                         if (buf[0] == '2') {
257                                                 serv_puts("CHAT");
258                                                 serv_getln(buf, sizeof buf);
259                                                 if (buf[0] == '8') {
260                                                         good_chatmode = 1;
261                                                 }
262                                         }
263                                 }
264                         }
265                 }
266
267                 /** Unswap the sockets. */
268                 i = WC->serv_sock;
269                 WC->serv_sock = WC->chat_sock;
270                 WC->chat_sock = i;
271
272                 if (!good_chatmode) close(WC->serv_sock);
273
274         }
275         return(0);
276 }
277
278
279
280 /**
281  * \brief Receiving side of the chat window.  
282  * This is implemented in a
283  * tiny hidden IFRAME that just does JavaScript writes to
284  * other frames whenever it refreshes and finds new data.
285  */
286 void chat_recv(void) {
287         int i;
288         struct pollfd pf;
289         int got_data = 0;
290         int end_chat_now = 0;
291         char buf[SIZ];
292         char cl_user[SIZ];
293         char cl_text[SIZ];
294         char *output_data = NULL;
295
296         output_headers(0, 0, 0, 0, 0, 0);
297
298         wprintf("Content-type: text/html; charset=utf-8\n");
299         wprintf("\n");
300         wprintf("<html>\n"
301                 "<head>\n"
302                 "<meta http-equiv=\"refresh\" content=\"3\" />\n"
303                 "</head>\n"
304
305                 "<body bgcolor=\"#FFFFFF\">\n"
306         );
307
308         if (setup_chat_socket() != 0) {
309                 wprintf(_("An error occurred while setting up the chat socket."));
310                 wprintf("</BODY></HTML>\n");
311                 wDumpContent(0);
312                 return;
313         }
314
315         /**
316          * See if there is any chat data waiting.
317          */
318         output_data = strdup("");
319         do {
320                 got_data = 0;
321                 pf.fd = WC->chat_sock;
322                 pf.events = POLLIN;
323                 pf.revents = 0;
324                 if (poll(&pf, 1, 1) > 0) if (pf.revents & POLLIN) {
325                         ++got_data;
326
327                         /** Temporarily swap the serv and chat sockets during chat talk */
328                         i = WC->serv_sock;
329                         WC->serv_sock = WC->chat_sock;
330                         WC->chat_sock = i;
331         
332                         serv_getln(buf, sizeof buf);
333
334                         if (!strcmp(buf, "000")) {
335                                 strcpy(buf, ":|");
336                                 strcat(buf, _("Now exiting chat mode."));
337                                 end_chat_now = 1;
338                         }
339                         
340                         /** Unswap the sockets. */
341                         i = WC->serv_sock;
342                         WC->serv_sock = WC->chat_sock;
343                         WC->chat_sock = i;
344
345                         /** Append our output data */
346                         output_data = realloc(output_data, strlen(output_data) + strlen(buf) + 4);
347                         strcat(output_data, buf);
348                         strcat(output_data, "\n");
349                 }
350
351         } while ( (got_data) && (!end_chat_now) );
352
353         if (end_chat_now) {
354                 close(WC->chat_sock);
355                 WC->chat_sock = (-1);
356                 wprintf("<img src=\"static/blank.gif\" onLoad=\"parent.window.close();\">\n");
357         }
358
359         if (strlen(output_data) > 0) {
360
361                 if (output_data[strlen(output_data)-1] == '\n') {
362                         output_data[strlen(output_data)-1] = 0;
363                 }
364
365                 /** Output our fun to the other frame. */
366                 wprintf("<img src=\"static/blank.gif\" WIDTH=1 HEIGHT=1\n"
367                         "onLoad=\" \n"
368                 );
369
370                 for (i=0; i<num_tokens(output_data, '\n'); ++i) {
371                         extract_token(buf, output_data, i, '\n', sizeof buf);
372                         extract_token(cl_user, buf, 0, '|', sizeof cl_user);
373                         extract_token(cl_text, buf, 1, '|', sizeof cl_text);
374
375                         if (strcasecmp(cl_text, "NOOP")) {
376
377                                 wprintf("parent.chat_transcript.document.write('");
378         
379                                 if (strcasecmp(cl_user, WC->last_chat_user)) {
380                                         wprintf("<TABLE border=0 WIDTH=100%% "
381                                                 "CELLSPACING=1 CELLPADDING=0 "
382                                                 "BGCOLOR=&quot;#FFFFFF&quot;>"
383                                                 "<TR><TD></TR></TD></TABLE>"
384                                         );
385         
386                                 }
387
388                                 wprintf("<TABLE border=0 WIDTH=100%% "
389                                         "CELLSPACING=0 CELLPADDING=0 "
390                                         "BGCOLOR=&quot;#EEEEEE&quot;>");
391         
392                                 wprintf("<TR><TD>");
393         
394                                 if (!strcasecmp(cl_user, ":")) {
395                                         wprintf("<I>");
396                                 }
397
398                                 if (strcasecmp(cl_user, WC->last_chat_user)) {
399                                         wprintf("<B>");
400         
401                                         if (!strcasecmp(cl_user, WC->wc_fullname)) {
402                                                 wprintf("<FONT COLOR=&quot;#FF0000&quot;>");
403                                         }
404                                         else {
405                                                 wprintf("<FONT COLOR=&quot;#0000FF&quot;>");
406                                         }
407                                         jsescputs(cl_user);
408         
409                                         wprintf("</FONT>: </B>");
410                                 }
411                                 else {
412                                         wprintf("&nbsp;&nbsp;&nbsp;");
413                                 }
414                                 jsescputs(cl_text);
415                                 if (!strcasecmp(cl_user, ":")) {
416                                         wprintf("</I>");
417                                 }
418
419                                 wprintf("</TD></TR></TABLE>");
420                                 wprintf("'); \n");
421
422                                 strcpy(WC->last_chat_user, cl_user);
423                         }
424                 }
425
426                 wprintf("parent.chat_transcript.scrollTo(999999,999999);\">\n");
427         }
428
429         free(output_data);
430
431         wprintf("</BODY></HTML>\n");
432         wDumpContent(0);
433 }
434
435
436 /**
437  * \brief sending side of the chat window
438  */
439 void chat_send(void) {
440         int i;
441         char send_this[SIZ];
442         char buf[SIZ];
443
444         output_headers(0, 0, 0, 0, 0, 0);
445         wprintf("Content-type: text/html; charset=utf-8\n");
446         wprintf("\n");
447         wprintf("<HTML>"
448                 "<BODY onLoad=\"document.chatsendform.send_this.focus();\" >"
449         );
450
451         if (bstr("send_this") != NULL) {
452                 strcpy(send_this, bstr("send_this"));
453         }
454         else {
455                 strcpy(send_this, "");
456         }
457
458         if (strlen(bstr("help_button")) > 0) {
459                 strcpy(send_this, "/help");
460         }
461
462         if (strlen(bstr("list_button")) > 0) {
463                 strcpy(send_this, "/who");
464         }
465
466         if (strlen(bstr("exit_button")) > 0) {
467                 strcpy(send_this, "/quit");
468         }
469
470         if (setup_chat_socket() != 0) {
471                 wprintf(_("An error occurred while setting up the chat socket."));
472                 wprintf("</BODY></HTML>\n");
473                 wDumpContent(0);
474                 return;
475         }
476
477         /** Temporarily swap the serv and chat sockets during chat talk */
478         i = WC->serv_sock;
479         WC->serv_sock = WC->chat_sock;
480         WC->chat_sock = i;
481
482         while (strlen(send_this) > 0) {
483                 if (strlen(send_this) < 67) {
484                         serv_puts(send_this);
485                         strcpy(send_this, "");
486                 }
487                 else {
488                         for (i=55; i<67; ++i) {
489                                 if (send_this[i] == ' ') break;
490                         }
491                         strncpy(buf, send_this, i);
492                         buf[i] = 0;
493                         strcpy(send_this, &send_this[i]);
494                         serv_puts(buf);
495                 }
496         }
497
498         /** Unswap the sockets. */
499         i = WC->serv_sock;
500         WC->serv_sock = WC->chat_sock;
501         WC->chat_sock = i;
502
503         wprintf("<FORM METHOD=\"POST\" action=\"chat_send\" NAME=\"chatsendform\">\n");
504         wprintf("<INPUT TYPE=\"text\" SIZE=\"80\" MAXLENGTH=\"%d\" "
505                 "NAME=\"send_this\">\n", SIZ-10);
506         wprintf("<br />");
507         wprintf("<INPUT TYPE=\"submit\" NAME=\"send_button\" VALUE=\"%s\">\n", _("Send"));
508         wprintf("<INPUT TYPE=\"submit\" NAME=\"help_button\" VALUE=\"%s\">\n", _("Help"));
509         wprintf("<INPUT TYPE=\"submit\" NAME=\"list_button\" VALUE=\"%s\">\n", _("List users"));
510         wprintf("<INPUT TYPE=\"submit\" NAME=\"exit_button\" VALUE=\"%s\">\n", _("Exit"));
511         wprintf("</FORM>\n");
512
513         wprintf("</BODY></HTML>\n");
514         wDumpContent(0);
515 }
516
517 /*@}*/