4 * Functions which deal with the fetching and displaying of messages.
14 #include <sys/types.h>
16 #include <sys/socket.h>
18 #include <netinet/in.h>
31 * Look for URL's embedded in a buffer and make them linkable. We use a
32 * target window in order to keep the BBS session in its own window.
48 for (pos = 0; pos < strlen(buf); ++pos) {
49 if (!strncasecmp(&buf[pos], "http://", 7))
51 if (!strncasecmp(&buf[pos], "ftp://", 6))
58 if ((start > 0) && (buf[start - 1] == '<'))
60 if ((start > 0) && (buf[start - 1] == '['))
62 if ((start > 0) && (buf[start - 1] == '('))
64 if ((start > 0) && (buf[start - 1] == '{'))
67 for (pos = strlen(buf); pos > start; --pos) {
68 if ((buf[pos] == ' ') || (buf[pos] == ench))
72 strncpy(urlbuf, &buf[start], end - start);
73 urlbuf[end - start] = 0;
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 )
84 /* display_vcard() calls this after parsing the textual vCard into
85 * our 'struct vCard' data object.
87 * Set 'full' to nonzero to display the full card, otherwise it will only
88 * show a summary line.
90 void display_parsed_vcard(struct vCard *v, int full) {
97 name = vcard_get_prop(v, "n", 1, 0, 0);
109 wprintf("<TABLE bgcolor=#888888>");
110 if (v->numprops) for (i=0; i<(v->numprops); ++i) {
111 if (!strcasecmp(v->prop[i].name, "n")) {
112 wprintf("<TR BGCOLOR=#AAAAAA>"
113 "<TD BGCOLOR=#FFFFFF>"
114 "<IMG VALIGN=CENTER SRC=\"/static/vcard.gif\"></TD>"
115 "<TD><FONT SIZE=+1><B>");
116 escputs(v->prop[i].value);
117 wprintf("</B></FONT></TD></TR>\n");
119 else if (!strcasecmp(v->prop[i].name, "email;internet")) {
120 wprintf("<TR><TD>Internet e-mail:</TD>"
121 "<TD><A HREF=\"mailto:");
122 urlescputs(v->prop[i].value);
124 escputs(v->prop[i].value);
125 wprintf("</A></TD></TR>\n");
127 else if (!strcasecmp(v->prop[i].name, "adr")) {
128 wprintf("<TR><TD>Address:</TD><TD>");
129 for (j=0; j<num_tokens(v->prop[i].value, ';'); ++j) {
130 extract_token(buf, v->prop[i].value, j, ';');
131 if (strlen(buf) > 0) {
136 wprintf("</TD></TR>\n");
138 else if (!strncasecmp(v->prop[i].name, "tel;", 4)) {
139 wprintf("<TR><TD>%s telephone:</TD><TD>",
140 &v->prop[i].name[4]);
141 for (j=0; j<num_tokens(v->prop[i].value, ';'); ++j) {
142 extract_token(buf, v->prop[i].value, j, ';');
143 if (strlen(buf) > 0) {
148 wprintf("</TD></TR>\n");
152 escputs(v->prop[i].name);
153 wprintf("</TD><TD>");
154 escputs(v->prop[i].value);
155 wprintf("</TD></TR>\n");
158 wprintf("</TABLE>\n");
164 * Display a textual vCard
165 * (Converts to a vCard object and then calls the actual display function)
166 * Set 'full' to nonzero to display the whole card instead of a one-liner
168 void display_vcard(char *vcard_source, char alpha, int full) {
174 v = vcard_load(vcard_source);
175 if (v == NULL) return;
177 name = vcard_get_prop(v, "n", 1, 0, 0);
184 || ((isalpha(alpha)) && (tolower(alpha) == tolower(this_alpha)) )
185 || ((!isalpha(alpha)) && (!isalpha(this_alpha))) ) {
187 display_parsed_vcard(v, full);
197 void output_text_plain(char *partbuf, int total_length) {
199 write(WC->http_sock, partbuf, total_length);
200 wprintf("</PRE><BR>\n");
207 * Output the chosen part of a MIME message. This might be chosen from
208 * a multipart/alternative or it might be chosen because it's the only one
209 * present. We care not why it was chosen; it is our job to be a servile
210 * little function and do what we are told.
212 void output_chosen_part(long msgnum, char *multipart_chosen) {
215 int total_length = 0;
216 int downloaded_length = 0;
217 int block_length = 0;
218 char content_type[SIZ];
220 serv_printf("OPNA %ld|%s", msgnum, multipart_chosen);
223 wprintf("<I>Error reading msg %ld part %s</I><BR><BR>",
224 msgnum, multipart_chosen);
228 total_length = extract_int(&buf[4], 0);
229 extract(content_type, &buf[4], 3);
231 if ( (strlen(content_type) ==0)
232 ||(!strcasecmp(content_type, "text"))
233 ||(!strcasecmp(content_type, "text/english"))
235 strcpy(content_type, "text/plain");
238 partbuf = malloc(total_length + 1);
239 if (partbuf == NULL) {
240 wprintf("<I>Memory allocation error</I><BR><BR>");
244 partbuf[total_length] = 0; /* Give it a nice null terminator */
246 /* FIXME ... add something to make this die if we
247 * lose the server connection.
249 while (downloaded_length < total_length) {
250 if ((total_length - downloaded_length) < 4096) {
251 block_length = total_length - downloaded_length;
256 serv_printf("READ %d|%d", downloaded_length, block_length);
259 block_length = extract_int(&buf[4], 0);
260 serv_read(partbuf, block_length);
261 downloaded_length += block_length;
268 if (!strcasecmp(content_type, "text/plain")) {
269 output_text_plain(partbuf, total_length);
271 if (!strcasecmp(content_type, "text/html")) {
272 output_text_html(partbuf, total_length);
275 wprintf("<I>Unknown content type %s</I><BR><BR>\n",
287 * I wanna SEE that message!
289 void read_message(long msgnum) {
291 char mime_partnum[SIZ];
292 char mime_filename[SIZ];
293 char mime_content_type[SIZ];
294 char mime_disposition[SIZ];
296 char *mime_http = NULL;
306 char vcard_partnum[SIZ];
307 char *vcard_source = NULL;
308 int multipart_hunting = 0;
309 char multipart_chosen[SIZ];
310 char multipart_prefix[SIZ];
315 strcpy(reply_to, "");
316 strcpy(vcard_partnum, "");
317 strcpy(multipart_chosen, "1");
319 serv_printf("MSG0 %ld|1", msgnum); /* ask for headers only */
322 wprintf("<STRONG>ERROR:</STRONG> %s<BR>\n", &buf[4]);
326 wprintf("<TABLE WIDTH=100%% BORDER=0 CELLSPACING=0 "
327 "CELLPADDING=1 BGCOLOR=CCCCCC><TR><TD>\n");
331 wprintf("COLOR=\"000000\"> ");
332 strcpy(m_subject, "");
334 while (serv_gets(buf), strcasecmp(buf, "000")) {
335 if (!strncasecmp(buf, "nhdr=yes", 8))
339 if (!strncasecmp(buf, "type=", 5))
340 format_type = atoi(&buf[5]);
341 if (!strncasecmp(buf, "from=", 5)) {
342 strcpy(from, &buf[5]);
343 wprintf("from <A HREF=\"/showuser&who=");
349 if (!strncasecmp(buf, "subj=", 5))
350 strcpy(m_subject, &buf[5]);
351 if ((!strncasecmp(buf, "hnod=", 5))
352 && (strcasecmp(&buf[5], serv_info.serv_humannode)))
353 wprintf("(%s) ", &buf[5]);
354 if ((!strncasecmp(buf, "room=", 5))
355 && (strcasecmp(&buf[5], WC->wc_roomname)))
356 wprintf("in %s> ", &buf[5]);
357 if (!strncasecmp(buf, "rfca=", 5)) {
358 strcpy(rfca, &buf[5]);
364 if (!strncasecmp(buf, "node=", 5)) {
365 if ( ((WC->room_flags & QR_NETWORK)
366 || ((strcasecmp(&buf[5], serv_info.serv_nodename)
367 && (strcasecmp(&buf[5], serv_info.serv_fqdn)))))
370 wprintf("@%s ", &buf[5]);
373 if (!strncasecmp(buf, "rcpt=", 5))
374 wprintf("to %s ", &buf[5]);
375 if (!strncasecmp(buf, "time=", 5)) {
376 fmt_date(now, atol(&buf[5]));
380 if (format_type == 4) {
381 if (!strncasecmp(buf, "pref=", 5)) {
382 extract(multipart_prefix, &buf[5], 1);
383 if (!strcasecmp(multipart_prefix,
384 "multipart/alternative")) {
388 if (!strncasecmp(buf, "suff=", 5)) {
389 extract(multipart_prefix, &buf[5], 1);
390 if (!strcasecmp(multipart_prefix,
391 "multipart/alternative")) {
395 if (!strncasecmp(buf, "part=", 5)) {
396 if (multipart_hunting > 0) {
397 extract(mime_partnum, &buf[5], 2);
398 extract(mime_content_type, &buf[5], 4);
399 if ( (!strcasecmp(mime_content_type,
401 || (!strcasecmp(mime_content_type,
403 strcpy(multipart_chosen,
410 if (!strncasecmp(buf, "part=", 5)) {
411 extract(mime_filename, &buf[5], 1);
412 extract(mime_partnum, &buf[5], 2);
413 extract(mime_disposition, &buf[5], 3);
414 extract(mime_content_type, &buf[5], 4);
415 mime_length = extract_int(&buf[5], 5);
417 if (!strcasecmp(mime_disposition, "attachment")) {
418 if (mime_http == NULL) {
419 mime_http = malloc(512);
420 strcpy(mime_http, "");
423 mime_http = realloc(mime_http,
424 strlen(mime_http) + 512);
426 sprintf(&mime_http[strlen(mime_http)],
427 "<A HREF=\"/output_mimepart?"
428 "msgnum=%ld&partnum=%s\" "
429 "TARGET=\"wc.%ld.%s\">"
430 "<IMG SRC=\"/static/attachment.gif\" "
431 "BORDER=0 ALIGN=MIDDLE>\n"
432 "Part %s: %s (%s, %d bytes)</A><BR>\n",
433 msgnum, mime_partnum,
434 msgnum, mime_partnum,
435 mime_partnum, mime_filename,
436 mime_content_type, mime_length);
439 if ((!strcasecmp(mime_disposition, "inline"))
440 && (!strncasecmp(mime_content_type, "image/", 6)) ){
441 if (mime_http == NULL) {
442 mime_http = malloc(512);
443 strcpy(mime_http, "");
446 mime_http = realloc(mime_http,
447 strlen(mime_http) + 512);
449 sprintf(&mime_http[strlen(mime_http)],
450 "<IMG SRC=\"/output_mimepart?"
451 "msgnum=%ld&partnum=%s\">",
452 msgnum, mime_partnum);
455 if (!strcasecmp(mime_content_type, "text/x-vcard")) {
456 strcpy(vcard_partnum, mime_partnum);
464 /* Generate a reply-to address */
465 if (strlen(rfca) > 0) {
466 strcpy(reply_to, rfca);
469 if (strlen(node) > 0) {
470 snprintf(reply_to, sizeof(reply_to), "%s @ %s",
474 snprintf(reply_to, sizeof(reply_to), "%s", from);
482 wprintf("</FONT></TD>");
484 wprintf("<TD ALIGN=RIGHT>\n"
485 "<TABLE BORDER=0><TR>\n");
487 wprintf("<TD BGCOLOR=\"AAAADD\">"
488 "<A HREF=\"/readfwd?startmsg=%ld", msgnum);
489 wprintf("&maxmsgs=1&summary=0\">Read</A>"
492 wprintf("<TD BGCOLOR=\"AAAADD\">"
493 "<A HREF=\"/display_enter?recp=");
494 urlescputs(reply_to);
495 wprintf("\"><FONT SIZE=-1>Reply</FONT></A>"
498 if (WC->is_room_aide) {
499 wprintf("<TD BGCOLOR=\"AAAADD\">"
500 "<A HREF=\"/confirm_move_msg"
502 "\"><FONT SIZE=-1>Move</FONT></A>"
505 wprintf("<TD BGCOLOR=\"AAAADD\">"
506 "<A HREF=\"/delete_msg"
508 "onClick=\"return confirm('Delete this message?');\""
509 "><FONT SIZE=-1>Del</FONT></A>"
513 wprintf("</TR></TABLE>\n"
516 if (strlen(m_subject) > 0) {
517 wprintf("<TR><TD><FONT COLOR=\"0000FF\">"
519 "</TD><TD> </TD></TR>\n", m_subject);
522 wprintf("</TR></TABLE>\n");
525 /* Messages in legacy Citadel variformat get handled thusly... */
526 if (format_type == 0) {
527 serv_printf("MSG0 %ld", msgnum);
530 while (serv_gets(buf), strncasecmp(buf, "text", 4)) { }
535 /* Boring old 80-column fixed format text gets handled this way... */
536 if (format_type == 1) {
537 serv_printf("MSG0 %ld", msgnum);
540 while (serv_gets(buf), strncasecmp(buf, "text", 4)) { }
541 while (serv_gets(buf), strcmp(buf, "000")) {
542 while ((strlen(buf) > 0) && (isspace(buf[strlen(buf) - 1])))
543 buf[strlen(buf) - 1] = 0;
545 ((!strncmp(buf, ">", 1)) || (!strncmp(buf, " >", 2)) || (!strncmp(buf, " :-)", 4)))) {
546 wprintf("<FONT COLOR=\"000044\"><I>");
548 } else if ((bq == 1) &&
549 (strncmp(buf, ">", 1)) && (strncmp(buf, " >", 2)) && (strncmp(buf, " :-)", 4))) {
550 wprintf("</FONT></I>");
556 wprintf("</TT><BR>\n");
562 /* MIME! Rock on!! */
563 if (format_type == 4) {
564 output_chosen_part(msgnum, multipart_chosen);
567 /* Afterwards, offer links to download attachments 'n' such */
568 if (mime_http != NULL) {
569 wprintf("%s", mime_http);
573 if (strlen(vcard_partnum) > 0) {
574 vcard_source = load_mimepart(msgnum, vcard_partnum);
575 if (vcard_source != NULL) {
577 /* If it's my vCard I can edit it */
578 if ( (!strcasecmp(WC->wc_roomname, USERCONFIGROOM))
579 || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM))) {
580 wprintf("<A HREF=\"/edit_vcard?"
581 "msgnum=%ld&partnum=%s\">",
582 msgnum, vcard_partnum);
583 wprintf("(edit)</A>");
586 /* In all cases, display the full card */
587 display_vcard(vcard_source, 0, 1);
595 void summarize_message(long msgnum) {
606 memset(&summ, 0, sizeof(summ));
607 strcpy(summ.subj, "(no subject)");
609 sprintf(buf, "MSG0 %ld|1", msgnum); /* ask for headers only */
612 if (buf[0] != '1') return;
614 while (serv_gets(buf), strcmp(buf, "000")) {
615 if (!strncasecmp(buf, "from=", 5)) {
616 strcpy(summ.from, &buf[5]);
618 if (!strncasecmp(buf, "subj=", 5)) {
619 strcpy(summ.subj, &buf[5]);
621 if (!strncasecmp(buf, "rfca=", 5)) {
622 strcat(summ.from, " <");
623 strcat(summ.from, &buf[5]);
624 strcat(summ.from, ">");
627 if (!strncasecmp(buf, "node=", 5)) {
628 if ( ((WC->room_flags & QR_NETWORK)
629 || ((strcasecmp(&buf[5], serv_info.serv_nodename)
630 && (strcasecmp(&buf[5], serv_info.serv_fqdn)))))
632 strcat(summ.from, " @ ");
633 strcat(summ.from, &buf[5]);
637 if (!strncasecmp(buf, "rcpt=", 5)) {
638 strcpy(summ.to, &buf[5]);
641 if (!strncasecmp(buf, "time=", 5)) {
642 fmt_date(summ.date, atol(&buf[5]));
646 wprintf("<TD><A HREF=\"/readfwd?startmsg=%ld"
647 "&maxmsgs=1&summary=0\">",
650 wprintf("</A></TD><TD>");
652 wprintf(" </TD><TD>");
656 "<INPUT TYPE=\"checkbox\" NAME=\"msg_%ld\" VALUE=\"yes\">"
664 void display_addressbook(long msgnum, char alpha) {
666 char mime_partnum[SIZ];
667 char mime_filename[SIZ];
668 char mime_content_type[SIZ];
669 char mime_disposition[SIZ];
671 char vcard_partnum[SIZ];
672 char *vcard_source = NULL;
682 memset(&summ, 0, sizeof(summ));
683 strcpy(summ.subj, "(no subject)");
685 sprintf(buf, "MSG0 %ld|1", msgnum); /* ask for headers only */
688 if (buf[0] != '1') return;
690 while (serv_gets(buf), strcmp(buf, "000")) {
691 if (!strncasecmp(buf, "part=", 5)) {
692 extract(mime_filename, &buf[5], 1);
693 extract(mime_partnum, &buf[5], 2);
694 extract(mime_disposition, &buf[5], 3);
695 extract(mime_content_type, &buf[5], 4);
696 mime_length = extract_int(&buf[5], 5);
698 if (!strcasecmp(mime_content_type, "text/x-vcard")) {
699 strcpy(vcard_partnum, mime_partnum);
705 if (strlen(vcard_partnum) > 0) {
706 vcard_source = load_mimepart(msgnum, vcard_partnum);
707 if (vcard_source != NULL) {
709 /* Display the summary line */
710 display_vcard(vcard_source, alpha, 0);
712 /* If it's my vCard I can edit it */
713 if ( (!strcasecmp(WC->wc_roomname, USERCONFIGROOM))
714 || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM))) {
715 wprintf("<A HREF=\"/edit_vcard?"
716 "msgnum=%ld&partnum=%s\">",
717 msgnum, vcard_partnum);
718 wprintf("(edit)</A>");
730 * load message pointers from the server
732 int load_msg_ptrs(servcmd)
742 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
745 while (serv_gets(buf), strcmp(buf, "000")) {
746 WC->msgarr[nummsgs] = atol(buf);
754 * command loop for reading messages
756 void readloop(char *oper)
764 int num_displayed = 0;
766 int is_addressbook = 0;
767 int remaining_messages;
769 int lowest_displayed = (-1);
770 int highest_displayed = 0;
771 long pn_previous = 0L;
772 long pn_current = 0L;
777 startmsg = atol(bstr("startmsg"));
778 maxmsgs = atoi(bstr("maxmsgs"));
779 is_summary = atoi(bstr("summary"));
780 if (maxmsgs == 0) maxmsgs = 20;
784 if (!strcmp(oper, "readnew")) {
785 strcpy(cmd, "MSGS NEW");
786 } else if (!strcmp(oper, "readold")) {
787 strcpy(cmd, "MSGS OLD");
789 strcpy(cmd, "MSGS ALL");
792 /* FIXME put in the correct constant #defs */
793 if ((WC->wc_view == 1) && (maxmsgs > 1)) {
795 strcpy(cmd, "MSGS ALL");
798 if ((WC->wc_view == 2) && (maxmsgs > 1)) {
800 strcpy(cmd, "MSGS ALL");
802 if (bstr("alpha") == NULL) {
806 strcpy(buf, bstr("alpha"));
810 for (i='A'; i<='Z'; ++i) {
811 if (i == alpha) wprintf("<FONT SIZE=+2>"
814 wprintf("<A HREF=\"/readfwd?alpha=%c\">"
819 if (!isalpha(alpha)) wprintf("<FONT SIZE=+2>(other)</FONT>\n");
820 else wprintf("<A HREF=\"/readfwd?alpha=1\">(other)</A>\n");
821 wprintf("<HR width=100%%>\n");
824 nummsgs = load_msg_ptrs(cmd);
826 if (!strcmp(oper, "readnew")) {
827 wprintf("<EM>No new messages in this room.</EM>\n");
828 } else if (!strcmp(oper, "readold")) {
829 wprintf("<EM>No old messages in this room.</EM>\n");
831 wprintf("<EM>This room is empty.</EM>\n");
836 if (startmsg == 0L) startmsg = WC->msgarr[0];
837 remaining_messages = 0;
839 for (a = 0; a < nummsgs; ++a) {
840 if (WC->msgarr[a] >= startmsg) {
841 ++remaining_messages;
846 wprintf("<FORM METHOD=\"POST\" ACTION=\"/do_stuff_to_msgs\">\n"
847 "<TABLE border=0 cellspacing=0 "
848 "cellpadding=0 width=100%%>\n"
850 "<TD><I>Subject</I></TD>"
851 "<TD><I>Sender</I></TD>"
852 "<TD><I>Date</I></TD>"
858 if (is_addressbook) {
859 wprintf("<TABLE border=0 cellspacing=0 "
860 "cellpadding=0 width=100%%>\n"
864 for (a = 0; a < nummsgs; ++a) {
865 if ((WC->msgarr[a] >= startmsg) && (num_displayed < maxmsgs)) {
867 /* Learn which msgs "Prev" & "Next" buttons go to */
868 pn_current = WC->msgarr[a];
869 if (a > 0) pn_previous = WC->msgarr[a-1];
870 if (a < (nummsgs-1)) pn_next = WC->msgarr[a+1];
872 /* If a tabular view, set up the line */
873 if ( (is_summary) || (is_addressbook) ) {
875 wprintf("<TR BGCOLOR=%s>",
876 (bg ? "DDDDDD" : "FFFFFF")
880 /* Display the message */
882 summarize_message(WC->msgarr[a]);
884 else if (is_addressbook) {
885 display_addressbook(WC->msgarr[a], alpha);
888 read_message(WC->msgarr[a]);
891 /* If a tabular view, finish the line */
892 if ( (is_summary) || (is_addressbook) ) {
896 if (lowest_displayed < 0) lowest_displayed = a;
897 highest_displayed = a;
900 --remaining_messages;
905 wprintf("</TABLE>\n");
908 if (is_addressbook) {
909 wprintf("</TABLE>\n");
912 /* Bump these because although we're thinking in zero base, the user
913 * is a drooling idiot and is thinking in one base.
918 /* If we're only looking at one message, do a prev/next thing */
919 if (num_displayed == 1) {
922 "<TABLE BORDER=0 WIDTH=100%% BGCOLOR=DDDDDD><TR><TD>"
923 "Reading #%d of %d messages.</TD>\n"
924 "<TD ALIGN=RIGHT><FONT SIZE=+1>",
925 lowest_displayed, nummsgs);
928 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" "
929 "VALUE=\"Delete selected\">\n");
932 if (pn_previous > 0L) {
933 wprintf("<A HREF=\"/%s"
943 wprintf("<A HREF=\"/%s"
952 wprintf("<A HREF=\"/%s?startmsg=%ld"
953 "&maxmsgs=999999&summary=1\">"
959 wprintf("</TD></TR></TABLE></CENTER>\n");
964 * If we're not currently looking at ALL requested
965 * messages, then display the selector bar
967 if (num_displayed > 1) {
969 "<TABLE BORDER=0 WIDTH=100%% BGCOLOR=DDDDDD><TR><TD>"
970 "Reading #%d-%d of %d messages.</TD>\n"
971 "<TD ALIGN=RIGHT><FONT SIZE=+1>",
972 lowest_displayed, highest_displayed, nummsgs);
975 wprintf("<INPUT TYPE=\"submit\" NAME=\"sc\" "
976 "VALUE=\"Delete selected\">\n");
980 for (b=0; b<nummsgs; b = b + maxmsgs) {
983 if (hi > nummsgs) hi = nummsgs;
984 if (WC->msgarr[b] != startmsg) {
985 wprintf("<A HREF=\"/%s"
997 wprintf("%d-%d \n", lo, hi);
1001 wprintf("<A HREF=\"/%s?startmsg=%ld"
1002 "&maxmsgs=999999&summary=%d\">"
1006 WC->msgarr[0], is_summary);
1008 wprintf("<A HREF=\"/%s?startmsg=%ld"
1009 "&maxmsgs=999999&summary=1\">"
1015 wprintf("</TD></TR></TABLE></CENTER>\n");
1017 if (is_summary) wprintf("</FORM>\n");
1019 DONE: wDumpContent(1);
1026 * Post message (or don't post message)
1028 * Note regarding the "dont_post" variable:
1029 * A random value (actually, it's just a timestamp) is inserted as a hidden
1030 * field called "postseq" when the display_enter page is generated. This
1031 * value is checked when posting, using the static variable dont_post. If a
1032 * user attempts to post twice using the same dont_post value, the message is
1033 * discarded. This prevents the accidental double-saving of the same message
1034 * if the user happens to click the browser "back" button.
1036 void post_message(void)
1039 static long dont_post = (-1L);
1043 wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\">");
1044 strcpy(buf, bstr("sc"));
1045 if (strcasecmp(buf, "Save message")) {
1046 wprintf("Cancelled. Message was not posted.<BR>\n");
1047 } else if (atol(bstr("postseq")) == dont_post) {
1048 wprintf("Automatically cancelled because you have already "
1049 "saved this message.<BR>\n");
1051 sprintf(buf, "ENT0 1|%s|0|4|%s",
1056 if (buf[0] == '4') {
1057 serv_puts("Content-type: text/html");
1059 text_to_server(bstr("msgtext"), 1);
1061 wprintf("Message has been posted.<BR>\n");
1062 dont_post = atol(bstr("postseq"));
1064 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
1075 * display the message entry screen
1077 void display_enter(void)
1085 wprintf("<FONT FACE=\"Arial,Helvetica,sans-serif\">");
1087 sprintf(buf, "ENT0 0|%s|0|0", bstr("recp"));
1091 if (!strncmp(buf, "570", 3)) {
1092 if (strlen(bstr("recp")) > 0) {
1093 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
1095 do_template("prompt_for_recipient");
1098 if (buf[0] != '2') {
1099 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
1104 tm = (struct tm *) localtime(&now);
1105 strcpy(buf, (char *) asctime(tm));
1106 buf[strlen(buf) - 1] = 0;
1107 strcpy(&buf[16], &buf[19]);
1108 wprintf("</CENTER><FONT COLOR=\"440000\">\n"
1109 "<IMG SRC=\"static/enter.gif\" ALIGN=MIDDLE ALT=\" \" "
1110 "onLoad=\"document.enterform.msgtext.focus();\" >");
1111 wprintf("<B> %s ", &buf[4]);
1112 wprintf("from %s ", WC->wc_username);
1113 if (strlen(bstr("recp")) > 0)
1114 wprintf("to %s ", bstr("recp"));
1115 wprintf("in %s> ", WC->wc_roomname);
1116 wprintf("</B></FONT><BR><CENTER>\n");
1118 wprintf("<FORM METHOD=\"POST\" ACTION=\"/post\" "
1119 "NAME=\"enterform\">\n");
1120 wprintf("<INPUT TYPE=\"hidden\" NAME=\"recp\" VALUE=\"%s\">\n",
1122 wprintf("<INPUT TYPE=\"hidden\" NAME=\"postseq\" VALUE=\"%ld\">\n",
1124 wprintf("<FONT SIZE=-1>Subject (optional):</FONT>"
1125 "<INPUT TYPE=\"text\" NAME=\"subject\" MAXLENGTH=70>"
1126 " "
1127 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Save message\">"
1128 "<INPUT TYPE=\"submit\" NAME=\"sc\" VALUE=\"Cancel\"><BR>\n");
1130 wprintf("<TEXTAREA NAME=\"msgtext\" wrap=soft ROWS=30 COLS=80 "
1131 "WIDTH=80></TEXTAREA><P>\n");
1133 wprintf("</FORM></CENTER>\n");
1134 DONE: wDumpContent(1);
1145 void delete_msg(void)
1150 msgid = atol(bstr("msgid"));
1154 sprintf(buf, "DELE %ld", msgid);
1157 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
1166 * Confirm move of a message
1168 void confirm_move_msg(void)
1174 msgid = atol(bstr("msgid"));
1178 wprintf("<TABLE WIDTH=100%% BORDER=0 BGCOLOR=770000><TR><TD>");
1179 wprintf("<FONT SIZE=+1 COLOR=\"FFFFFF\"");
1180 wprintf("<B>Confirm move of message</B>\n");
1181 wprintf("</FONT></TD></TR></TABLE>\n");
1183 wprintf("<CENTER>");
1185 wprintf("Please select the room to which you would like this message moved:<BR>\n");
1187 wprintf("<FORM METHOD=\"POST\" ACTION=\"/move_msg\">\n");
1188 wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgid\" VALUE=\"%s\">\n",
1192 wprintf("<SELECT NAME=\"target_room\" SIZE=5>\n");
1195 if (buf[0] == '1') {
1196 while (serv_gets(buf), strcmp(buf, "000")) {
1197 extract(targ, buf, 0);
1198 wprintf("<OPTION>");
1203 wprintf("</SELECT>\n");
1206 wprintf("<INPUT TYPE=\"submit\" NAME=\"yesno\" VALUE=\"Move\">");
1207 wprintf("<INPUT TYPE=\"submit\" NAME=\"yesno\" VALUE=\"Cancel\">");
1208 wprintf("</FORM></CENTER>\n");
1210 wprintf("</CENTER>\n");
1221 msgid = atol(bstr("msgid"));
1225 if (!strcasecmp(bstr("yesno"), "Move")) {
1226 sprintf(buf, "MOVE %ld|%s", msgid, bstr("target_room"));
1229 wprintf("<EM>%s</EM><BR>\n", &buf[4]);
1231 wprintf("<EM>Message not moved.</EM><BR>\n");
1239 void do_stuff_to_msgs(void) {
1244 struct stuff_t *next;
1248 struct stuff_t *stuff = NULL;
1249 struct stuff_t *ptr;
1252 serv_puts("MSGS ALL");
1255 if (buf[0] == '1') while (serv_gets(buf), strcmp(buf, "000")) {
1256 ptr = malloc(sizeof(struct stuff_t));
1257 ptr->msgnum = atol(buf);
1262 strcpy(sc, bstr("sc"));
1264 while (stuff != NULL) {
1266 sprintf(buf, "msg_%ld", stuff->msgnum);
1267 if (!strcasecmp(bstr(buf), "yes")) {
1269 if (!strcasecmp(sc, "Delete selected")) {
1270 serv_printf("DELE %ld", stuff->msgnum);
1281 readloop("readfwd");