You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by ma...@apache.org on 2005/08/26 23:33:19 UTC
svn commit: r240348 - in /httpd/mod_mbox/branches/httpd-mbox-if: ./ data/
module-2.0/
Author: maxime
Date: Fri Aug 26 14:33:07 2005
New Revision: 240348
URL: http://svn.apache.org/viewcvs?rev=240348&view=rev
Log:
AJAX browser basics. Backported some fixes by justin from
trunk/. Still some bugs, though. Bug squashing in progress ...
Note: there are still some tabs in the code indentation. I'll make a
one-shot commit for this kind of stuff.
* module-2.0/mod_mbox_cte.c:
(mbox_cte_decode_header): added lacks to function's comment. Basics for charset conversion using apr_xlate, but not working yet.
* module-2.0/mod_mbox_file.c:
(fetch_context_msgids): set the pointers to NULL by default in
order to avoid false-positives tests later on.
* module-2.0/mod_mbox.c:
(mbox_wrap_text): new utility function for basic text
wrapping. Not very good, but better than nothing.
(get_base_path): added comment.
* module-2.0/mod_mbox.h: added include for apr_xlate and function
prototype for mbox_wrap_text.
* module-2.0/mod_mbox_mime.c:
(mbox_mime_decode_multipart): exclude mail contents from header
lookups. Fixes several weird bugs in gathered informations.
(mbox_mime_get_body): do not work on m->body directly because
length can grow while decoding Quoted-Printable or Base64.
(mbox_mime_static_structure): factored </a> markup.
(mbox_mime_xml_structure): fixed outputted structure incoherence.
* module-2.0/mod_mbox_index.c:
(mbox_index_handler): return DECLINED instead of HTTP_NOT_FOUND
when the mbox cache is not available. Backported from r231188. Added
an ID parameter to the body markup.
* module-2.0/mod_mbox_out.c:
(mbox_static_boxlist): fixed typo in function's comment. Added ID
parameter to a message's table row (only if needed).
(mbox_xml_msglist): removed unused month and year attributes. Same
for baseURI, now useless.
(mbox_static_msglist): added ID parameter to body markup. Small
change to page header. Don't link to current sort mode.
(mbox_ajax_browser): pass the baseURI to the Javascript context.
(mbox_static_message_nav): new function displaying message navigation.
(mbox_static_message): added ID parameter to body markup. Now uses
the new mbox_static_message_nav function. Also display the message
navigation as table footer. Wrap text before displaying it.
(mbox_xml_message): use CDATA for subject, too. Wrap text.
* module-2.0/mod-mbox-util.c:
(scan_dir): skip empty mbox files in order to determine list
info. Backported from r231183.
* STATUS: updated.
* configure.ac: fixed typo. Backported from r231182.
* data/archives.js:
(getBoxList, getMsgList, getMessage, ...): implementing the AJAX
browser.
* data/style.css: minor fixes related to the AJAX browser's needs.
Modified:
httpd/mod_mbox/branches/httpd-mbox-if/STATUS
httpd/mod_mbox/branches/httpd-mbox-if/configure.ac
httpd/mod_mbox/branches/httpd-mbox-if/data/archives.js
httpd/mod_mbox/branches/httpd-mbox-if/data/asf_logo_simple.png
httpd/mod_mbox/branches/httpd-mbox-if/data/style.css
httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod-mbox-util.c
httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.c
httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.h
httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_cte.c
httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_file.c
httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_index.c
httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_mime.c
httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_out.c
Modified: httpd/mod_mbox/branches/httpd-mbox-if/STATUS
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/STATUS?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/STATUS (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/STATUS Fri Aug 26 14:33:07 2005
@@ -8,36 +8,32 @@
Release showstoppers:
- * AJAX browsing interface
- * S/MIME and MIME structure parsing [done]
- * MIME header parsing [done]
- * Charset conversions (to UTF-8)
+ * MIME part viewing / downloading
Other known issues / ToDo:
- * MIME part viewing / downloading
-
* Documentation
- For developpers : internals
- For admins : setup and update
- For users : usage, interface description, ...
- * Wrap long lines in mails (to ~90 chars so we don't mess
- with MUA different configurations). Any ideas on how to do
- this clean and fast enough ?
-
- * A QP mail with a '=_N' in it's MIME boundary fails to be parsed
- by mbox_mime_decode_multipart[1]. Strange, because no QP
- decoding is done before multipart parsing : only 'JIT' before
- display.
+ * Use apr_strftime() to format dates instead of apr_rfc822_date()
+
+ * Charset conversions (to UTF-8). APR-Xlate features are nice, but
+ the conversion are easy only from APR v1.1.0. Multibyte
+ characters conversion with APR v0.x is a pain.
- [1] dev@httpd (200302.mbox): <00...@fred>
+ * Better page selector (usefull for 10+ pages archives)
- * Merge Justin changes into httpd-mbox-if branch
- r231181, r231182, r231183, r231187, r231188
+ * Subject RFC 2047 decoding. See function's comment
+ (mod_mbox_cte.c)
Wish list:
* Better integration with httpd-2.0 build system.
* Interface internationalization
* Better XML semantics ?
+ * Use Javascript object-oriented features
+ * When viewing a message, come back to the page we came instead of
+ the first page of the choosen listing (without cookie, if
+ possible)
\ No newline at end of file
Modified: httpd/mod_mbox/branches/httpd-mbox-if/configure.ac
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/configure.ac?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/configure.ac (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/configure.ac Fri Aug 26 14:33:07 2005
@@ -44,6 +44,6 @@
echo "---"
echo "Configuration summary for mod_mbox"
echo ""
-echo " * Apache Dodules Directory: $AP_LIBEXECDIR"
+echo " * Apache Modules Directory: $AP_LIBEXECDIR"
echo ""
echo "---"
Modified: httpd/mod_mbox/branches/httpd-mbox-if/data/archives.js
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/data/archives.js?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/data/archives.js (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/data/archives.js Fri Aug 26 14:33:07 2005
@@ -1,11 +1,24 @@
-/** mod_mbox
- */
+/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
+* applicable.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
-/* onLoad function for boxes list.
- *
- * Change 'Threads - Date - Author' links into a single 'Browser'
- * link.
+/* mod_mbox javascript functions.
*/
+
+/* onLoad function for boxes list : changes 'Threads - Date - Author'
+ * links into a single 'Browser' link. */
function indexLinks ()
{
var i, entries;
@@ -17,28 +30,534 @@
/* Update span.links contents */
while (entries[i]) {
- if (entries[i].hasAttribute('class')) {
- if (entries[i].getAttribute('class') == 'links') {
- entries[i].innerHTML = '<a href="' +
- entries[i].getAttribute('id') +
- '.mbox/browser">Browse</a>';
+ if (entries[i].className == 'links') {
+ entries[i].innerHTML = '<a href="' +
+ entries[i].getAttribute('id') +
+ '.mbox/browser">Browse</a>';
+ }
+ i++;
+ }
+
+ return true;
+}
+
+var _mbox = ''; /* Current browsed mailbox */
+var _baseURI = ''; /* Base archives URI */
+var _sort = 'thread'; /* Sort mode defaults to 'thread' */
+var _page = 0;
+
+var _boxlist = null;
+var _msglist = null;
+
+var _default_ctx = 3;
+
+/* onLoad function for browser. Call the message list and box list
+ * creation functions. */
+function loadBrowser (baseURI)
+{
+ _baseURI = baseURI.substring(0, baseURI.lastIndexOf('/')+1);
+ _mbox = baseURI.substring(baseURI.lastIndexOf('/')+1);
+
+ body = document.getElementsByTagName('body')[0];
+ body.innerHTML += '<div id="loading">Loading ...</div>';
+
+ document.getElementsByTagName('h1')[0].innerHTML += ': ' +
+ getMonthName(parseInt(_mbox.substr(4, 2), 10), true) + ' ' +
+ _mbox.substr(0, 4);
+
+ /* Get message list */
+ if (!getMsgList (null, null)) {
+ body.innerHTML += '<table id="msglist">' +
+ '<thead><tr><th>Message list</th></tr></thead>' +
+ '<tbody><tr><td>Unable to load message list for ' +
+ _mbox + ' !</td></tr></tbody></table>';
+ }
+
+ /* Get box list */
+ if (!getBoxList ()) {
+ body.innerHTML += '<table id="boxlist">' +
+ '<thead><tr><th>Box list</th></tr></thead>' +
+ '<tbody><tr><td>Unable to load box list !</td></tr></tbody>' +
+ '</table>';
+ }
+
+ return true;
+}
+
+/* Returns the textual representation of a month number. */
+function getMonthName (num, full)
+{
+ var full_months = new Array("January", "February", "March",
+ "April", "May", "June", "July",
+ "August", "September", "October",
+ "November", "December");
+
+ var short_months = new Array("Jan", "Feb", "Mar", "Apr",
+ "May", "Jun", "Jul", "Aug",
+ "Sep", "Oct", "Nov", "Dec");
+
+ if (full) {
+ return full_months[num-1];
+ }
+
+ return short_months[num-1];
+}
+
+/* Returns a XmlHttpObject, or false on error. Don't forget to use
+ * different variable names for XMLHttpRequest object instances since
+ * we are doing asynchronous Javascript and JS does not support
+ * variable scope (local variables). */
+function getHTTPObject ()
+{
+ var xmlhttp = false;
+
+ /*@cc_on
+ @if (@_jscript_version >= 5)
+
+ try {
+ xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
+ } catch (e) {
+ try {
+ xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+ } catch (E) {
+ xmlhttp = false;
+ }
+ }
+
+ @else
+ xmlhttp = false;
+ @end
+ @*/
+
+ if (!xmlhttp && typeof XMLHttpRequest != 'undefined') {
+ try {
+ xmlhttp = new XMLHttpRequest();
+ } catch (e) {
+ xmlhttp = false;
+ }
+ }
+
+ return xmlhttp;
+}
+
+/* Retreive the message list from server, according to the sort flag
+ * and page number given */
+function getMsgList (sort, page)
+{
+ var msglist_http = getHTTPObject ();
+
+ if (!msglist_http) {
+ return false;
+ }
+
+ if (!sort) {
+ sort = _sort;
+ }
+
+ _sort = sort;
+
+ /* The handler */
+ msglist_http.onreadystatechange = function () {
+ if (msglist_http.readyState == 4) { /* 4 : "complete" */
+ if (msglist_http.status == 200) { /* 200 : OK */
+ _msglist = msglist_http.responseXML.documentElement;
+ var i;
+
+ drawFullMsgList ();
+
+ /* Remove now useless loading message */
+ body.removeChild(document.getElementById('loading'));
}
}
+ }
+
+ msglist_http.open('GET', 'ajax/' + sort + '?' + page, true);
+ msglist_http.send(null);
+
+ return true;
+}
+
+function drawFullMsgList ()
+{
+ /* Destroy previous message view if displayed */
+ if (document.getElementById('msgview')) {
+ body.removeChild(document.getElementById('msgview'));
+ }
+
+ /* Get an array of all messages */
+ var msgs = _msglist.getElementsByTagName('message');
+
+ /* Create the destination table */
+ var msglist = document.createElement('table');
+ msglist.setAttribute('id', 'msglist');
+
+ var str = getMsgListHeader ();
+
+ /* Build message list entries */
+ str += '<tbody>';
+
+ i = 0;
+ while (msgs[i]) {
+ str += buildMessageListEntry (msgs[i], i);
i++;
}
+ str += '</tbody>';
+ msglist.innerHTML = str;
+
+ if (document.getElementById('msglist')) {
+ body.removeChild(document.getElementById('msglist'));
+ }
+
+ body.appendChild(msglist);
+}
+
+
+/* Returns the message list table header, including page selector and
+ * sort links */
+function getMsgListHeader ()
+{
+ /* Fetch current page and page count */
+ var current_page = _msglist.getAttribute('page');
+ var pages = _msglist.getAttribute('pages');
+
+ var str = '<thead><tr><th class="title">Message list</th>';
+
+ /* Page selector */
+ str += '<th class="pages">';
+ for (i = 0; i<pages ; i++) {
+ if (i) {
+ str += ' · ';
+ }
+
+ if (i != current_page) {
+ str += '<a href="browser" onclick="javascript:getMsgList(\'' + _sort + '\', \'' +
+ i + '\'); return false;">' + (i+1) + '</a>';
+ }
+ else {
+ str += (i+1);
+ }
+ }
+ str += '</th>';
+
+ str += '<th class="sort">';
+ if (_sort == 'thread') {
+ str += 'Thread · ' +
+ '<a href="browser" onclick="javascript:getMsgList(\'author\', null); return false;">Author</a>' +
+ ' · ' +
+ '<a href="browser" onclick="javascript:getMsgList(\'date\', null); return false;">Date</a>';
+ }
+ else if (_sort == 'author') {
+ str += '<a href="browser" onclick="javascript:getMsgList(\'thread\', null); return false;">Thread</a>' +
+ ' · Author · ' +
+ '<a href="browser" onclick="javascript:getMsgList(\'date\', null); return false;">Date</a>';
+ }
+ else {
+ str += '<a href="browser" onclick="javascript:getMsgList(\'thread\', null); return false;">Thread</a>' +
+ ' · ' +
+ '<a href="browser" onclick="javascript:getMsgList(\'author\', null); return false;">Author</a>' +
+ ' · Date';
+ }
+
+ str += '</th></tr></thead>';
+
+ return str;
+}
+
+/* Returns a table-formatted message list entry */
+function buildMessageListEntry (msg, msg_num)
+{
+ var linked = parseInt(msg.getAttribute('linked'));
+ var str = '';
+ var i;
+
+ if (linked) {
+ str += '<tr id="' + msg.getAttribute('id') + '">';
+ }
+ else {
+ str += '<tr>';
+ }
+
+ /* The author */
+ str += '<td class="author">';
+ if (linked) {
+ str += msg.getElementsByTagName('from')[0].firstChild.data;
+ }
+ str += '</td>';
+
+ /* The subject */
+ str += '<td class="subject">';
+ for (i=0 ; i<msg.getAttribute('depth') ; i++) {
+ str += ' ';
+ }
+
+ if (linked) {
+ str += '<a href="ajax/' + msg.getAttribute('id') +
+ '" onclick="javascript:toggleMessage(' + msg_num + '); return false;">';
+ }
+
+ str += msg.getElementsByTagName('subject')[0].firstChild.data;
+
+ if (linked) {
+ str += '</a>';
+ }
+ str += '</td>';
+
+ /* The message date */
+ str += '<td class="date">';
+ if (linked) {
+ str += msg.getElementsByTagName('date')[0].firstChild.data;
+ }
+ str += '</td>';
+
+ str += '</tr>';
+
+ return str;
+}
+
+/* Toggle the view of a message. Change the message list into a
+ * context view, and call message view table creation. */
+function toggleMessage (msg_num)
+{
+ var msgs = _msglist.getElementsByTagName('message');
+ var id = msgs[msg_num].getAttribute('id');
+ var i;
+
+ var min = msg_num - _default_ctx;
+ var max = msg_num + _default_ctx;
+
+ /* Check context id values */
+ if (min < 0) {
+ min = 0;
+ }
+
+ /* Destroy previous message list table */
+ if (document.getElementById('msglist')) {
+ body.removeChild(document.getElementById('msglist'));
+ }
+
+ var msglist = document.createElement('table');
+ msglist.setAttribute('id', 'msglist');
+
+ var str = getMsgListHeader ();
+ str += '<tbody>';
+
+ /* Build list */
+ for (i=min ; i<=max ; i++) {
+ if (msgs[i]) {
+ str += buildMessageListEntry (msgs[i], i);
+ }
+ }
+
+ str += '</tbody></table>';
+ msglist.innerHTML = str;
+ body.appendChild(msglist);
+ document.getElementById(id).setAttribute('class', 'msgactive');
+
+ /* Display a loading box ... */
+ body.innerHTML += '<div id="loading">Loading ...</div>';
+
+ /* Now, display the message */
+ if (document.getElementById('msgview')) {
+ body.removeChild(document.getElementById('msgview'));
+ }
+
+ if (!getMessage (id)) {
+ body.innerHTML += '<table class="js" id="msgview">' +
+ '<thead><tr><th>Message view</th></tr></thead>' +
+ '<tbody><tr><td>Unable to load message ' + id + ' !</td></tr></tbody>' +
+ '</table>';
+ }
+}
+
+function getMessage (id)
+{
+ var message_http = getHTTPObject ();
+
+ if (!message_http) {
+ return false;
+ }
+
+ /* The handler */
+ message_http.onreadystatechange = function () {
+ if (message_http.readyState == 4) { /* 4 : "complete" */
+ if (message_http.status == 200) { /* 200 : OK */
+ var message = message_http.responseXML.documentElement;
+
+ /* Create the destination table */
+ var msgview = document.createElement('table');
+ msgview.setAttribute('id', 'msgview');
+ msgview.setAttribute('class', 'js');
+
+ var str = '<thead><tr><th class="title">Message view</th><th class="nav">' +
+ '<a href="browser" onclick="javascript:closeMessage(); return false;">x</a>' +
+ '</th></tr></thead>';
+ str += '<tbody>';
+
+ str += '<tr class="from"><td class="left">From</td><td class="right">' +
+ message.getElementsByTagName('from')[0].firstChild.data + '</td></tr>';
+ str += '<tr class="subject"><td class="left">Subject</td><td class="right">' +
+ message.getElementsByTagName('subject')[0].firstChild.data + '</td></tr>';
+ str += '<tr class="date"><td class="left">Date</td><td class="right">' +
+ message.getElementsByTagName('date')[0].firstChild.data + '</td></tr>';
+
+ str += '<tr class="contents"><td colspan="2"><pre>' +
+ message.getElementsByTagName('contents')[0].firstChild.data + '</pre></td></tr>';
+
+ /* MIME structure */
+ var mime = message.getElementsByTagName('mime')[0].childNodes;
+
+ str += '<tr class="mime"><td class="left">Mime</td><td class="right"><ul>' +
+ parseMimeStructure (mime) + '</ul></td></tr>';
+
+ str += '<tr class="raw"><td class="left"></td><td class="right">' +
+ '<a href="' + _baseURI + _mbox + '/raw?' + id + '" target="_blank">View raw message</a></td></tr>';
+
+ str += '</tbody>';
+ msgview.innerHTML = str;
+
+ /* Place our msgview just under the msglist */
+ msgview.style.top = document.getElementById('msglist').offsetHeight + 'px';
+ msgview.style.display = 'table';
+
+ /* Remove now useless loading message */
+ body.removeChild(document.getElementById('loading'));
+
+ /* And display the msgview */
+ body.appendChild(msgview);
+ document.documentElement.scrollTop = 0;
+ }
+ }
+ }
+
+ message_http.open('GET', 'ajax/' + id, true);
+ message_http.send(null);
+
return true;
}
-/* onLoad function for browser.
- *
+function parseMimeStructure (mime)
+{
+ var i = 0;
+ var str = '';
+
+ while (mime[i]) {
+
+ /* If the node is a MIME part, output its entry */
+ if (mime[i].nodeName == "part") {
+ str += '<li>';
+
+ var name = mime[i].getAttribute('name');
+ if (name) {
+ str += 'name';
+ }
+ else {
+ str += 'Unnamed ' + mime[i].getAttribute('ct');
+ }
+
+ str += ' (' + mime[i].getAttribute('cd') + ', ' +
+ mime[i].getAttribute('cte') + ', ' +
+ mime[i].getAttribute('length') + ' bytes)</li>';
+ }
+
+ /* Otherwise it's a MIME multipart, recurse */
+ else if (mime[i].nodeName == "mime") {
+ str += '<ul>' + parseMimeStructure (mime[i].childNodes) + '</ul>';
+ }
+ i++;
+ }
+
+ return str;
+}
+
+function closeMessage ()
+{
+ /* First, destroy the message view window */
+ if (document.getElementById('msgview')) {
+ body.removeChild(document.getElementById('msgview'));
+ }
+
+ /* Next, destroy previous message list table */
+ if (document.getElementById('msglist')) {
+ body.removeChild(document.getElementById('msglist'));
+ }
+
+ /* Finally, redraw full message list */
+ drawFullMsgList ();
+}
+
+/* Retreive and parse the box list.
*/
-function loadBrowser ()
+function getBoxList ()
{
- var body;
+ var boxlist_http = getHTTPObject ();
+
+ if (!boxlist_http) {
+ return false;
+ }
+
+ /* The handler */
+ boxlist_http.onreadystatechange = function () {
+ if (boxlist_http.readyState == 4) { /* 4 : "complete" */
+ if (boxlist_http.status == 200) { /* 200 : OK */
+ _boxlist = boxlist_http.responseXML.documentElement;
+
+ /* Get an array of all mbox entries */
+ var boxes = _boxlist.getElementsByTagName('mbox');
- body = document.getElementsByTagName('body');
- body[0].innerHTML = body[0].innerHTML + '<p id="loading">Loading ...</p>';
+ /* Create the destination table */
+ var boxlist = document.createElement('table');
+ boxlist.setAttribute('id', 'boxlist');
+
+ var str = '<thead><tr><th colspan="2">Box list</th></tr></thead>';
+ str += '<tbody>';
+
+ /* Parse boxes array */
+ var i = 0;
+ while (boxes[i]) {
+ str += buildBoxListEntry (boxes[i]);
+ i++;
+ }
+
+ str += '</tbody>';
+ boxlist.innerHTML = str;
+ body.appendChild(boxlist);
+ }
+ }
+ }
+
+ boxlist_http.open('GET', 'ajax/boxlist', true);
+ boxlist_http.send(null);
return true;
+}
+
+function buildBoxListEntry (box)
+{
+ var id = box.getAttribute('id');
+ var str = '';
+
+ /* If the mbox id is the same as the one who called the
+ browser, set the entry as active */
+ if (id == _mbox) {
+ str += '<tr id="boxactive">';
+ }
+ else {
+ str += '<tr>';
+ }
+
+ /* Build link (_baseURI/id/browser) */
+ str += '<td class="box"><a href="' + _baseURI + id + '/browser">';
+
+ /* Display month name (short text) and year. The decimal
+ base (10) is passed to parseInt in order to avoid octal
+ parsing due to leading 0. */
+ str += getMonthName(parseInt(id.substr(4, 2), 10), false) +
+ ' ' + id.substr(0, 4) + '</a></td>';
+
+ /* Finally end the entry with the message count */
+ str += '<td class="msgcount">' + box.getAttribute('count') +
+ '</td></tr>';
+
+ return str;
}
Modified: httpd/mod_mbox/branches/httpd-mbox-if/data/asf_logo_simple.png
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/data/asf_logo_simple.png?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
Binary files - no diff available.
Modified: httpd/mod_mbox/branches/httpd-mbox-if/data/style.css
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/data/style.css?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/data/style.css (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/data/style.css Fri Aug 26 14:33:07 2005
@@ -1,3 +1,5 @@
+html { margin: 0; padding: 0; }
+
body
{
margin: 0;
@@ -14,8 +16,8 @@
h1
{
font-size: xx-large;
- margin: 0.6em 2%;
- padding: 0 0 0.2em 0;
+ margin: 0.5em 2%;
+ padding: 0;
}
p#lastupdated
@@ -28,10 +30,19 @@
font-style: italic;
}
-p#loading
+div#loading
{
+ border: 2px #900 solid;
+ background: #ccc;
text-align: center;
font-style: italic;
+
+ position: absolute;
+ top: 65%;
+ left: 30%;
+ right: 30%;
+
+ padding: 2em;
}
table
@@ -44,7 +55,7 @@
border-top: none;
}
-table thead th
+table thead th, table tfoot th
{
font-size: 110%;
font-weight: bold;
@@ -55,8 +66,8 @@
color: white;
}
-table thead th a { color: white; }
-table td { padding: 0.3em 0.5em; }
+table thead th a, table tfoot th a { color: white; }
+table td { padding: 0.2em 0.5em; }
table#grid
{
@@ -88,7 +99,7 @@
table.year tr td.date { background: #ddd; width: 20%;
text-align: center; padding-right: 1em;
- font-weight: bold; }
+ font-weight: bold; white-space: nowrap; }
table.year tr td.links { background: #eee; width: 70%; }
table.year tr td.msgcount { background: #ddd; width: 10%; text-align: center; }
@@ -102,7 +113,7 @@
table#boxlist
{
position: absolute;
- top: 7em;
+ top: 6em;
left: 2%;
right: 88%;
width: 10%;
@@ -119,9 +130,6 @@
border-bottom: 1px #888 solid;
}
-table#boxlist tr.newyear { border-top: 1px #888 solid; border-bottom: 1px #888 solid;
- text-align: center; font-weight: bold; background: white; }
-
table#boxlist td.msgcount { text-align: right; }
table#boxlist td.box { white-space: nowrap; }
table#boxlist td.box a { display: block; }
@@ -131,9 +139,9 @@
table#msglist
{
position: absolute;
- top: 7em;
+ top: 6em;
margin: 0 2% 2em auto;
- width: 80%;
+ width: 82%;
}
table#msglist thead th.title { text-align: left; white-space: nowrap; }
@@ -148,14 +156,11 @@
text-align: right; font-style: italic;
white-space: nowrap; }
-table#msglist tr#msgactive
-{
- border-top: 1px #888 solid;
-}
+table#msglist tr.msgactive { border-top: 1px #888 solid; }
-table#msglist tr#msgactive td.author,
-table#msglist tr#msgactive td.subject,
-table#msglist tr#msgactive td.date { background: white; }
+table#msglist tr.msgactive td.author,
+table#msglist tr.msgactive td.subject,
+table#msglist tr.msgactive td.date { background: white; }
table#msglist tr:hover td.author { background: #eee; }
table#msglist tr:hover td.subject { background: white; }
@@ -163,16 +168,27 @@
/** Message view
*/
-table#msgview
+table.static#msgview
{
position: absolute;
- top: 7em;
+ top: 6em;
margin: 0 2% 2em 2%;
width: 96%;
}
-table#msgview thead th.title { text-align: left; white-space: nowrap; }
-table#msgview thead th.nav { text-align: right; padding-right: 0.3em; }
+table.js#msgview
+{
+ position: absolute;
+ top: 0;
+ margin: 5em 2% 2em auto;
+ width: 82%;
+ display: none;
+}
+
+table#msgview thead th.title,
+table#msgview tfoot th.title { text-align: left; white-space: nowrap; }
+table#msgview thead th.nav,
+table#msgview tfoot th.nav { text-align: right; padding-right: 0.3em; }
table#msgview tr td.left { background: #ddd; width: 10%;
text-align: right; padding-right: 1em; font-weight: bold; }
@@ -180,7 +196,7 @@
table#msgview tr.raw td.right { font-family: sans-serif; }
-table#msgview tr.contents { border-top: 1px #888 solid; }
+table#msgview tr.contents { border-top: 1px #888 solid; background: white; }
table#msgview tr.contents pre { white-space: pre-wrap; }
table#msgview tr.mime { vertical-align: top; }
Modified: httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod-mbox-util.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod-mbox-util.c?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod-mbox-util.c (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod-mbox-util.c Fri Aug 26 14:33:07 2005
@@ -128,7 +128,7 @@
apr_dir_t *dir;
apr_finfo_t finfo;
apr_array_header_t* files;
- char* file;
+ char* file = NULL;
char* ml;
char* domain;
char* list;
@@ -178,7 +178,14 @@
files->nelts);
}
- file = ((char**)files->elts)[0];
+ /* Look for first non-empty file. */
+ for (i = 0; i < files->nelts; i++) {
+ file = ((char**)files->elts)[i];
+ rv = apr_stat(&finfo, file, APR_FINFO_SIZE, mpool);
+ if (rv == APR_SUCCESS && finfo.size > 0) {
+ break;
+ }
+ }
if (verbose) {
apr_file_printf(errfile, "Scaning %s for Mailing List info" NL,
Modified: httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.c?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.c (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.c Fri Aug 26 14:33:07 2005
@@ -132,6 +132,33 @@
return to;
}
+/* Wrap text to MBOX_WRAP_TO. Changes passed string. */
+char *mbox_wrap_text(char *str)
+{
+ int i, pos;
+
+ if (!str || (strlen(str) < MBOX_WRAP_TO))
+ return str;
+
+ for (i=0, pos=0; i<strlen(str); i++, pos++) {
+ /* Reset the position counter if we pass a newline character */
+ if (str[i] == '\n') {
+ pos = 0;
+ }
+
+ /* If the position counter is after the wrap limit, wrap text at
+ first space available */
+ if ((pos >= MBOX_WRAP_TO) &&
+ ((str[i] == ' ') || (str[i] == '\t'))) {
+ str[i] = '\n';
+ pos = 0;
+ }
+ }
+
+ return str;
+}
+
+/* Returns the archives base path */
char *get_base_path(request_rec *r)
{
char *baseURI, *temp;
Modified: httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.h
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.h?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.h (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox.h Fri Aug 26 14:33:07 2005
@@ -24,12 +24,13 @@
#include "http_protocol.h"
#include "http_request.h"
#include "util_script.h"
-#include "apr_date.h"
+#include "apr_date.h"
#include "apr_strings.h"
#include "apr_dbm.h"
#include "apr_hash.h"
#include "apr_fnmatch.h"
+#include "apr_xlate.h"
#include <stdio.h>
#include <ctype.h>
@@ -65,6 +66,8 @@
#define MBOX_OUTPUT_STATIC 0
#define MBOX_OUTPUT_AJAX 1
+#define MBOX_WRAP_TO 90
+
typedef struct mbox_dir_cfg {
int enabled;
int antispam;
@@ -130,6 +133,7 @@
void mbox_mime_display_xml_structure(request_rec *r, mbox_mime_message_t *m);
/* Utility functions */
+char *mbox_wrap_text(char *str);
char *get_base_path(request_rec *r);
char *get_base_uri(request_rec *r);
Modified: httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_cte.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_cte.c?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_cte.c (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_cte.c Fri Aug 26 14:33:07 2005
@@ -254,11 +254,17 @@
*
* These headers complies to the following syntax :
* =?charset?mode?data?= rest
+ *
+ * FIXME: does not support multiple blocks.
+ * possible mis-use of decoding functions.
*/
char *mbox_cte_decode_header(apr_pool_t *p, char *src)
{
+ apr_xlate_t *xlate;
apr_size_t len;
+
char *charset, *mode, *data, *rest;
+ int i;
/* Look for the end bound */
rest = strstr(src, "?=");
@@ -311,6 +317,34 @@
else if ((*mode == 'b') || (*mode == 'B')) {
len = mbox_cte_decode_b64(data);
data[len] = 0;
+ }
+
+ /* Convert charset to uppercase */
+ for (i=0; i<strlen(charset); i++) {
+ charset[i] = toupper(charset[i]);
+ }
+
+ /* Charset conversion */
+ if (apr_xlate_open(&xlate, "UTF-8", charset, p) == APR_SUCCESS) {
+ apr_size_t inbytes_left, outbytes_left;
+ apr_size_t outbuf_len = strlen(data);
+
+ char *new_data;
+
+ /* Allocate some memory for our resulting data, and initialize
+ counters. */
+ new_data = apr_palloc(p, outbuf_len);
+ inbytes_left = strlen(data);
+ outbytes_left = strlen(data);
+
+ /* Convert */
+ // apr_xlate_conv_buffer(xlate, data, &inbytes_left,
+ // new_data, &outbytes_left);
+
+ // new_data[outbuf_len - outbytes_left] = 0;
+ // data = new_data;
+
+ apr_xlate_close(xlate);
}
return apr_psprintf(p, "%s%s", data, rest);
Modified: httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_file.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_file.c?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_file.c (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_file.c Fri Aug 26 14:33:07 2005
@@ -164,6 +164,8 @@
char **context = apr_palloc(r->pool, 4*sizeof(char *));
+ memset(context, 0, 4*sizeof(char *));
+
/* First, set the MBOX_PREV and MBOX_NEXT IDs */
head = mbox_load_index(r, f, NULL);
head = mbox_sort_list(head, MBOX_SORT_DATE);
Modified: httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_index.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_index.c?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_index.c (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_index.c Fri Aug 26 14:33:07 2005
@@ -109,10 +109,10 @@
/* Open mbox cache */
rv = mbox_cache_get(&mli, r->filename, r->pool);
if (rv != APR_SUCCESS) {
- ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, rv, r,
"mod_mbox: Can't open directory cache '%s' for index",
r->filename);
- return HTTP_FORBIDDEN;
+ return DECLINED;
}
ap_set_content_type(r, "text/html; charset=utf-8");
@@ -144,7 +144,7 @@
ap_rputs(" </head>\n\n", r);
- ap_rputs(" <body onload=\"indexLinks ();\">\n", r);
+ ap_rputs(" <body id=\"archives\" onload=\"indexLinks ();\">\n", r);
ap_rputs(" <h1>Mailing list archives</h1>\n\n", r);
/* Output header and list information */
Modified: httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_mime.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_mime.c?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_mime.c (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_mime.c Fri Aug 26 14:33:07 2005
@@ -28,6 +28,13 @@
{
mbox_mime_message_t *mail;
char *tmp = NULL, *k = NULL, *end_bound = NULL;
+ char *headers_bound = NULL;
+
+ /* Locate the end of part headers */
+ headers_bound = strstr(body, "\n\n");
+ if (!headers_bound) {
+ return NULL;
+ }
/* If no Content-Type is provided, it means that we are parsing a
sub-part of the multipart message. The Content-Type header
@@ -46,7 +53,7 @@
/* Isolate the Content-Type string (between 'Content-Type: '
and ';' or end of line */
- if (k) {
+ if (k && k < headers_bound) {
*k = 0;
}
else {
@@ -66,7 +73,7 @@
/* If available, get MIME part name */
tmp = strstr(body, "name=\"");
- if (tmp) {
+ if (tmp && tmp < headers_bound) {
tmp += strlen("name=\"");
k = tmp;
@@ -87,9 +94,9 @@
/* Now we have a Content-Type. Look for other useful header information */
- /* Check Content-Disposition */
+ /* Check Content-Disposition if the match is within the headers */
tmp = strstr(body, "Content-Disposition: ");
- if (tmp) {
+ if (tmp && tmp < headers_bound) {
tmp += strlen("Content-Disposition: ");
k = tmp;
@@ -113,7 +120,7 @@
if (cte == CTE_NONE)
{
tmp = strstr(body, "Content-Transfer-Encoding: ");
- if (tmp) {
+ if (tmp && tmp < headers_bound) {
tmp += strlen("Content-Transfer-Encoding: ");
k = tmp;
@@ -235,7 +242,7 @@
}
/* Finally reset the end-body pointer. */
- *k = '\n';
+ // *tmp = '-';
}
/* If the parsed body is not multipart or is a MIME part, the body
@@ -264,11 +271,17 @@
char *new_body = NULL;
if (m->cte == CTE_BASE64) {
- m->body_len = mbox_cte_decode_b64(m->body);
+ new_body = apr_pstrndup(p, m->body, m->body_len);
+ m->body_len = mbox_cte_decode_b64(new_body);
+
+ m->body = new_body;
m->body[m->body_len] = 0;
}
else if (m->cte == CTE_QP) {
+ new_body = apr_pstrndup(p, m->body, m->body_len);
m->body_len = mbox_cte_decode_qp(m->body);
+
+ m->body = new_body;
m->body[m->body_len] = 0;
}
@@ -302,13 +315,13 @@
ap_rprintf(r, "<li><a href=\"%s\">", link);
if (m->content_name) {
- ap_rprintf(r, "%s</a>", m->content_name);
+ ap_rprintf(r, "%s", m->content_name);
}
else {
- ap_rprintf(r, "Unnamed %s</a>", m->content_type);
+ ap_rprintf(r, "Unnamed %s", m->content_type);
}
- ap_rprintf(r, " (%s, %s, %u bytes)</li>\n", m->content_disposition,
+ ap_rprintf(r, "</a> (%s, %s, %u bytes)</li>\n", m->content_disposition,
mbox_cte_to_char(m->cte), m->body_len);
if (!m->sub) {
@@ -318,7 +331,7 @@
for (i=0 ; i<m->sub_count ; i++) {
ap_rputs("<ul>\n", r);
mbox_mime_display_static_structure(r, m->sub[i],
- apr_psprintf(r->pool, "%s%d/", link, i));
+ apr_psprintf(r->pool, "%s/%d", link, i+1));
ap_rputs("</ul>\n", r);
}
}
@@ -347,9 +360,9 @@
return;
}
+ ap_rputs("<mime>\n", r);
for (i=0 ; i<m->sub_count ; i++) {
- ap_rputs("<mime>\n", r);
- mbox_mime_display_xml_structure(r, m->sub[i]);
- ap_rputs("</mime>\n", r);
+ mbox_mime_display_xml_structure(r, m->sub[i]);
}
+ ap_rputs("</mime>\n", r);
}
Modified: httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_out.c
URL: http://svn.apache.org/viewcvs/httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_out.c?rev=240348&r1=240347&r2=240348&view=diff
==============================================================================
--- httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_out.c (original)
+++ httpd/mod_mbox/branches/httpd-mbox-if/module-2.0/mod_mbox_out.c Fri Aug 26 14:33:07 2005
@@ -87,7 +87,7 @@
return APR_SUCCESS;
}
-/* Outputs an XML list of available mailboxes */
+/* Outputs a statix XHTML list of available mailboxes */
apr_status_t mbox_static_boxlist(request_rec *r)
{
apr_status_t rv = APR_SUCCESS;
@@ -290,17 +290,16 @@
from = email_antispam(from);
}
- ap_rputs(" <tr>\n", r);
-
/* Message author */
if (linked) {
+ ap_rprintf(r, " <tr id=\"%s\">\n", m->msgID);
ap_rprintf(r, " <td class=\"author\">%s</td>\n", from);
}
else {
+ ap_rputs(" <tr>\n", r);
ap_rputs(" <td class=\"author\"></td>\n", r);
}
-
/* Subject, linked or not */
ap_rputs(" <td class=\"subject\">", r);
for (i=0 ; i < depth ; i++) {
@@ -414,10 +413,7 @@
int count = 0; /* Message count */
int i = 0;
- char *baseURI;
-
conf = ap_get_module_config(r->per_dir_config, &mbox_module);
- baseURI = get_base_uri(r);
/* Fetch page number if present. Otherwise, assume page #1 */
if (r->args && strcmp(r->args, ""))
@@ -456,10 +452,8 @@
/* Send page header */
ap_rputs("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", r);
- ap_rprintf(r, "<index month=\"%.2s\" year=\"%.4s\" page=\"%d\" pages=\"%d\">\n",
- baseURI + (strlen(baseURI) - strlen(".mbox") - 2),
- baseURI + (strlen(baseURI) - strlen(".mbox") - 6),
- current_page + 1, pages);
+ ap_rprintf(r, "<index page=\"%d\" pages=\"%d\">\n",
+ current_page, pages);
/* For date and author sorts */
if (sortFlags != MBOX_SORT_THREAD) {
@@ -607,26 +601,41 @@
}
ap_rputs(" </head>\n\n", r);
- ap_rputs(" <body>\n", r);
-
- ap_rputs(" <h1>Mailing list archives</a></h1>\n\n", r);
+ ap_rputs(" <body id=\"archives\">\n", r);
- ap_rputs(" <table id=\"msglist\">\n", r);
- ap_rprintf(r, " <thead><tr><th class=\"title\">Message list : %s %.4s</th>",
+ ap_rprintf(r, " <h1>Mailing list archives: %s %.4s</a></h1>\n\n",
mbox_months[atoi(apr_pstrndup(r->pool, baseURI +
(strlen(baseURI) -
strlen(".mbox") - 2), 2)) - 1][1],
baseURI + (strlen(baseURI) - strlen(".mbox") - 6));
+ ap_rputs(" <table id=\"msglist\">\n", r);
+ ap_rputs(" <thead><tr><th class=\"title\">Message list</th>", r);
+
ap_rputs("<th class=\"pages\">", r);
mbox_static_msglist_page_selector(r, baseURI, pages, current_page);
ap_rputs("</th>", r);
- ap_rprintf(r, "<th class=\"sort\">"
- "<a href=\"%s/thread\">Thread</a> · "
- "<a href=\"%s/author\">Author</a> · "
- "<a href=\"%s/date\">Date</a></th></tr></thead>\n",
- baseURI, baseURI, baseURI);
+ ap_rputs("<th class=\"sort\">", r);
+ if (sortFlags == MBOX_SORT_THREAD) {
+ ap_rprintf(r, "Thread · "
+ "<a href=\"%s/author\">Author</a> · "
+ "<a href=\"%s/date\">Date</a>",
+ baseURI, baseURI);
+ }
+ else if (sortFlags == MBOX_SORT_AUTHOR) {
+ ap_rprintf(r, "<a href=\"%s/thread\">Thread</a> · "
+ "Author · "
+ "<a href=\"%s/date\">Date</a>",
+ baseURI, baseURI);
+ }
+ else {
+ ap_rprintf(r, "<a href=\"%s/thread\">Thread</a> · "
+ "<a href=\"%s/author\">Author</a> · "
+ "Date",
+ baseURI, baseURI);
+ }
+ ap_rputs("</th></tr></thead>\n", r);
ap_rputs(" <tbody>\n", r);
@@ -684,8 +693,10 @@
apr_status_t mbox_ajax_browser(request_rec *r)
{
mbox_dir_cfg_t *conf;
+ char *baseURI;
conf = ap_get_module_config(r->per_dir_config, &mbox_module);
+ baseURI = get_base_uri(r);
ap_set_content_type(r, "text/html; charset=utf-8");
@@ -711,7 +722,7 @@
ap_rputs(" </head>\n\n", r);
- ap_rputs(" <body onload=\"javascript:loadBrowser ();\">\n", r);
+ ap_rprintf(r, " <body id=\"archives\" onload=\"javascript:loadBrowser ('%s');\">\n", baseURI);
ap_rputs(" <h1>Mailing list archives</h1>\n\n", r);
/* Output a small notice if no MboxScriptPath configuration
@@ -766,6 +777,62 @@
return OK;
}
+void mbox_static_message_nav(request_rec *r, char **context,
+ char *baseURI, char *msgID)
+{
+ ap_rputs(" <th class=\"nav\">", r);
+
+ /* Date navigation */
+ if (context[0]) {
+ ap_rprintf(r, "<a href=\"%s/%s\" "
+ "title=\"Previous by date\">«</a>",
+ baseURI, context[0]);
+ }
+ else {
+ ap_rputs("«", r);
+ }
+
+ ap_rprintf(r, " <a href=\"%s/date#%s\" "
+ "title=\"View messages sorted by date\">Date</a> ",
+ baseURI, msgID);
+
+ if (context[1]) {
+ ap_rprintf(r, "<a href=\"%s/%s\" "
+ "title=\"Next by date\">»</a>",
+ baseURI, context[1]);
+ }
+ else {
+ ap_rputs("»", r);
+ }
+
+ ap_rputs(" · ", r);
+
+ /* Thread navigation */
+ if (context[2]) {
+ ap_rprintf(r, "<a href=\"%s/%s\" "
+ "title=\"Previous by thread\">«</a>",
+ baseURI, context[2]);
+ }
+ else {
+ ap_rputs("«", r);
+ }
+
+ ap_rprintf(r, " <a href=\"%s/thread#%s\" "
+ "title=\"View messages sorted by thread\">Thread</a> ",
+ baseURI, msgID);
+
+ if (context[3]) {
+ ap_rprintf(r, "<a href=\"%s/%s\" "
+ "title=\"Next by thread\">»</a>",
+ baseURI, context[3]);
+ }
+ else {
+ ap_rputs("»", r);
+ }
+
+ ap_rputs("</th>\n", r);
+}
+
/* Display a static XHTML mail */
apr_status_t mbox_static_message(request_rec *r, apr_file_t *f)
{
@@ -803,7 +870,7 @@
}
ap_rputs(" </head>\n\n", r);
- ap_rputs(" <body>\n", r);
+ ap_rputs(" <body id=\"archives\">\n", r);
ap_rputs(" <h1>Mailing list archives</h1>\n\n", r);
/* Display context message list */
@@ -813,66 +880,26 @@
from = email_antispam(from);
}
- ap_rputs(" <table id=\"msgview\">\n", r);
+ ap_rputs(" <table class=\"static\" id=\"msgview\">\n", r);
context = fetch_context_msgids(r, f, m->msgID);
- ap_rputs(" <thead>\n"
- " <tr>\n"
- " <th class=\"title\">Message view</th>\n"
- " <th class=\"nav\">", r);
-
- /* Date navigation */
- if (context[0]) {
- ap_rprintf(r, "<a href=\"%s/%s\" "
- "title=\"Previous by date\">«</a>",
- baseURI, context[0]);
- }
- else {
- ap_rputs("«", r);
- }
-
- ap_rprintf(r, " <a href=\"%s/date\" "
- "title=\"View messages sorted by date\">Date</a> ",
- baseURI);
-
- if (context[1]) {
- ap_rprintf(r, "<a href=\"%s/%s\" "
- "title=\"Next by date\">»</a>",
- baseURI, context[1]);
- }
- else {
- ap_rputs("»", r);
- }
- ap_rputs(" · ", r);
-
- /* Thread navigation */
- if (context[2]) {
- ap_rprintf(r, "<a href=\"%s/%s\" "
- "title=\"Previous by thread\">«</a>",
- baseURI, context[2]);
- }
- else {
- ap_rputs("«", r);
- }
-
- ap_rprintf(r, " <a href=\"%s/thread\" "
- "title=\"View messages sorted by thread\">Thread</a> ",
- baseURI);
-
- if (context[3]) {
- ap_rprintf(r, "<a href=\"%s/%s\" "
- "title=\"Next by thread\">»</a>",
- baseURI, context[3]);
- }
- else {
- ap_rputs("»", r);
- }
-
- ap_rputs("</th>\n"
- " </tr>\n"
+ /* Top navigation */
+ ap_rputs(" <thead>\n"
+ " <tr>\n"
+ " <th class=\"title\">Message view</th>\n", r);
+ mbox_static_message_nav(r, context, baseURI, m->msgID);
+ ap_rputs(" </tr>\n"
" </thead>\n\n", r);
+ /* Bottom navigation */
+ ap_rputs(" <tfoot>\n"
+ " <tr>\n"
+ " <th class=\"title\"><a href=\"#archives\">Top</a></th>\n", r);
+ mbox_static_message_nav(r, context, baseURI, m->msgID);
+ ap_rputs(" </tr>\n"
+ " </tfoot>\n\n", r);
+
/* Headers */
ap_rputs(" <tbody>\n", r);
ap_rprintf(r, " <tr class=\"from\">\n"
@@ -890,14 +917,9 @@
" <td class=\"right\">%s</td>\n"
" </tr>\n", ESCAPE_OR_BLANK(r->pool, m->str_date));
- ap_rprintf(r, " <tr class=\"raw\">\n"
- " <td class=\"left\"></td>\n"
- " <td class=\"right\"><a href=\"%s/raw?%s\">View raw message</a></td>\n"
- " </tr>\n", baseURI, URI_ESCAPE_OR_BLANK(r->pool, m->msgID));
-
/* Message body */
ap_rputs(" <tr class=\"contents\"><td colspan=\"2\"><pre>\n", r);
- ap_rprintf(r, "%s", mbox_mime_get_body(r->pool, m->mime_msg));
+ ap_rprintf(r, "%s", mbox_wrap_text(mbox_mime_get_body(r->pool, m->mime_msg)));
ap_rputs("</pre></td></tr>\n", r);
/* MIME structure */
@@ -905,9 +927,15 @@
" <td class=\"left\">Mime</td>\n"
" <td class=\"right\">\n<ul>\n", r);
mbox_mime_display_static_structure(r, m->mime_msg,
- apr_psprintf(r->pool, "%s/%s/",
+ apr_psprintf(r->pool, "%s/%s",
baseURI, m->msgID));
ap_rputs("</ul>\n</td>\n</tr>\n", r);
+
+ ap_rprintf(r, " <tr class=\"raw\">\n"
+ " <td class=\"left\"></td>\n"
+ " <td class=\"right\"><a href=\"%s/raw?%s\">View raw message</a></td>\n"
+ " </tr>\n", baseURI, URI_ESCAPE_OR_BLANK(r->pool, m->msgID));
+
ap_rputs(" </tbody>\n", r);
ap_rputs(" </table>\n", r);
@@ -944,7 +972,7 @@
ap_rprintf(r, "<mail id=\"%s\">\n"
" <from><![CDATA[%s]]></from>\n"
- " <subject>%s</subject>\n"
+ " <subject><![CDATA[%s]]></subject>\n"
" <date>%s</date>\n"
" <contents><![CDATA[",
URI_ESCAPE_OR_BLANK(r->pool, m->msgID),
@@ -952,7 +980,7 @@
ESCAPE_OR_BLANK(r->pool, m->subject),
ESCAPE_OR_BLANK(r->pool, m->str_date));
- ap_rprintf(r, "%s", mbox_mime_get_body(r->pool, m->mime_msg));
+ ap_rprintf(r, "%s", mbox_wrap_text(mbox_mime_get_body(r->pool, m->mime_msg)));
ap_rputs("]]></contents>\n", r);
ap_rputs(" <mime>\n", r);
mbox_mime_display_xml_structure(r, m->mime_msg);