* Removed all of the absolute URL's.
[citadel.git] / webcit / messages.c
index a02296df53adc56ece5f0d9fedec100624bd71e8..190f6061e4d4772689aa7173dfd996c6191bc2a1 100644 (file)
@@ -162,7 +162,7 @@ char buf[];
        urlbuf[end - start] = 0;
 
        strncpy(outbuf, buf, start);
-       sprintf(&outbuf[start], "%cA HREF=%c%s%c TARGET=%c%s%c%c%s%c/A%c",
+       sprintf(&outbuf[start], "%ca href=%c%s%c TARGET=%c%s%c%c%s%c/A%c",
                LB, QU, urlbuf, QU, QU, TARGET, QU, RB, urlbuf, LB, RB);
        strcat(outbuf, &buf[end]);
        if ( strlen(outbuf) < 250 )
@@ -342,7 +342,7 @@ void display_parsed_vcard(struct vCard *v, int full) {
                        else if (!strcasecmp(firsttoken, "email")) {
                                if (strlen(mailto) > 0) strcat(mailto, "<br />");
                                strcat(mailto,
-                                       "<A HREF=\"/display_enter"
+                                       "<a href=\"display_enter"
                                        "?force_room=_MAIL_?recp=");
 
                                urlesc(&mailto[strlen(mailto)], displayname);
@@ -419,7 +419,7 @@ void display_parsed_vcard(struct vCard *v, int full) {
                if (pass == 1) {
                        wprintf("<TR BGCOLOR=\"#AAAAAA\">"
                        "<TD COLSPAN=2 BGCOLOR=\"#FFFFFF\">"
-                       "<IMG ALIGN=CENTER SRC=\"/static/viewcontacts_48x.gif\">"
+                       "<IMG ALIGN=CENTER src=\"static/viewcontacts_48x.gif\">"
                        "<FONT SIZE=+1><B>");
                        escputs(displayname);
                        wprintf("</B></FONT>");
@@ -580,7 +580,7 @@ void read_message(long msgnum, int printable_view, char *section) {
                if (!strncasecmp(buf, "from=", 5)) {
                        strcpy(from, &buf[5]);
                        wprintf(_("from "));
-                       wprintf("<A HREF=\"/showuser?who=");
+                       wprintf("<a href=\"showuser?who=");
 #ifdef HAVE_ICONV
                        utf8ify_rfc822_string(from);
 #endif
@@ -659,16 +659,16 @@ void read_message(long msgnum, int printable_view, char *section) {
                           && (!strncasecmp(mime_content_type, "image/", 6)) ){
                                snprintf(&mime_http[strlen(mime_http)],
                                        (sizeof(mime_http) - strlen(mime_http) - 1),
-                                       "<IMG SRC=\"/mimepart/%ld/%s/%s\">",
+                                       "<img src=\"mimepart/%ld/%s/%s\">",
                                        msgnum, mime_partnum, mime_filename);
                        }
                        else if ( (!strcasecmp(mime_disposition, "attachment")) 
                             || (!strcasecmp(mime_disposition, "inline")) ) {
                                snprintf(&mime_http[strlen(mime_http)],
                                        (sizeof(mime_http) - strlen(mime_http) - 1),
-                                       "<A HREF=\"/mimepart/%ld/%s/%s\" "
+                                       "<a href=\"mimepart/%ld/%s/%s\" "
                                        "TARGET=\"wc.%ld.%s\">"
-                                       "<IMG SRC=\"/static/diskette_24x.gif\" "
+                                       "<img src=\"static/diskette_24x.gif\" "
                                        "BORDER=0 ALIGN=MIDDLE>\n"
                                        "%s (%s, %d bytes)</A><br />\n",
                                        msgnum, mime_partnum, mime_filename,
@@ -742,7 +742,7 @@ void read_message(long msgnum, int printable_view, char *section) {
 
                /* Reply */
                if ( (WC->wc_view == VIEW_MAILBOX) || (WC->wc_view == VIEW_BBS) ) {
-                       wprintf("<a href=\"/display_enter");
+                       wprintf("<a href=\"display_enter");
                        if (WC->is_mailbox) {
                                wprintf("?replyquote=%ld", msgnum);
                        }
@@ -757,7 +757,7 @@ void read_message(long msgnum, int printable_view, char *section) {
                /* ReplyQuoted */
                if ( (WC->wc_view == VIEW_MAILBOX) || (WC->wc_view == VIEW_BBS) ) {
                        if (!WC->is_mailbox) {
-                               wprintf("<a href=\"/display_enter");
+                               wprintf("<a href=\"display_enter");
                                wprintf("?replyquote=%ld", msgnum);
                                wprintf("?recp=");
                                urlescputs(reply_to);
@@ -770,7 +770,7 @@ void read_message(long msgnum, int printable_view, char *section) {
 
                /* ReplyAll */
                if (WC->wc_view == VIEW_MAILBOX) {
-                       wprintf("<a href=\"/display_enter");
+                       wprintf("<a href=\"display_enter");
                        wprintf("?replyquote=%ld", msgnum);
                        wprintf("?recp=");
                        urlescputs(reply_to);
@@ -786,7 +786,7 @@ void read_message(long msgnum, int printable_view, char *section) {
 
                /* Forward */
                if (WC->wc_view == VIEW_MAILBOX) {
-                       wprintf("<a href=\"/display_enter?fwdquote=%ld?subject=", msgnum);
+                       wprintf("<a href=\"display_enter?fwdquote=%ld?subject=", msgnum);
                        if (strncasecmp(m_subject, "Fwd:", 4)) wprintf("Fwd:%20");
                        urlescputs(m_subject);
                        wprintf("\">[%s]</a> ", _("Forward"));
@@ -795,17 +795,17 @@ void read_message(long msgnum, int printable_view, char *section) {
                /* If this is one of my own rooms, or if I'm an Aide or Room Aide, I can move/delete */
                if ( (WC->is_room_aide) || (WC->is_mailbox) ) {
                        /* Move */
-                       wprintf("<a href=\"/confirm_move_msg?msgid=%ld\">[%s]</a> ",
+                       wprintf("<a href=\"confirm_move_msg?msgid=%ld\">[%s]</a> ",
                                msgnum, _("Move"));
        
                        /* Delete */
-                       wprintf("<a href=\"/delete_msg?msgid=%ld\" "
+                       wprintf("<a href=\"delete_msg?msgid=%ld\" "
                                "onClick=\"return confirm('%s');\">"
                                "[%s]</a> ", msgnum, _("Delete this message?"), _("Delete")
                        );
                }
 
-               wprintf("<a href=\"#\" onClick=\"window.open('/printmsg?msgnum=%ld', 'print%ld', 'toolbar=no,location=no,directories=no,copyhistory=no,status=yes,scrollbars=yes,resizable=yes,width=600,height=400'); \" >"
+               wprintf("<a href=\"#\" onClick=\"window.open('/printmsg/%ld', 'print%ld', 'toolbar=no,location=no,directories=no,copyhistory=no,status=yes,scrollbars=yes,resizable=yes,width=600,height=400'); \" >"
                        "[%s]</a>", msgnum, msgnum, _("Print"));
 
                wprintf("</td>");
@@ -944,7 +944,7 @@ void read_message(long msgnum, int printable_view, char *section) {
                                || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM))
                                || (WC->wc_view == VIEW_ADDRESSBOOK)
                        ) {
-                               wprintf("<A HREF=\"/edit_vcard?"
+                               wprintf("<a href=\"edit_vcard?"
                                        "msgnum=%ld?partnum=%s\">",
                                        msgnum, vcard_partnum);
                                wprintf("[%s]</A>", _("edit"));
@@ -991,10 +991,10 @@ ENDBODY:
  * Unadorned HTML output of an individual message, suitable
  * for placing in a hidden iframe, for printing, or whatever
  */
-void embed_message(void) {
+void embed_message(char *msgnum_as_string) {
        long msgnum = 0L;
 
-       msgnum = atol(bstr("msgnum"));
+       msgnum = atol(msgnum_as_string);
        begin_ajax_response();
        read_message(msgnum, 0, "");
        end_ajax_response();
@@ -1004,10 +1004,10 @@ void embed_message(void) {
 /*
  * Printable view of a message
  */
-void print_message(void) {
+void print_message(char *msgnum_as_string) {
        long msgnum = 0L;
 
-       msgnum = atol(bstr("msgnum"));
+       msgnum = atol(msgnum_as_string);
        output_headers(0, 0, 0, 0, 0, 0);
 
        wprintf("Content-type: text/html\r\n"
@@ -1331,39 +1331,33 @@ ENDBODY:
 }
 
 
-
-
-
-
 void display_summarized(int num) {
        char datebuf[64];
 
-       wprintf("<tr bgcolor=\"#%s\" ",
-               ((num % 2) ? "DDDDDD" : "FFFFFF")
+       wprintf("<tr id=\"m%ld\" style=\"width:100%%;font-weight:%s;background-color:#fff\" "
+               "onClick=\"CtdlSingleClickMsg(%ld)\">",
+               WC->summ[num].msgnum,
+               (WC->summ[num].is_new ? "bold" : "normal"),
+               WC->summ[num].msgnum
        );
 
-       wprintf("onClick=\" new Ajax.Updater('preview_pane', '/msg', { method: 'get', parameters: 'msgnum=%ld' } ); \" ", WC->summ[num].msgnum);
-       wprintf(">");
-
-       wprintf("<TD>");
-       if (WC->summ[num].is_new) wprintf("<B>");
+       wprintf("<td>");
        escputs(WC->summ[num].subj);
-       if (WC->summ[num].is_new) wprintf("</B>");
-       wprintf("</TD><TD>");
-       if (WC->summ[num].is_new) wprintf("<B>");
+       wprintf("</td>");
+
+       wprintf("<td>");
        escputs(WC->summ[num].from);
-       if (WC->summ[num].is_new) wprintf("</B>");
-       wprintf(" </TD><TD>");
-       if (WC->summ[num].is_new) wprintf("<B>");
+       wprintf("</td>");
+
+       wprintf("<td>");
        fmt_date(datebuf, WC->summ[num].date, 1);       /* brief */
        escputs(datebuf);
-       if (WC->summ[num].is_new) wprintf("</B>");
-       wprintf(" </TD>");
-       wprintf("<TD>"
-               "<INPUT TYPE=\"checkbox\" NAME=\"msg_%ld\" VALUE=\"yes\">"
-               "</TD>",
+       wprintf("</td>");
+
+       wprintf("<td><input type=\"checkbox\" name=\"msg_%ld\" value=\"yes\">",
                WC->summ[num].msgnum
        );
+       wprintf("</td>");
 
        wprintf("</tr>\n");
 }
@@ -1418,7 +1412,7 @@ void display_addressbook(long msgnum, char alpha) {
                                || (!strcasecmp(&WC->wc_roomname[11], USERCONFIGROOM))
                                || (WC->wc_view == VIEW_ADDRESSBOOK)
                        ) {
-                               wprintf("<A HREF=\"/edit_vcard?"
+                               wprintf("<a href=\"edit_vcard?"
                                        "msgnum=%ld?partnum=%s\">",
                                        msgnum, vcard_partnum);
                                wprintf("[%s]</A>", _("edit"));
@@ -1569,7 +1563,7 @@ void do_addrbook_view(struct addrbookent *addrbook, int num_ab) {
        wprintf("Page: ");
        for (i=0; i<=num_pages; ++i) {
                if (i != page) {
-                       wprintf("<A HREF=\"/readfwd?page=%d\">", i);
+                       wprintf("<a href=\"readfwd?page=%d\">", i);
                }
                else {
                        wprintf("<B>");
@@ -1611,7 +1605,7 @@ void do_addrbook_view(struct addrbookent *addrbook, int num_ab) {
        
                        wprintf("<TD>");
        
-                       wprintf("<A HREF=\"/readfwd?startmsg=%ld&is_singlecard=1",
+                       wprintf("<a href=\"readfwd?startmsg=%ld&is_singlecard=1",
                                addrbook[i].ab_msgnum);
                        wprintf("?maxmsgs=1?summary=0?alpha=%s\">", bstr("alpha"));
                        vcard_n_prettyize(addrbook[i].ab_name);
@@ -1720,6 +1714,18 @@ int load_msg_ptrs(char *servcmd, int with_headers)
        return (nummsgs);
 }
 
+int longcmp_r(const void *s1, const void *s2) {
+       long l1;
+       long l2;
+
+       l1 = *(long *)s1;
+       l2 = *(long *)s2;
+
+       if (l1 > l2) return(-1);
+       if (l1 < l2) return(+1);
+       return(0);
+}
+
  
 int summcmp_subj(const void *s1, const void *s2) {
        struct message_summary *summ1;
@@ -1793,6 +1799,7 @@ void readloop(char *oper)
        int nummsgs;
        long startmsg;
        int maxmsgs;
+       long *displayed_msgs = NULL;
        int num_displayed = 0;
        int is_summary = 0;
        int is_addressbook = 0;
@@ -1800,13 +1807,9 @@ void readloop(char *oper)
        int is_calendar = 0;
        int is_tasks = 0;
        int is_notes = 0;
-       int remaining_messages;
        int lo, hi;
        int lowest_displayed = (-1);
        int highest_displayed = 0;
-       long pn_previous = 0L;
-       long pn_current = 0L;
-       long pn_next = 0L;
        struct addrbookent *addrbook = NULL;
        int num_ab = 0;
        char *sortby = NULL;
@@ -1815,6 +1818,7 @@ void readloop(char *oper)
        char *subjsort_button;
        char *sendsort_button;
        char *datesort_button;
+       int bbs_reverse = 0;    /* FIXME we need to set/reset this option now.  It works. */
 
        startmsg = atol(bstr("startmsg"));
        maxmsgs = atoi(bstr("maxmsgs"));
@@ -1829,8 +1833,18 @@ void readloop(char *oper)
                set_preference(sortpref_name, sortby, 1);
        }
        if (strlen(sortby) == 0) sortby = sortpref_value;
+
+       /* mailbox sort */
        if (strlen(sortby) == 0) sortby = "rdate";
 
+       /* message board sort */
+       if (!strcasecmp(sortby, "reverse")) {
+               bbs_reverse = 1;
+       }
+       else {
+               bbs_reverse = 0;
+       }
+
        output_headers(1, 1, 1, 0, 0, 0);
 
        /* When in summary mode, always show ALL messages instead of just
@@ -1926,12 +1940,12 @@ void readloop(char *oper)
                }
        }
 
-       if (startmsg == 0L) startmsg = WC->msgarr[0];
-       remaining_messages = 0;
-
-       for (a = 0; a < nummsgs; ++a) {
-               if (WC->msgarr[a] >= startmsg) {
-                       ++remaining_messages;
+       if (startmsg == 0L) {
+               if (bbs_reverse) {
+                       startmsg = WC->msgarr[(nummsgs >= maxmsgs) ? (nummsgs - maxmsgs) : 0];
+               }
+               else {
+                       startmsg = WC->msgarr[0];
                }
        }
 
@@ -1963,33 +1977,33 @@ void readloop(char *oper)
        }
 
        if (!strcasecmp(sortby, "subject")) {
-               subjsort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rsubject\"><img border=\"0\" src=\"/static/down_pointer.gif\" /></a>" ;
+               subjsort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rsubject\"><img border=\"0\" src=\"static/down_pointer.gif\" /></a>" ;
        }
        else if (!strcasecmp(sortby, "rsubject")) {
-               subjsort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=subject\"><img border=\"0\" src=\"/static/up_pointer.gif\" /></a>" ;
+               subjsort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=subject\"><img border=\"0\" src=\"static/up_pointer.gif\" /></a>" ;
        }
        else {
-               subjsort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=subject\"><img border=\"0\" src=\"/static/sort_none.gif\" /></a>" ;
+               subjsort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=subject\"><img border=\"0\" src=\"static/sort_none.gif\" /></a>" ;
        }
 
        if (!strcasecmp(sortby, "sender")) {
-               sendsort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rsender\"><img border=\"0\" src=\"/static/down_pointer.gif\" /></a>" ;
+               sendsort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rsender\"><img border=\"0\" src=\"static/down_pointer.gif\" /></a>" ;
        }
        else if (!strcasecmp(sortby, "rsender")) {
-               sendsort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=sender\"><img border=\"0\" src=\"/static/up_pointer.gif\" /></a>" ;
+               sendsort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=sender\"><img border=\"0\" src=\"static/up_pointer.gif\" /></a>" ;
        }
        else {
-               sendsort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=sender\"><img border=\"0\" src=\"/static/sort_none.gif\" /></a>" ;
+               sendsort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=sender\"><img border=\"0\" src=\"static/sort_none.gif\" /></a>" ;
        }
 
        if (!strcasecmp(sortby, "date")) {
-               datesort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rdate\"><img border=\"0\" src=\"/static/down_pointer.gif\" /></a>" ;
+               datesort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rdate\"><img border=\"0\" src=\"static/down_pointer.gif\" /></a>" ;
        }
        else if (!strcasecmp(sortby, "rdate")) {
-               datesort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=date\"><img border=\"0\" src=\"/static/up_pointer.gif\" /></a>" ;
+               datesort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=date\"><img border=\"0\" src=\"static/up_pointer.gif\" /></a>" ;
        }
        else {
-               datesort_button = "<a href=\"/readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rdate\"><img border=\"0\" src=\"/static/sort_none.gif\" /></a>" ;
+               datesort_button = "<a href=\"readfwd?startmsg=1?maxmsgs=9999999?summary=1?sortby=rdate\"><img border=\"0\" src=\"static/sort_none.gif\" /></a>" ;
        }
 
        if (is_summary) {
@@ -2000,20 +2014,15 @@ void readloop(char *oper)
                        "<div id=\"fix_scrollbar_bug\">\n"
 
                        "<form name=\"msgomatic\" "
-                       "method=\"POST\" action=\"/do_stuff_to_msgs\">\n"
+                       "method=\"POST\" action=\"do_stuff_to_msgs\">\n"
 
                        "<span class=\"mailbox_summary\">"
-                       "<table border=0 cellspacing=0 "
-                       "cellpadding=0 width=100%%>\n"
-                       "<TR>"
-                       "<TD align=center><b><i>%s</i></b> %s</TD>"
-                       "<TD align=center><b><i>%s</i></b> %s</TD>"
-                       "<TD align=center><b><i>%s</i></b> %s</TD>"
-                       "<TD><INPUT TYPE=\"submit\" NAME=\"delete_button\" "
-                       "STYLE=\"font-family: Bitstream Vera Sans,Arial,Helvetica,sans-serif;"
-                       " font-size: 6pt;\" "
-                       "VALUE=\"%s\"></TD>"
-                       "</TR>\n"
+                       "<table id=\"summary_headers\" rules=rows cellspacing=0 style=\"width:100%%\"><tr>"
+                       "<td><b><i>%s</i></b> %s</td>"
+                       "<td><b><i>%s</i></b> %s</td>"
+                       "<td><b><i>%s</i></b> %s</td>"
+                       "<td><input type=\"submit\" name=\"delete_button\" style=\"font-size:6pt\" value=\"%s\"></td>"
+                       "</tr>\n"
                        ,
                        _("Subject"),   subjsort_button,
                        _("Sender"),    sendsort_button,
@@ -2025,11 +2034,6 @@ void readloop(char *oper)
        for (a = 0; a < nummsgs; ++a) {
                if ((WC->msgarr[a] >= startmsg) && (num_displayed < maxmsgs)) {
 
-                       /* Learn which msgs "Prev" & "Next" buttons go to */
-                       pn_current = WC->msgarr[a];
-                       if (a > 0) pn_previous = WC->msgarr[a-1];
-                       if (a < (nummsgs-1)) pn_next = WC->msgarr[a+1];
-
                        /* Display the message */
                        if (is_summary) {
                                display_summarized(a);
@@ -2053,28 +2057,43 @@ void readloop(char *oper)
                                display_note(WC->msgarr[a]);
                        }
                        else {
-                               read_message(WC->msgarr[a], 0, "");
+                               if (displayed_msgs == NULL) {
+                                       displayed_msgs = malloc(sizeof(long) *
+                                                               (maxmsgs<nummsgs ? maxmsgs : nummsgs));
+                               }
+                               displayed_msgs[num_displayed] = WC->msgarr[a];
                        }
 
                        if (lowest_displayed < 0) lowest_displayed = a;
                        highest_displayed = a;
 
                        ++num_displayed;
-                       --remaining_messages;
                }
        }
 
+       if (displayed_msgs != NULL) {
+               if (bbs_reverse) {
+                       qsort(displayed_msgs, num_displayed, sizeof(long), longcmp_r);
+               }
+
+               for (a=0; a<num_displayed; ++a) {
+                       read_message(displayed_msgs[a], 0, "");
+               }
+               free(displayed_msgs);
+               displayed_msgs = NULL;
+       }
+
        if (is_summary) {
                wprintf("</table></span></form>"
                        "</div>\n");                    /* end of 'fix_scrollbar_bug' div */
                wprintf("</div>");                      /* end of 'message_list' div */
 
-               wprintf("<div id=\"ml_slider\"></div>");        /* slider */
-
                wprintf("<div id=\"preview_pane\">");   /* The preview pane will initially be empty */
 
                /* Now register each message (whose element ID is "m9999",
                 * where "9999" is the message number) as draggable.
+                * (NOTE: uses script.aculo.us draggables, which will probably not be
+                * adequate for this purpose.)
                wprintf("<script type=\"text/javascript\">\n");
                for (a = 0; a < nummsgs; ++a) {
                        wprintf("new Draggable('m%ld',{revert:true});\n",
@@ -2090,51 +2109,6 @@ void readloop(char *oper)
        ++lowest_displayed;
        ++highest_displayed;
 
-       /* If we're only looking at one message, do a prev/next thing */
-       if (num_displayed == 1) {
-          if ((!is_tasks) && (!is_calendar) && (!is_addressbook) && (!is_notes) && (!is_singlecard)) {
-
-               wprintf("<div id=\"fix_scrollbar_bug\">"
-                       "<table border=0 width=100%% bgcolor=\"#dddddd\"><tr><td>");
-               wprintf(_("Reading #%d of %d messages."), lowest_displayed, nummsgs);
-               wprintf("</TD><TD ALIGN=RIGHT><FONT SIZE=+1>");
-
-               if (pn_previous > 0L) {
-                       wprintf("<A HREF=\"/%s"
-                               "?startmsg=%ld"
-                               "?maxmsgs=1"
-                               "?summary=0\">"
-                               "%s</A> \n",
-                                       oper,
-                                       pn_previous,
-                                       _("Previous"));
-               }
-
-               if (pn_next > 0L) {
-                       wprintf("<A HREF=\"/%s"
-                               "?startmsg=%ld"
-                               "?maxmsgs=1"
-                               "?summary=0\">"
-                               "%s</A> \n",
-                                       oper,
-                                       pn_next,
-                                       _("Next"));
-               }
-
-               wprintf("<A HREF=\"/%s?startmsg=%ld"
-                       "?maxmsgs=%d?summary=1\">"
-                       "%s"
-                       "</A>",
-                       oper,
-                       WC->msgarr[0],
-                       DEFAULT_MAXMSGS,
-                       _("Summary")
-               );
-
-               wprintf("</td></tr></table></div>\n");
-           }
-       }
-
        /*
         * If we're not currently looking at ALL requested
         * messages, then display the selector bar
@@ -2144,7 +2118,7 @@ void readloop(char *oper)
              && (!is_notes) && (!is_singlecard) && (!is_summary)) {
 
                wprintf("<form name=\"msgomatic\" "
-                       "method=\"POST\" action=\"/do_stuff_to_msgs\">\n");
+                       "method=\"POST\" action=\"do_stuff_to_msgs\">\n");
 
                wprintf(_("Reading #"), lowest_displayed, highest_displayed);
 
@@ -2152,23 +2126,45 @@ void readloop(char *oper)
                        "OnChange=\"location.href=msgomatic.whichones.options"
                        "[selectedIndex].value\">\n");
 
-               for (b=0; b<nummsgs; b = b + maxmsgs) {
-               lo = b+1;
-               hi = b+maxmsgs;
-               if (hi > nummsgs) hi = nummsgs;
-                       wprintf("<option %s value="
-                               "\"/%s"
-                               "?startmsg=%ld"
-                               "?maxmsgs=%d"
-                               "?summary=%d\">"
-                               "%d-%d</option> \n",
-                               ((WC->msgarr[b] == startmsg) ? "selected" : ""),
-                               oper,
-                               WC->msgarr[b],
-                               maxmsgs,
-                               is_summary,
-                               lo, hi);
+               if (bbs_reverse) {
+                       for (b=nummsgs-1; b>=0; b = b - maxmsgs) {
+                               hi = b + 1;
+                               lo = b - maxmsgs + 2;
+                               if (lo < 1) lo = 1;
+                               wprintf("<option %s value="
+                                       "\"/%s"
+                                       "?startmsg=%ld"
+                                       "?maxmsgs=%d"
+                                       "?summary=%d\">"
+                                       "%d-%d</option> \n",
+                                       ((WC->msgarr[lo-1] == startmsg) ? "selected" : ""),
+                                       oper,
+                                       WC->msgarr[lo-1],
+                                       maxmsgs,
+                                       is_summary,
+                                       hi, lo);
+                       }
+               }
+               else {
+                       for (b=0; b<nummsgs; b = b + maxmsgs) {
+                               lo = b + 1;
+                               hi = b + maxmsgs + 1;
+                               if (hi > nummsgs) hi = nummsgs;
+                               wprintf("<option %s value="
+                                       "\"/%s"
+                                       "?startmsg=%ld"
+                                       "?maxmsgs=%d"
+                                       "?summary=%d\">"
+                                       "%d-%d</option> \n",
+                                       ((WC->msgarr[b] == startmsg) ? "selected" : ""),
+                                       oper,
+                                       WC->msgarr[lo-1],
+                                       maxmsgs,
+                                       is_summary,
+                                       lo, hi);
+                       }
                }
+
                wprintf("<option value=\"/%s?startmsg=%ld"
                        "?maxmsgs=9999999?summary=%d\">"
                        "ALL"
@@ -2178,6 +2174,25 @@ void readloop(char *oper)
 
                wprintf("</select> ");
                wprintf(_("of %d messages."), nummsgs);
+
+               /* forward/reverse */
+               wprintf("&nbsp;<select name=\"direction\" size=\"1\" "
+                       "OnChange=\"location.href=msgomatic.direction.options"
+                       "[selectedIndex].value\">\n"
+               );
+
+               wprintf("<option %s value=\"/%s&sortby=forward\">oldest to newest</option>\n",
+                       (bbs_reverse ? "" : "selected"),
+                       oper
+               );
+       
+               wprintf("<option %s value=\"/%s&sortby=reverse\">newest to oldest</option>\n",
+                       (bbs_reverse ? "selected" : ""),
+                       oper
+               );
+       
+               wprintf("</select>");
+
                wprintf("</form>\n");
            }
        }
@@ -2210,15 +2225,6 @@ DONE:
                WC->num_summ = 0;
                free(WC->summ);
        }
-
-       /* If we got here via a mailbox view and are reading a single
-        * message, mark it as "seen." We do this after rendering the web page
-        * so it doesn't keep the user waiting.
-        */
-       if ( (maxmsgs == 1) && (WC->wc_view == VIEW_MAILBOX) ) {
-               serv_printf("SEEN %ld|1", startmsg);
-               serv_getln(buf, sizeof buf);
-       }
 }
 
 
@@ -2496,7 +2502,7 @@ void display_enter(void)
 
        /* begin message entry screen */
        wprintf("<form enctype=\"multipart/form-data\" "
-               "method=\"POST\" action=\"/post\" "
+               "method=\"POST\" action=\"post\" "
                "name=\"enterform\""
                ">\n");
        wprintf("<input type=\"hidden\" name=\"postseq\" value=\"%ld\">\n", now);
@@ -2639,7 +2645,7 @@ void display_enter(void)
        );
 
        /* Enumerate any attachments which are already in place... */
-       wprintf("<img src=\"/static/diskette_24x.gif\" border=0 "
+       wprintf("<img src=\"static/diskette_24x.gif\" border=0 "
                "align=middle height=16 width=16> Attachments: ");
        wprintf("<select name=\"which_attachment\" size=1>");
        for (att = WC->first_attachment; att != NULL; att = att->next) {
@@ -2731,7 +2737,7 @@ void confirm_move_msg(void)
        wprintf(_("Move this message to:"));
        wprintf("<br />\n");
 
-       wprintf("<form METHOD=\"POST\" ACTION=\"/move_msg\">\n");
+       wprintf("<form METHOD=\"POST\" action=\"move_msg\">\n");
        wprintf("<INPUT TYPE=\"hidden\" NAME=\"msgid\" VALUE=\"%s\">\n", bstr("msgid"));
 
        wprintf("<SELECT NAME=\"target_room\" SIZE=5>\n");