You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by pq...@apache.org on 2005/10/08 11:04:27 UTC

svn commit: r307275 - in /httpd/mod_mbox/trunk/module-2.0: mbox_parse.c mbox_parse.h mod_mbox.h mod_mbox_file.c mod_mbox_index.c mod_mbox_out.c

Author: pquerna
Date: Sat Oct  8 02:04:23 2005
New Revision: 307275

URL: http://svn.apache.org/viewcvs?rev=307275&view=rev
Log:
Add support for Atom 1.0 feeds to mod_mbox indexes. Just pass '?format=atom' to any directory index handled by mod_mbox.

mod_mbox_file.c: Expose load_message, since this is the first time we are fetching message data without searching for a specific message ID
mod_mbox_index.c: Add mbox_atom_handler, to create the base Atom Feed.
mod_mbox_out.c: Add worker output functions for Atom Feeds.
mod_mbox.h: Add mbox_atom_entries, load_message, and MBOX_ATOM_NUM_ENTRIES(40)
mbox_parse.{c,h}: Add MBOX_SORT_REVERSE_DATE for sorting in newest to oldest.


Modified:
    httpd/mod_mbox/trunk/module-2.0/mbox_parse.c
    httpd/mod_mbox/trunk/module-2.0/mbox_parse.h
    httpd/mod_mbox/trunk/module-2.0/mod_mbox.h
    httpd/mod_mbox/trunk/module-2.0/mod_mbox_file.c
    httpd/mod_mbox/trunk/module-2.0/mod_mbox_index.c
    httpd/mod_mbox/trunk/module-2.0/mod_mbox_out.c

Modified: httpd/mod_mbox/trunk/module-2.0/mbox_parse.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/trunk/module-2.0/mbox_parse.c?rev=307275&r1=307274&r2=307275&view=diff
==============================================================================
--- httpd/mod_mbox/trunk/module-2.0/mbox_parse.c (original)
+++ httpd/mod_mbox/trunk/module-2.0/mbox_parse.c Sat Oct  8 02:04:23 2005
@@ -360,6 +360,14 @@
     return ((a->key > b->key) ? 1 : -1);
 }
 
+static int mbox_reverse_list(void *p, void *q, void *pointer)
+{
+    MBOX_LIST *a = (MBOX_LIST*)p;
+    MBOX_LIST *b = (MBOX_LIST*)q;
+
+    return ((a->key > b->key) ? -1 : 1);
+}
+
 /*
  * Comparison function called by sort_linked_list to sort MBOX_LIST items
  * by author (then by date).
@@ -398,6 +406,10 @@
     {
     case MBOX_SORT_DATE:
         l = (MBOX_LIST*) mbox_sort_linked_list(l, 0, mbox_compare_list,
+                                               NULL, NULL);
+        break;
+    case MBOX_SORT_REVERSE_DATE:
+        l = (MBOX_LIST*) mbox_sort_linked_list(l, 0, mbox_reverse_list,
                                                NULL, NULL);
         break;
     case MBOX_SORT_AUTHOR:

Modified: httpd/mod_mbox/trunk/module-2.0/mbox_parse.h
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/trunk/module-2.0/mbox_parse.h?rev=307275&r1=307274&r2=307275&view=diff
==============================================================================
--- httpd/mod_mbox/trunk/module-2.0/mbox_parse.h (original)
+++ httpd/mod_mbox/trunk/module-2.0/mbox_parse.h Sat Oct  8 02:04:23 2005
@@ -41,6 +41,7 @@
 #define MBOX_SORT_DATE   0
 #define MBOX_SORT_AUTHOR 1
 #define MBOX_SORT_THREAD 2
+#define MBOX_SORT_REVERSE_DATE 3
 
 /*
  * MBOX_BUFF emulates the Apache BUFF structure, however it only

Modified: httpd/mod_mbox/trunk/module-2.0/mod_mbox.h
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/trunk/module-2.0/mod_mbox.h?rev=307275&r1=307274&r2=307275&view=diff
==============================================================================
--- httpd/mod_mbox/trunk/module-2.0/mod_mbox.h (original)
+++ httpd/mod_mbox/trunk/module-2.0/mod_mbox.h Sat Oct  8 02:04:23 2005
@@ -62,6 +62,8 @@
 
 #define MBOX_WRAP_TO 90
 
+#define MBOX_ATOM_NUM_ENTRIES 40
+
 typedef struct mbox_dir_cfg {
     int enabled;
     int antispam;
@@ -98,12 +100,13 @@
 /* Output functions */
 apr_status_t mbox_xml_msglist(request_rec *r, apr_file_t *f, int sortFlags);
 apr_status_t mbox_static_msglist(request_rec *r, apr_file_t *f, int sortFlags);
-
 apr_status_t mbox_xml_boxlist(request_rec *r);
 apr_status_t mbox_static_boxlist(request_rec *r);
 apr_status_t mbox_static_index_boxlist(request_rec *r, mbox_dir_cfg_t *conf,
 				       mbox_cache_info *mli);
 
+void mbox_atom_entries(request_rec *r, mbox_cache_info *mli);
+
 apr_status_t mbox_ajax_browser(request_rec *r);
 
 apr_status_t mbox_raw_message(request_rec *r, apr_file_t *f);
@@ -139,6 +142,8 @@
                                           char *path);
 Message *fetch_message(request_rec *r, apr_file_t *f, char *msgID);
 char **fetch_context_msgids(request_rec *r, apr_file_t *f, char*msgID);
+
+void load_message(apr_pool_t *p, apr_file_t *f, Message *m);
 
 #ifdef __cplusplus
 }

Modified: httpd/mod_mbox/trunk/module-2.0/mod_mbox_file.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/trunk/module-2.0/mod_mbox_file.c?rev=307275&r1=307274&r2=307275&view=diff
==============================================================================
--- httpd/mod_mbox/trunk/module-2.0/mod_mbox_file.c (original)
+++ httpd/mod_mbox/trunk/module-2.0/mod_mbox_file.c Sat Oct  8 02:04:23 2005
@@ -49,6 +49,27 @@
     return m;
 }
 
+/* Fetch a message from mailbox */
+void load_message(apr_pool_t *p, apr_file_t *f, Message *m)
+{
+    apr_size_t len = 0;
+
+    /* Fetch message (from msg_start to body_end) */
+    if (apr_file_seek(f, APR_SET, &m->msg_start) != APR_SUCCESS) {
+        return;
+    }
+
+    len = m->body_end - m->msg_start;
+    m->raw_msg = apr_palloc(p, len+1);
+
+    if (apr_file_read(f, m->raw_msg, &len) != APR_SUCCESS) {
+        return;
+    }
+
+    m->raw_msg[len] = '\0';
+    m->raw_body = m->raw_msg + (m->body_start - m->msg_start);
+}
+
 /* Find thread starting with message 'msgID' in container 'c' */
 static Container *find_thread(request_rec *r, char *msgID, Container *c)
 {

Modified: httpd/mod_mbox/trunk/module-2.0/mod_mbox_index.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/trunk/module-2.0/mod_mbox_index.c?rev=307275&r1=307274&r2=307275&view=diff
==============================================================================
--- httpd/mod_mbox/trunk/module-2.0/mod_mbox_index.c (original)
+++ httpd/mod_mbox/trunk/module-2.0/mod_mbox_index.c Sat Oct  8 02:04:23 2005
@@ -89,6 +89,42 @@
     return files;
 }
 
+
+int mbox_atom_handler(request_rec *r, mbox_cache_info *mli)
+{
+    char dstr[100];
+    apr_size_t dlen;
+    char *etag;
+    apr_time_exp_t extime;
+    
+    ap_set_content_type(r, "application/xml; charset=utf-8");
+
+    /* Try to make the index page more cache friendly */
+    ap_update_mtime(r, mli->mtime);
+    ap_set_last_modified(r);
+    etag = ap_make_etag(r, 1);
+    apr_table_setn(r->headers_out, "ETag", etag);
+
+    ap_rputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", r);
+    ap_rputs("<feed xmlns=\"http://www.w3.org/2005/Atom\">\n", r);
+    ap_rprintf(r, "<title>%s@%s Archives</title>\n",
+	       ESCAPE_OR_BLANK(r->pool, mli->list),
+	       ESCAPE_OR_BLANK(r->pool, mli->domain));
+    ap_rprintf(r, "<link rel=\"self\" href=\"%s?format=atom\"/>\n",  ap_construct_url(r->pool, r->uri, r));
+    ap_rprintf(r, "<link href=\"%s\"/>\n",  ap_construct_url(r->pool, r->uri, r));
+    ap_rprintf(r, "<id>%s</id>\n",  ap_construct_url(r->pool, r->uri, r));
+
+    apr_time_exp_gmt(&extime, mli->mtime);
+    
+    apr_strftime(dstr, &dlen, sizeof(dstr),
+                 "%G-%m-%dT%H:%M:%SZ", &extime);
+
+    ap_rprintf(r, "<updated>%s</updated>\n", dstr);
+    mbox_atom_entries(r, mli);
+    ap_rputs("</feed>\n", r);
+    return OK;
+}
+
 /* The default index handler, using mbox_display_static_index() */
 int mbox_index_handler(request_rec *r)
 {
@@ -115,6 +151,10 @@
                        "mod_mbox: Can't open directory cache '%s' for index",
                        r->filename);
         return DECLINED;
+    }
+
+    if (r->args && strstr(r->args, "format=atom") != NULL) {
+        return mbox_atom_handler(r, mli);
     }
 
     ap_set_content_type(r, "text/html; charset=utf-8");

Modified: httpd/mod_mbox/trunk/module-2.0/mod_mbox_out.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/trunk/module-2.0/mod_mbox_out.c?rev=307275&r1=307274&r2=307275&view=diff
==============================================================================
--- httpd/mod_mbox/trunk/module-2.0/mod_mbox_out.c (original)
+++ httpd/mod_mbox/trunk/module-2.0/mod_mbox_out.c Sat Oct  8 02:04:23 2005
@@ -34,6 +34,122 @@
     { "Dec", "December" }
 };
 
+void display_atom_entry(request_rec *r, Message *m, const char* mboxfile,
+                        apr_pool_t *pool, apr_file_t *f)
+{
+    char dstr[100];
+    apr_size_t dlen;
+    apr_time_exp_t extime; 
+    char* uid;
+    char* c;
+
+    ap_rputs("<entry>\n", r);
+    ap_rprintf(r, "<title>%s</title>\n",  ESCAPE_OR_BLANK(pool, m->subject));
+    ap_rprintf(r, "<author><name>%s</name></author>\n",
+               ESCAPE_OR_BLANK(pool, m->from));
+
+    ap_rprintf(r, "<link rel=\"alternate\" href=\"%s%s/%s\"/>\n",
+               ap_construct_url(r->pool, r->uri, r), 
+               mboxfile, URI_ESCAPE_OR_BLANK(pool, m->msgID));
+
+    uid = URI_ESCAPE_OR_BLANK(pool, m->msgID);
+
+    c = uid;
+    while (*c != '\0') {
+        if (*c == '.') {
+            *c = '-';
+        }
+        *c++;
+    }
+
+    ap_rprintf(r, "<id>urn:uuid:%s</id>\n", uid);
+
+    apr_time_exp_gmt(&extime, m->date);
+
+    apr_strftime(dstr, &dlen, sizeof(dstr),
+                 "%G-%m-%dT%H:%M:%SZ", &extime);
+
+    ap_rprintf(r, "<updated>%s</updated>\n", dstr);
+    ap_rputs("<content type=\"text\">\n", r);
+
+    load_message(pool, f, m);
+    /* Parse multipart information */
+    m->mime_msg = mbox_mime_decode_multipart(pool, m->raw_body,
+					     m->content_type,
+					     m->cte, m->boundary);
+
+    ap_rprintf(r, "%s", mbox_wrap_text(mbox_mime_get_body(pool, m->mime_msg)));
+
+    ap_rputs("</content>\n", r);
+    ap_rputs("</entry>\n", r);
+}
+
+static int mbox2atom(request_rec *r, const char* mboxfile, mbox_cache_info *mli, int max)
+{
+    apr_status_t rv;
+    char* filename;
+    char* origfilename;
+    apr_file_t *f;
+    MBOX_LIST *head;
+    Message *m;
+    int i;
+    apr_pool_t* tpool;
+    
+    apr_pool_create(&tpool, r->pool);
+
+    filename = apr_pstrcat(r->pool, r->filename, mboxfile, NULL);
+
+    rv = apr_file_open(&f, filename, APR_READ,
+                       APR_OS_DEFAULT, r->pool);
+
+    if(rv != APR_SUCCESS) {
+        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+                      "mod_mbox(mbox2atom): Can't open mbox '%s' for atom feed",
+                      filename);
+        return 0;
+    }
+    origfilename = r->filename;
+
+    r->filename = filename;
+
+    head = mbox_load_index(r, f, NULL);
+    
+    /* Sort the list */
+    head = mbox_sort_list(head, MBOX_SORT_REVERSE_DATE);
+
+    for (i = 0; i < max && head != NULL; i++) {
+        m = (Message*)head->value;
+        display_atom_entry(r, m, mboxfile, tpool, f);
+        head = head->next;
+        apr_pool_clear(tpool);
+    }
+
+    r->filename = origfilename;
+    apr_pool_destroy(tpool);
+    return i;
+}
+
+void mbox_atom_entries(request_rec *r, mbox_cache_info *mli)
+{
+    mbox_file_t *fi;
+    apr_array_header_t *files;
+    int i, entries = 0;
+
+    files = mbox_fetch_boxes_list(r, mli, r->filename);
+    if (!files) {
+        return;
+    }
+
+    fi = (mbox_file_t *)files->elts;
+    for (i = 0; i < files->nelts && entries < MBOX_ATOM_NUM_ENTRIES; i++) {
+        if (!fi[i].count) {
+            continue;
+        }
+        entries += mbox2atom(r, fi[i].filename, mli, MBOX_ATOM_NUM_ENTRIES - entries);
+    }
+}
+
+
 /* Outputs an XML list of available mailboxes */
 apr_status_t mbox_xml_boxlist(request_rec *r)
 {