]> code.citadel.org Git - citadel.git/blob - webcit/messages.c
* Made the header-bar buttons more visible
[citadel.git] / webcit / messages.c
1
2
3
4
5 #include <ctype.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <stdio.h>
9 #include <fcntl.h>
10 #include <signal.h>
11 #include <sys/types.h>
12 #include <sys/wait.h>
13 #include <sys/socket.h>
14 #include <limits.h>
15 #include <netinet/in.h>
16 #include <netdb.h>
17 #include <string.h>
18 #include <pwd.h>
19 #include <errno.h>
20 #include <stdarg.h>
21 #include <pthread.h>
22 #include <signal.h>
23 #include "webcit.h"
24
25
26
27
28
29 /*
30  * Look for URL's embedded in a buffer and make them linkable.  We use a
31  * target window in order to keep the BBS session in its own window.
32  */
33 void url(buf)
34 char buf[];
35 {
36
37         int pos;
38         int start, end;
39         char ench;
40         char urlbuf[256];
41         char outbuf[1024];
42
43         start = (-1);
44         end = strlen(buf);
45         ench = 0;
46
47         for (pos = 0; pos < strlen(buf); ++pos) {
48                 if (!strncasecmp(&buf[pos], "http://", 7))
49                         start = pos;
50                 if (!strncasecmp(&buf[pos], "ftp://", 6))
51                         start = pos;
52         }
53
54         if (start < 0)
55                 return;
56
57         if ((start > 0) && (buf[start - 1] == '<'))
58                 ench = '>';
59         if ((start > 0) && (buf[start - 1] == '['))
60                 ench = ']';
61         if ((start > 0) && (buf[start - 1] == '('))
62                 ench = ')';
63         if ((start > 0) && (buf[start - 1] == '{'))
64                 ench = '}';
65
66         for (pos = strlen(buf); pos > start; --pos) {
67                 if ((buf[pos] == ' ') || (buf[pos] == ench))
68                         end = pos;
69         }
70
71         strncpy(urlbuf, &buf[start], end - start);
72         urlbuf[end - start] = 0;
73
74
75         strncpy(outbuf, buf, start);
76         sprintf(&outbuf[start], "%cA HREF=%c%s%c TARGET=%c%s%c%c%s%c/A%c",
77                 LB, QU, urlbuf, QU, QU, TARGET, QU, RB, urlbuf, LB, RB);
78         strcat(outbuf, &buf[end]);
79         if ( strlen(outbuf) < 250 )
80                 strcpy(buf, outbuf);
81 }
82
83
84 void read_message(msgnum, oper)
85 long msgnum;
86 char *oper;
87 {
88         char buf[256];
89         char m_subject[256];
90         char from[256];
91         char node[256];
92         char rfca[256];
93         char reply_to[512];
94         char now[256];
95         int format_type = 0;
96         int nhdr = 0;
97         int bq = 0;
98
99         strcpy(from, "");
100         strcpy(node, "");
101         strcpy(rfca, "");
102         strcpy(reply_to, "");
103
104         sprintf(buf, "MSG0 %ld", msgnum);
105         serv_puts(buf);
106         serv_gets(buf);
107         if (buf[0] != '1') {
108                 wprintf("<STRONG>ERROR:</STRONG> %s<BR>\n", &buf[4]);
109                 return;
110         }
111         wprintf("<TABLE WIDTH=100% BORDER=0 CELLSPACING=0 CELLPADDING=1 BGCOLOR=000077><TR><TD>\n");
112         wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\" SIZE=+1 COLOR=\"FFFF00\"> ");
113         strcpy(m_subject, "");
114
115         while (serv_gets(buf), strncasecmp(buf, "text", 4)) {
116                 if (!strncasecmp(buf, "nhdr=yes", 8))
117                         nhdr = 1;
118                 if (nhdr == 1)
119                         buf[0] = '_';
120                 if (!strncasecmp(buf, "type=", 5))
121                         format_type = atoi(&buf[5]);
122                 if (!strncasecmp(buf, "from=", 5)) {
123                         strcpy(from, &buf[5]);
124                         wprintf("from ");
125                         escputs(from);
126                         wprintf(" ");
127                 }
128                 if (!strncasecmp(buf, "subj=", 5))
129                         strcpy(m_subject, &buf[5]);
130                 if ((!strncasecmp(buf, "hnod=", 5))
131                     && (strcasecmp(&buf[5], serv_info.serv_humannode)))
132                         wprintf("(%s) ", &buf[5]);
133                 if ((!strncasecmp(buf, "room=", 5))
134                     && (strcasecmp(&buf[5], WC->wc_roomname)))
135                         wprintf("in %s> ", &buf[5]);
136                 if (!strncasecmp(buf, "rfca=", 5)) {
137                         strcpy(rfca, &buf[5]);
138                         wprintf("&lt;");
139                         escputs(rfca);
140                         wprintf("&gt; ");
141                 }
142
143                 if (!strncasecmp(buf, "node=", 5)) {
144                         if ( ((WC->room_flags & QR_NETWORK)
145                         || ((strcasecmp(&buf[5], serv_info.serv_nodename)
146                         && (strcasecmp(&buf[5], serv_info.serv_fqdn)))))
147                         && (strlen(rfca)==0)
148                         ) {
149                                 wprintf("@%s ", &buf[5]);
150                         }
151                 }
152                 if (!strncasecmp(buf, "rcpt=", 5))
153                         wprintf("to %s ", &buf[5]);
154                 if (!strncasecmp(buf, "time=", 5)) {
155                         fmt_date(now, atol(&buf[5]));
156                         wprintf("%s ", now);
157                 }
158         }
159
160
161         /* Generate a reply-to address */
162         if (strlen(rfca) > 0) {
163                 strcpy(reply_to, rfca);
164         }
165         else {
166                 if (strlen(node) > 0) {
167                         snprintf(reply_to, sizeof(reply_to), "%s @ %s",
168                                 from, node);
169                 }
170                 else {
171                         snprintf(reply_to, sizeof(reply_to), "%s", from);
172                 }
173         }
174
175         if (nhdr == 1)
176                 wprintf("****");
177         wprintf("</FONT></TD>");
178
179         /* begin right-hand toolbar */
180         wprintf("<TD ALIGN=RIGHT>\n"
181                 "<TABLE BORDER=0><TR>\n");
182
183         wprintf("<TD BGCOLOR=\"AAAADD\">"
184                 "<A HREF=\"/display_enter?recp=");
185         urlescputs(reply_to);
186         wprintf("\">Reply</A>"
187                 "</TD>\n", msgnum);
188
189         if (WC->is_room_aide) {
190                 wprintf("<TD BGCOLOR=\"AAAADD\">"
191                         "<A HREF=\"/confirm_move_msg"
192                         "&msgid=%ld"
193                         "\">Move</A>"
194                         "</TD>\n", msgnum);
195
196                 wprintf("<TD BGCOLOR=\"AAAADD\">"
197                         "<A HREF=\"/confirm_delete_msg"
198                         "&msgid=%ld"
199                         "\">Del</A>"
200                         "</TD>\n", msgnum);
201
202         }
203
204         wprintf("</TR></TABLE>\n"
205                 "</TD>\n");
206
207         /* end right-hand toolbar */
208
209
210         if (strlen(m_subject) > 0) {
211                 wprintf("<TR><TD><FONT COLOR=\"FFFFFF\">"
212                         "Subject: %s</FONT>"
213                         "</TD><TD>&nbsp;</TD></TR>\n", m_subject);
214         }
215
216         wprintf("</TR></TABLE>\n");
217
218         if (format_type == 0) {
219                 fmout(NULL);
220         } else {
221                 while (serv_gets(buf), strcmp(buf, "000")) {
222                         while ((strlen(buf) > 0) && (isspace(buf[strlen(buf) - 1])))
223                                 buf[strlen(buf) - 1] = 0;
224                         if ((bq == 0) &&
225                             ((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) || (!strncmp(buf, " :-)", 4)))) {
226                                 wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\" COLOR=\"000044\"><I>");
227                                 bq = 1;
228                         } else if ((bq == 1) &&
229                                    (strncmp(buf, ">", 1)) && (strncmp(buf, " >", 2)) && (strncmp(buf, " :-)", 4))) {
230                                 wprintf("</FONT></I>");
231                                 bq = 0;
232                         }
233                         wprintf("<TT>");
234                         url(buf);
235                         escputs(buf);
236                         wprintf("</TT><BR>\n");
237                 }
238         }
239         wprintf("</I><BR>");
240 }
241
242
243
244 /* 
245  * load message pointers from the server
246  */
247 int load_msg_ptrs(servcmd)
248 char *servcmd;
249 {
250         char buf[256];
251         int nummsgs;
252
253         nummsgs = 0;
254         serv_puts(servcmd);
255         serv_gets(buf);
256         if (buf[0] != '1') {
257                 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
258                 return (nummsgs);
259         }
260         while (serv_gets(buf), strcmp(buf, "000")) {
261                 WC->msgarr[nummsgs] = atol(buf);
262                 ++nummsgs;
263         }
264         return (nummsgs);
265 }
266
267
268 /*
269  * command loop for reading messages
270  */
271 void readloop(char *oper)
272 {
273         char cmd[256];
274         int a;
275         int nummsgs;
276
277         output_headers(1);
278
279         wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\"><CENTER><B>%s - ",
280                 WC->wc_roomname);
281         if (!strcmp(oper, "readnew")) {
282                 strcpy(cmd, "MSGS NEW");
283                 wprintf("new messages");
284         } else if (!strcmp(oper, "readold")) {
285                 strcpy(cmd, "MSGS OLD");
286                 wprintf("old messages");
287         } else {
288                 strcpy(cmd, "MSGS ALL");
289                 wprintf("all messages");
290         }
291         wprintf("</B></CENTER><BR>\n");
292
293         nummsgs = load_msg_ptrs(cmd);
294         if (nummsgs == 0) {
295                 if (!strcmp(oper, "readnew")) {
296                         wprintf("<EM>No new messages in this room.</EM>\n");
297                 } else if (!strcmp(oper, "readold")) {
298                         wprintf("<EM>No old messages in this room.</EM>\n");
299                 } else {
300                         wprintf("<EM>This room is empty.</EM>\n");
301                 }
302                 goto DONE;
303         }
304         for (a = 0; a < nummsgs; ++a) {
305                 read_message(WC->msgarr[a], oper);
306         }
307
308 DONE:   wDumpContent(1);
309 }
310
311
312
313
314 /*
315  * Post message (or don't post message)
316  *
317  * Note regarding the "dont_post" variable:
318  * A random value (actually, it's just a timestamp) is inserted as a hidden
319  * field called "postseq" when the display_enter page is generated.  This
320  * value is checked when posting, using the static variable dont_post.  If a
321  * user attempts to post twice using the same dont_post value, the message is
322  * discarded.  This prevents the accidental double-saving of the same message
323  * if the user happens to click the browser "back" button.
324  */
325 void post_message(void)
326 {
327         char buf[256];
328         static long dont_post = (-1L);
329
330         output_headers(1);
331
332         wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\">");
333         strcpy(buf, bstr("sc"));
334         if (strcasecmp(buf, "Save message")) {
335                 wprintf("Cancelled.  Message was not posted.<BR>\n");
336         } else if (atol(bstr("postseq")) == dont_post) {
337                 wprintf("Automatically cancelled because you have already "
338                         "saved this message.<BR>\n");
339         } else {
340                 sprintf(buf, "ENT0 1|%s|0|0", bstr("recp"));
341                 serv_puts(buf);
342                 serv_gets(buf);
343                 if (buf[0] == '4') {
344                         text_to_server(bstr("msgtext"));
345                         serv_puts("000");
346                         wprintf("Message has been posted.<BR>\n");
347                         dont_post = atol(bstr("postseq"));
348                 } else {
349                         wprintf("<EM>%s</EM><BR>\n", &buf[4]);
350                 }
351         }
352
353         wDumpContent(1);
354 }
355
356
357
358
359
360
361
362
363 /*
364  * prompt for a recipient (to be called from display_enter() only)
365  */
366 void prompt_for_recipient()
367 {
368
369         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=007700><TR><TD>");
370         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
371         wprintf("<B>Send private e-mail</B>\n");
372         wprintf("</FONT></TD></TR></TABLE>\n");
373
374         wprintf("<CENTER>");
375         wprintf("<FORM METHOD=\"POST\" ACTION=\"/display_enter\">\n");
376         wprintf("Enter recipient: ");
377         wprintf("<INPUT TYPE=\"text\" NAME=\"recp\" MAXLENGTH=\"64\"><BR>\n");
378         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Enter message\">");
379         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\">");
380         wprintf("</FORM></CENTER>\n");
381 }
382
383
384
385 /*
386  * display the message entry screen
387  */
388 void display_enter(void)
389 {
390         char buf[256];
391         long now;
392         struct tm *tm;
393
394         output_headers(1);
395
396         wprintf("<FACE=\"Arial,Helvetica,sans-serif\">");
397
398         sprintf(buf, "ENT0 0|%s|0|0", bstr("recp"));
399         serv_puts(buf);
400         serv_gets(buf);
401
402         if (!strncmp(buf, "570", 3)) {
403                 if (strlen(bstr("recp")) > 0) {
404                         wprintf("<EM>%s</EM><BR>\n", &buf[4]);
405                 }
406                 prompt_for_recipient();
407                 goto DONE;
408         }
409         if (buf[0] != '2') {
410                 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
411                 goto DONE;
412         }
413         wprintf("<CENTER>Enter message below.  Messages are formatted to\n");
414         wprintf("the <EM>reader's</EM> screen width.  To defeat the\n");
415         wprintf("formatting, indent a line at least one space.  \n");
416         wprintf("<BR>");
417
418         now = time(NULL);
419         tm = (struct tm *) localtime(&now);
420         strcpy(buf, (char *) asctime(tm));
421         buf[strlen(buf) - 1] = 0;
422         strcpy(&buf[16], &buf[19]);
423         wprintf("</CENTER><FONT COLOR=\"440000\"><B> %s ", &buf[4]);
424         wprintf("from %s ", WC->wc_username);
425         if (strlen(bstr("recp")) > 0)
426                 wprintf("to %s ", bstr("recp"));
427         wprintf("in %s&gt; ", WC->wc_roomname);
428         wprintf("</B></FONT><BR><CENTER>\n");
429
430         wprintf("<FORM METHOD=\"POST\" ACTION=\"/post\">\n");
431         wprintf("<INPUT TYPE=\"hidden\" NAME=\"recp\" VALUE=\"%s\">\n",
432                 bstr("recp"));
433         wprintf("<INPUT TYPE=\"hidden\" NAME=\"postseq\" VALUE=\"%ld\">\n",
434                 now);
435         wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Save message\">"
436                 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\"><BR>\n");
437
438         wprintf("<TEXTAREA NAME=\"msgtext\" wrap=soft ROWS=30 COLS=80 "
439                 "WIDTH=80></TEXTAREA><P>\n");
440
441         wprintf("</FORM></CENTER>\n");
442 DONE:   wDumpContent(1);
443         wprintf("</FONT>");
444 }
445
446
447
448
449
450
451
452 /*
453  * Confirm deletion of a message
454  */
455 void confirm_delete_msg(void)
456 {
457         long msgid;
458
459         msgid = atol(bstr("msgid"));
460
461         output_headers(1);
462
463         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
464         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
465         wprintf("<B>Confirm deletion of message</B>\n");
466         wprintf("</FONT></TD></TR></TABLE>\n");
467
468         wprintf("<CENTER>");
469
470         wprintf("Are you sure you want to delete this message? <BR>\n");
471
472         wprintf("<FORM METHOD=\"POST\" ACTION=\"/delete_msg\">\n");
473         wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgid\" VALUE=\"%s\">\n",
474                 bstr("msgid"));
475         wprintf("<INPUT TYPE=\"submit\" NAME=\"yesno\" VALUE=\"Yes\">");
476         wprintf("<INPUT TYPE=\"submit\" NAME=\"yesno\" VALUE=\"No\">");
477         wprintf("</FORM></CENTER>\n");
478
479         wprintf("</CENTER>\n");
480         wDumpContent(1);
481 }
482
483
484
485 void delete_msg(void)
486 {
487         long msgid;
488         char buf[256];
489
490         msgid = atol(bstr("msgid"));
491
492         output_headers(1);
493
494         if (!strcasecmp(bstr("yesno"), "Yes")) {
495                 sprintf(buf, "DELE %ld", msgid);
496                 serv_puts(buf);
497                 serv_gets(buf);
498                 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
499         } else {
500                 wprintf("<EM>Message not deleted.</EM><BR>\n");
501         }
502
503         wDumpContent(1);
504 }
505
506
507
508
509 /*
510  * Confirm move of a message
511  */
512 void confirm_move_msg(void)
513 {
514         long msgid;
515         char buf[256];
516         char targ[256];
517
518         msgid = atol(bstr("msgid"));
519
520         output_headers(1);
521
522         wprintf("<TABLE WIDTH=100% BORDER=0 BGCOLOR=770000><TR><TD>");
523         wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
524         wprintf("<B>Confirm move of message</B>\n");
525         wprintf("</FONT></TD></TR></TABLE>\n");
526
527         wprintf("<CENTER>");
528
529         wprintf("Please select the room to which you would like this message moved:<BR>\n");
530
531         wprintf("<FORM METHOD=\"POST\" ACTION=\"/move_msg\">\n");
532         wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgid\" VALUE=\"%s\">\n",
533                 bstr("msgid"));
534
535
536         wprintf("<SELECT NAME=\"target_room\" SIZE=5>\n");
537         serv_puts("LKRA");
538         serv_gets(buf);
539         if (buf[0] == '1') {
540                 while (serv_gets(buf), strcmp(buf, "000")) {
541                         extract(targ, buf, 0);
542                         wprintf("<OPTION>");
543                         escputs(targ);
544                         wprintf("\n");
545                 }
546         }
547         wprintf("</SELECT>\n");
548         wprintf("<BR>\n");
549
550         wprintf("<INPUT TYPE=\"submit\" NAME=\"yesno\" VALUE=\"Move\">");
551         wprintf("<INPUT TYPE=\"submit\" NAME=\"yesno\" VALUE=\"Cancel\">");
552         wprintf("</FORM></CENTER>\n");
553
554         wprintf("</CENTER>\n");
555         wDumpContent(1);
556 }
557
558
559
560 void move_msg(void)
561 {
562         long msgid;
563         char buf[256];
564
565         msgid = atol(bstr("msgid"));
566
567         output_headers(1);
568
569         if (!strcasecmp(bstr("yesno"), "Move")) {
570                 sprintf(buf, "MOVE %ld|%s", msgid, bstr("target_room"));
571                 serv_puts(buf);
572                 serv_gets(buf);
573                 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
574         } else {
575                 wprintf("<EM>Message not deleted.</EM><BR>\n");
576         }
577
578         wDumpContent(1);
579 }