* mailbox summary sort by subject/sender/date
authorArt Cancro <ajc@citadel.org>
Mon, 25 Jul 2005 19:22:30 +0000 (19:22 +0000)
committerArt Cancro <ajc@citadel.org>
Mon, 25 Jul 2005 19:22:30 +0000 (19:22 +0000)
webcit/ChangeLog
webcit/messages.c
webcit/static/sort_none.gif [new file with mode: 0644]
webcit/webcit.h

index 49de13d6d776ad4d21d681a3079a4544130f7857..4e73f61fe6ad4cf17a45d956285aa0264403ac69 100644 (file)
@@ -1,4 +1,7 @@
 $Log$
+Revision 619.34  2005/07/25 19:22:30  ajc
+* mailbox summary sort by subject/sender/date
+
 Revision 619.33  2005/07/24 04:25:42  ajc
 * Replaced the old Citadel logo with a new one
   designed by Lisa Aurigemma (vermilion).
@@ -2744,4 +2747,3 @@ Sun Dec  6 19:50:55 EST 1998 Art Cancro <ajc@uncnsrd.mt-kisco.ny.us>
 
 1998-12-03 Nathan Bryant <bryant@cs.usm.maine.edu>
        * webserver.c: warning fix
-
index 370454c792a02a3eb3804417b9f1bec73d4da6a0..813f26d4ea2c67de95073d45316146ffdab522b4 100644 (file)
@@ -849,19 +849,41 @@ ENDBODY:
 }
 
 
-void summarize_message(long msgnum, int is_new) {
-       char buf[SIZ];
+void display_summarized(int num) {
+       char datebuf[64];
 
-       struct {
-               char date[SIZ];
-               char from[SIZ];
-               char to[SIZ];
-               char subj[SIZ];
-               int hasattachments;
-       } summ;
+       wprintf("<TD>");
+       if (WC->summ[num].is_new) wprintf("<B>");
+       wprintf("<A HREF=\"/readfwd?startmsg=%ld"
+               "&maxmsgs=1&summary=0\">", 
+               WC->msgarr[num]);
+       escputs(WC->summ[num].subj);
+       wprintf("</A>");
+       if (WC->summ[num].is_new) wprintf("</B>");
+       wprintf("</TD><TD>");
+       if (WC->summ[num].is_new) wprintf("<B>");
+       escputs(WC->summ[num].from);
+       if (WC->summ[num].is_new) wprintf("</B>");
+       wprintf(" </TD><TD>");
+       if (WC->summ[num].is_new) wprintf("<B>");
+       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>\n"
+       );
+}
 
-       memset(&summ, 0, sizeof(summ));
-       strcpy(summ.subj, "(no subject)");
+
+void summarize_message(int num, long msgnum, int is_new) {
+       char buf[SIZ];
+
+       memset(&WC->summ[num], 0, sizeof(struct message_summary));
+       safestrncpy(WC->summ[num].subj, "(no subject)", sizeof WC->summ[num].subj);
+       WC->summ[num].is_new = is_new;
+       WC->summ[num].msgnum = msgnum;
 
        /* ask for headers only with no MIME */
        sprintf(buf, "MSG0 %ld|3", msgnum);
@@ -871,75 +893,48 @@ void summarize_message(long msgnum, int is_new) {
 
        while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) {
                if (!strncasecmp(buf, "from=", 5)) {
-                       strcpy(summ.from, &buf[5]);
+                       safestrncpy(WC->summ[num].from, &buf[5], sizeof WC->summ[num].from);
                }
                if (!strncasecmp(buf, "subj=", 5)) {
                        if (strlen(&buf[5]) > 0) {
-                               strcpy(summ.subj, &buf[5]);
+                               safestrncpy(WC->summ[num].subj, &buf[5],
+                                       sizeof WC->summ[num].subj);
 #ifdef HAVE_ICONV
                                /* Handle subjects with RFC2047 encoding */
-                               utf8ify_rfc822_string(summ.subj);
+                               utf8ify_rfc822_string(WC->summ[num].subj);
 #endif
-                               if (strlen(summ.subj) > 75) {
-                                       strcpy(&summ.subj[72], "...");
+                               if (strlen(WC->summ[num].subj) > 75) {
+                                       strcpy(&WC->summ[num].subj[72], "...");
                                }
                        }
                }
-               /* if (!strncasecmp(buf, "rfca=", 5)) {
-                       strcat(summ.from, " <");
-                       strcat(summ.from, &buf[5]);
-                       strcat(summ.from, ">");
-               } */
 
                if (!strncasecmp(buf, "node=", 5)) {
                        if ( ((WC->room_flags & QR_NETWORK)
                        || ((strcasecmp(&buf[5], serv_info.serv_nodename)
                        && (strcasecmp(&buf[5], serv_info.serv_fqdn)))))
                        ) {
-                               strcat(summ.from, " @ ");
-                               strcat(summ.from, &buf[5]);
+                               strcat(WC->summ[num].from, " @ ");
+                               strcat(WC->summ[num].from, &buf[5]);
                        }
                }
 
                if (!strncasecmp(buf, "rcpt=", 5)) {
-                       strcpy(summ.to, &buf[5]);
+                       safestrncpy(WC->summ[num].to, &buf[5], sizeof WC->summ[num].to);
                }
 
                if (!strncasecmp(buf, "time=", 5)) {
-                       fmt_date(summ.date, atol(&buf[5]), 1);  /* brief */
+                       WC->summ[num].date = atol(&buf[5]);
                }
        }
        
 #ifdef HAVE_ICONV
        /* Handle senders with RFC2047 encoding */
-       utf8ify_rfc822_string(summ.from);
+       utf8ify_rfc822_string(WC->summ[num].from);
 #endif
-       if (strlen(summ.from) > 25) {
-               strcpy(&summ.from[22], "...");
+       if (strlen(WC->summ[num].from) > 25) {
+               strcpy(&WC->summ[num].from[22], "...");
        }
-
-       wprintf("<TD>");
-       if (is_new) wprintf("<B>");
-       wprintf("<A HREF=\"/readfwd?startmsg=%ld"
-               "&maxmsgs=1&summary=0\">", 
-               msgnum);
-       escputs(summ.subj);
-       wprintf("</A>");
-       if (is_new) wprintf("</B>");
-       wprintf("</TD><TD>");
-       if (is_new) wprintf("<B>");
-       escputs(summ.from);
-       if (is_new) wprintf("</B>");
-       wprintf(" </TD><TD>");
-       if (is_new) wprintf("<B>");
-       escputs(summ.date);
-       if (is_new) wprintf("</B>");
-       wprintf(" </TD>");
-       wprintf("<TD>"
-               "<INPUT TYPE=\"checkbox\" NAME=\"msg_%ld\" VALUE=\"yes\">"
-               "</TD>\n");
-
-       return;
 }
 
 
@@ -953,17 +948,10 @@ void display_addressbook(long msgnum, char alpha) {
        int mime_length;
        char vcard_partnum[SIZ];
        char *vcard_source = NULL;
-
-       struct {
-               char date[SIZ];
-               char from[SIZ];
-               char to[SIZ];
-               char subj[SIZ];
-               int hasattachments;
-       } summ;
+       struct message_summary summ;
 
        memset(&summ, 0, sizeof(summ));
-       strcpy(summ.subj, "(no subject)");
+       safestrncpy(summ.subj, "(no subject)", sizeof summ.subj);
 
        sprintf(buf, "MSG0 %ld|1", msgnum);     /* ask for headers only */
        serv_puts(buf);
@@ -1042,20 +1030,13 @@ void fetch_ab_name(long msgnum, char *namebuf) {
        char vcard_partnum[SIZ];
        char *vcard_source = NULL;
        int i;
-
-       struct {
-               char date[SIZ];
-               char from[SIZ];
-               char to[SIZ];
-               char subj[SIZ];
-               int hasattachments;
-       } summ;
+       struct message_summary summ;
 
        if (namebuf == NULL) return;
        strcpy(namebuf, "");
 
        memset(&summ, 0, sizeof(summ));
-       strcpy(summ.subj, "(no subject)");
+       safestrncpy(summ.subj, "(no subject)", sizeof summ.subj);
 
        sprintf(buf, "MSG0 %ld|1", msgnum);     /* ask for headers only */
        serv_puts(buf);
@@ -1236,6 +1217,36 @@ int load_msg_ptrs(char *servcmd)
        return (nummsgs);
 }
 
+int summcmp_subj(const void *s1, const void *s2) {
+       struct message_summary *summ1;
+       struct message_summary *summ2;
+       
+       summ1 = (struct message_summary *)s1;
+       summ2 = (struct message_summary *)s2;
+       return strcasecmp(summ1->subj, summ2->subj);
+}
+
+int summcmp_sender(const void *s1, const void *s2) {
+       struct message_summary *summ1;
+       struct message_summary *summ2;
+       
+       summ1 = (struct message_summary *)s1;
+       summ2 = (struct message_summary *)s2;
+       return strcasecmp(summ1->from, summ2->from);
+}
+
+int summcmp_date(const void *s1, const void *s2) {
+       struct message_summary *summ1;
+       struct message_summary *summ2;
+       
+       summ1 = (struct message_summary *)s1;
+       summ2 = (struct message_summary *)s2;
+
+       if (summ1->date < summ2->date) return -1;
+       else if (summ1->date > summ2->date) return +1;
+       else return 0;
+}
 
 /*
  * command loop for reading messages
@@ -1267,11 +1278,15 @@ void readloop(char *oper)
        int bg = 0;
        struct addrbookent *addrbook = NULL;
        int num_ab = 0;
+       char *sortby = NULL;
 
        startmsg = atol(bstr("startmsg"));
        maxmsgs = atoi(bstr("maxmsgs"));
        is_summary = atoi(bstr("summary"));
        if (maxmsgs == 0) maxmsgs = DEFAULT_MAXMSGS;
+       sortby = bstr("sortby");
+       if (strlen(sortby) == 0) sortby = "msgid";
+       if (strcasecmp(sortby, "msgid")) maxmsgs = 9999999;
 
        output_headers(1, 1, 1, 0, 0, 0, 0);
 
@@ -1350,6 +1365,29 @@ void readloop(char *oper)
                goto DONE;
        }
 
+       if (is_summary) {
+               if (WC->num_summ != 0) {
+                       WC->num_summ = 0;
+                       free(WC->summ);
+               }
+               WC->num_summ = nummsgs;
+               WC->summ = malloc(WC->num_summ*sizeof(struct message_summary));
+               for (a = 0; a < nummsgs; ++a) {
+                       /* Gather summary information */
+                       summarize_message(a, WC->msgarr[a], is_new);
+
+                       /* Are you a new message, or an old message? */
+                       if (is_summary) {
+                               if (is_msg_in_mset(old_msgs, WC->msgarr[a])) {
+                                       WC->summ[a].is_new = 0;
+                               }
+                               else {
+                                       WC->summ[a].is_new = 1;
+                               }
+                       }
+               }
+       }
+
        if (startmsg == 0L) startmsg = WC->msgarr[0];
        remaining_messages = 0;
 
@@ -1359,6 +1397,21 @@ void readloop(char *oper)
                }
        }
 
+       if (is_summary) {
+               if (!strcasecmp(sortby, "subject")) {
+                       qsort(WC->summ, WC->num_summ,
+                               sizeof(struct message_summary), summcmp_subj);
+               }
+               else if (!strcasecmp(sortby, "sender")) {
+                       qsort(WC->summ, WC->num_summ,
+                               sizeof(struct message_summary), summcmp_sender);
+               }
+               else if (!strcasecmp(sortby, "date")) {
+                       qsort(WC->summ, WC->num_summ,
+                               sizeof(struct message_summary), summcmp_date);
+               }
+       }
+
        wprintf("<form name=\"msgomatic\" "
                "METHOD=\"POST\" ACTION=\"/do_stuff_to_msgs\">\n");
        if (is_summary) {
@@ -1366,28 +1419,21 @@ void readloop(char *oper)
                        "<table border=0 cellspacing=0 "
                        "cellpadding=0 width=100%%>\n"
                        "<TR>"
-                       "<TD align=center><b><i>Subject</i></b></TD>"
-                       "<TD align=center><b><i>Sender</i></b></TD>"
-                       "<TD align=center><b><i>Date</i></b></TD>"
+                       "<TD align=center><b><i>Subject</i></b>%s</TD>"
+                       "<TD align=center><b><i>Sender</i></b>%s</TD>"
+                       "<TD align=center><b><i>Date</i></b>%s</TD>"
                        "<TD></TD>"
                        "</TR>\n"
+                       ,
+                       (!strcasecmp(sortby, "subject") ? "" : " <a href=\"/readfwd?startmsg=1&maxmsgs=9999999&summary=1&sortby=subject\"><img border=\"0\" src=\"/static/sort_none.gif\"></img></a>"),
+                       (!strcasecmp(sortby, "sender") ? "" : " <a href=\"/readfwd?startmsg=1&maxmsgs=9999999&summary=1&sortby=sender\"><img border=\"0\" src=\"/static/sort_none.gif\"></img></a>"),
+                       (!strcasecmp(sortby, "date") ? "" : " <a href=\"/readfwd?startmsg=1&maxmsgs=9999999&summary=1&sortby=date\"><img border=\"0\" src=\"/static/sort_none.gif\"></img></a>")
                );
        }
 
        for (a = 0; a < nummsgs; ++a) {
                if ((WC->msgarr[a] >= startmsg) && (num_displayed < maxmsgs)) {
 
-                       /* Are you a new message, or an old message? */
-                       is_new = 0;
-                       if (is_summary) {
-                               if (is_msg_in_mset(old_msgs, WC->msgarr[a])) {
-                                       is_new = 0;
-                               }
-                               else {
-                                       is_new = 1;
-                               }
-                       }
-
                        /* Learn which msgs "Prev" & "Next" buttons go to */
                        pn_current = WC->msgarr[a];
                        if (a > 0) pn_previous = WC->msgarr[a-1];
@@ -1403,7 +1449,7 @@ void readloop(char *oper)
 
                        /* Display the message */
                        if (is_summary) {
-                               summarize_message(WC->msgarr[a], is_new);
+                               display_summarized(a);
                        }
                        else if (is_addressbook) {
                                fetch_ab_name(WC->msgarr[a], buf);
@@ -1563,6 +1609,12 @@ DONE:
        wDumpContent(1);
        if (addrbook != NULL) free(addrbook);
 
+       /* free the summary */
+       if (WC->num_summ != 0) {
+               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.
diff --git a/webcit/static/sort_none.gif b/webcit/static/sort_none.gif
new file mode 100644 (file)
index 0000000..68dce00
Binary files /dev/null and b/webcit/static/sort_none.gif differ
index be6bbafe5829884c3cd09156f41a61673219082c..db14657589408ef0c32f47ab499e8d179371339a 100644 (file)
@@ -181,6 +181,16 @@ struct wc_attachment {
        char *data;
 };
 
+struct message_summary {
+       time_t date;
+       long msgnum;
+       char from[128];
+       char to[128];
+       char subj[128];
+       int hasattachments;
+       int is_new;
+};
+
 /*
  * One of these is kept for each active Citadel session.
  * HTTP transactions are bound to one at a time.
@@ -219,7 +229,11 @@ struct wcsession {
        int killthis;                   /* Nonzero == purge this session */
        struct march *march;            /* march mode room list */
        char reply_to[SIZ];             /* reply-to address */
+
        long msgarr[10000];             /* for read operations */
+       int num_summ;
+       struct message_summary *summ;
+
        int is_wap;                     /* Client is a WAP gateway */
        struct urlcontent *urlstrings;
        int HaveInstantMessages;        /* Nonzero if incoming msgs exist */
@@ -524,7 +538,6 @@ void end_burst(void);
 extern char *ascmonths[];
 void http_datestring(char *buf, size_t n, time_t xtime);
 
-
 /* Views (from citadel.h) */
 #define        VIEW_BBS                0       /* Traditional Citadel BBS view */
 #define VIEW_MAILBOX           1       /* Mailbox summary */