commit 8e0a1f6357238f9de4b064385317e0865be2f74e
parent be457efe87a88b1168c74437ea38d1ec50f0da97
Author: Jaromil <jaromil@dyne.org>
Date:   Wed, 23 Jul 2014 22:32:50 +0200
fixes to parse email date in publish function
Diffstat:
| M | build/build-gnu.sh |  |  | 148 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- | 
| A | src/parsedate.c |  |  | 104 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ | 
| M | src/zlibs/publish |  |  | 233 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ | 
3 files changed, 310 insertions(+), 175 deletions(-)
diff --git a/build/build-gnu.sh b/build/build-gnu.sh
@@ -17,75 +17,75 @@ target=all
 
 mkdir -p build/gnu
 
-{ test "$target" = "deps" } || { 
+{ test "$target" = "deps" } || {
     test "$target" = "all" } && {
     deps=()
     case $distro in
-	debian)
-	    print "Building on Debian"
-	    print "Checking software to install"
-	    which procmail  >/dev/null || deps+=(procmail)
-	    which fetchmail >/dev/null || deps+=(fetchmail)
-	    which msmtp     >/dev/null || deps+=(msmtp)
-	    which mutt      >/dev/null || deps+=(mutt)
-	    which mairix    >/dev/null || deps+=(mairix)
-	    which pinentry  >/dev/null || deps+=(pinentry-curses)
-	    which abook     >/dev/null || deps+=(abook)
-	    which wipe      >/dev/null || deps+=(wipe)
-
-	    print "Checking build dependencies"
-	    which gcc      >/dev/null || deps+=(gcc)
-	    which bison    >/dev/null || deps+=(bison)
-	    which flex     >/dev/null || deps+=(flex)
-	    which make     >/dev/null || deps+=(make)
-	    which autoconf >/dev/null || deps+=(autoconf)
-	    which automake >/dev/null || deps+=(automake)
-	    which sqlite3  >/dev/null || deps+=(sqlite3)
-#	    which gpgme-config || sudo apt-get install libgpgme11-dev
-	    
-	    { test -r /usr/share/doc/libgnome-keyring-dev/copyright } || {
-		deps+=(libglib2.0-dev libgnome-keyring-dev) }
-	    
-
-	    { test ${#deps} -gt 0 } && { 
-		print "Installing missing components"
-		sudo apt-get install ${=deps} }
-
-	    ;;
-	
-	fedora)
-	    
-	    print "Building on Fedora"
-	    print "Checking software to install..."
-	    which zsh || sudo yum install zsh
-	    which mutt || sudo yum install mutt
-	    which procmail || sudo yum install procmail
-	    which msmtp || sudo yum install msmtp
-	    which pinentry || sudo yum install pinentry
-	    which fetchmail || sudo yum install fetchmail
-	    which wipe || sudo yum install wipe
-	    which abook || sudo yum install abook
-	    
-	    print "Checking build dependencies"
-	    which gcc || sudo yum install gcc
-	    which bison || sudo yum install bison
-	    which flex || sudo yum install flex
-	    rpm -q glib2-devel || sudo yum install glib2-devel
-	    rpm -q libgnome-keyring-devel || sudo yum install libgnome-keyring-devel
-	    rpm -q bzip2-devel || sudo yum install bzip2-devel
-	    rpm -q zlib-devel || sudo yum install zlib-devel
-	    
-	    ;;
-	
-	*)
-	    print "Error: no distro recognized, build by hand."
-	    ;;
+    debian)
+        print "Building on Debian"
+        print "Checking software to install"
+        which procmail  >/dev/null || deps+=(procmail)
+        which fetchmail >/dev/null || deps+=(fetchmail)
+        which msmtp     >/dev/null || deps+=(msmtp)
+        which mutt      >/dev/null || deps+=(mutt)
+        which mairix    >/dev/null || deps+=(mairix)
+        which pinentry  >/dev/null || deps+=(pinentry-curses)
+        which abook     >/dev/null || deps+=(abook)
+        which wipe      >/dev/null || deps+=(wipe)
+
+        print "Checking build dependencies"
+        which gcc      >/dev/null || deps+=(gcc)
+        which bison    >/dev/null || deps+=(bison)
+        which flex     >/dev/null || deps+=(flex)
+        which make     >/dev/null || deps+=(make)
+        which autoconf >/dev/null || deps+=(autoconf)
+        which automake >/dev/null || deps+=(automake)
+        which sqlite3  >/dev/null || deps+=(sqlite3)
+#       which gpgme-config || sudo apt-get install libgpgme11-dev
+
+        { test -r /usr/share/doc/libgnome-keyring-dev/copyright } || {
+        deps+=(libglib2.0-dev libgnome-keyring-dev) }
+
+
+        { test ${#deps} -gt 0 } && {
+        print "Installing missing components"
+        sudo apt-get install ${=deps} }
+
+        ;;
+
+    fedora)
+
+        print "Building on Fedora"
+        print "Checking software to install..."
+        which zsh || sudo yum install zsh
+        which mutt || sudo yum install mutt
+        which procmail || sudo yum install procmail
+        which msmtp || sudo yum install msmtp
+        which pinentry || sudo yum install pinentry
+        which fetchmail || sudo yum install fetchmail
+        which wipe || sudo yum install wipe
+        which abook || sudo yum install abook
+
+        print "Checking build dependencies"
+        which gcc || sudo yum install gcc
+        which bison || sudo yum install bison
+        which flex || sudo yum install flex
+        rpm -q glib2-devel || sudo yum install glib2-devel
+        rpm -q libgnome-keyring-devel || sudo yum install libgnome-keyring-devel
+        rpm -q bzip2-devel || sudo yum install bzip2-devel
+        rpm -q zlib-devel || sudo yum install zlib-devel
+
+        ;;
+
+    *)
+        print "Error: no distro recognized, build by hand."
+        ;;
     esac
-    
+
     print "All dependencies installed"
 }
 
-{ test "$target" = "fetchaddr" } || { 
+{ test "$target" = "fetchaddr" } || {
     test "$target" = "all" } && {
     pushd src
     print -n "Compiling the address parser... "
@@ -100,15 +100,25 @@ mkdir -p build/gnu
 }
 
 { test "$target" = "dfasyn" } || {
-    test "$target" = "all" } && { 
+    test "$target" = "all" } && {
     print "Compiling the generator for deterministic finite state automata... "
     pushd src/dfasyn
     make
     popd
 }
 
+{ test "$target" = "parsedate" } || {
+    test "$target" = "all" } && {
+    print "Compiling the minimalistic RFC822 date re-formatter..."
+    pushd src
+    ${=cc} -o parsedate parsedate.c
+    popd
+    cp src/parsedate build/gnu/
+    print OK
+}
+
 { test "$target" = "fetchdate" } || {
-    test "$target" = "all" } && { 
+    test "$target" = "all" } && {
     print "Compiling the date parser... "
     pushd src
     # then the C files made by dfasyn
@@ -122,21 +132,21 @@ mkdir -p build/gnu
     cp src/fetchdate build/gnu/
     print OK
 }
-		
 
 
-{ test "$target" = "gnome-keyring" } || { 
+
+{ test "$target" = "gnome-keyring" } || {
     test "$target" = "all" } && {
     print "Compiling gnome-keyring"
     pushd src/gnome-keyring
     ${=cc} jaro-gnome-keyring.c -o jaro-gnome-keyring \
-	`pkg-config --cflags --libs glib-2.0 gnome-keyring-1`
+    `pkg-config --cflags --libs glib-2.0 gnome-keyring-1`
     popd
     cp src/gnome-keyring/jaro-gnome-keyring build/gnu/
 }
 
 # build mixmaster only if specified
-{ test "$target" = "mixmaster" } && { 
+{ test "$target" = "mixmaster" } && {
     print "Compiling Mixmaster (anonymous remailer)"
     pushd src/mixmaster-3.0/Src
     mixmaster_sources=(main menustats mix rem rem1 rem2 chain chain1 chain2 nym)
@@ -144,7 +154,7 @@ mkdir -p build/gnu
     mixmaster_sources+=(compress stats crypto random rndseed util buffers maildir parsedate.tab)
     bison parsedate.y
     for s in ${=mixmaster_sources}; do ${=cc} -c ${s}.c; done
-    ${=cc} -o mixmaster *.o -lssl 
+    ${=cc} -o mixmaster *.o -lssl
     popd
     cp src/mixmaster-3.0/Src/mixmaster build/gnu
 }
diff --git a/src/parsedate.c b/src/parsedate.c
@@ -0,0 +1,104 @@
+/* Jaro Mail
+ *
+ *  (C) Copyright 2014 Denis Roio <jaromil@dyne.org>
+ *      
+ * Minimalist date reformatted learned from Mairix and Mutt
+ *
+ * This source code is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Public License as published 
+ * by the Free Software Foundation; either version 3 of the License,
+ * or (at your option) any later version.
+ *
+ * This source code is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * Please refer to the GNU Public License for more details.
+ *
+ * You should have received a copy of the GNU Public License along with
+ * this source code; if not, write to:
+ * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+/* #include <sys/types.h> */
+/* #include <sys/stat.h> */
+
+time_t parse_rfc822_date(char *date_string)/*{{{*/
+{
+  struct tm tm;
+  char *s, *z;
+  /* Format [weekday ,] day-of-month month year hour:minute:second timezone.
+
+     Some of the ideas, sanity checks etc taken from parse.c in the mutt
+     sources, credit to Michael R. Elkins et al
+     */
+
+  s = date_string;
+  z = strchr(s, ',');
+  if (z) s = z + 1;
+  while (*s && isspace(*s)) s++;
+  /* Should now be looking at day number */
+  if (!isdigit(*s)) goto tough_cheese;
+  tm.tm_mday = atoi(s);
+  if (tm.tm_mday > 31) goto tough_cheese;
+
+  while (isdigit(*s)) s++;
+  while (*s && isspace(*s)) s++;
+  if (!*s) goto tough_cheese;
+  if      (!strncasecmp(s, "jan", 3)) tm.tm_mon =  0;
+  else if (!strncasecmp(s, "feb", 3)) tm.tm_mon =  1;
+  else if (!strncasecmp(s, "mar", 3)) tm.tm_mon =  2;
+  else if (!strncasecmp(s, "apr", 3)) tm.tm_mon =  3;
+  else if (!strncasecmp(s, "may", 3)) tm.tm_mon =  4;
+  else if (!strncasecmp(s, "jun", 3)) tm.tm_mon =  5;
+  else if (!strncasecmp(s, "jul", 3)) tm.tm_mon =  6;
+  else if (!strncasecmp(s, "aug", 3)) tm.tm_mon =  7;
+  else if (!strncasecmp(s, "sep", 3)) tm.tm_mon =  8;
+  else if (!strncasecmp(s, "oct", 3)) tm.tm_mon =  9;
+  else if (!strncasecmp(s, "nov", 3)) tm.tm_mon = 10;
+  else if (!strncasecmp(s, "dec", 3)) tm.tm_mon = 11;
+  else goto tough_cheese;
+
+  while (!isspace(*s)) s++;
+  while (*s && isspace(*s)) s++;
+  if (!isdigit(*s)) goto tough_cheese;
+  tm.tm_year = atoi(s);
+  if (tm.tm_year < 70) {
+    tm.tm_year += 100;
+  } else if (tm.tm_year >= 1900) {
+    tm.tm_year -= 1900;
+  }
+
+  while (isdigit(*s)) s++;
+  while (*s && isspace(*s)) s++;
+  if (!*s) goto tough_cheese;
+
+  /* Now looking at hms */
+  /* For now, forget this.  The searching will be vague enough that nearest day is good enough. */
+
+  tm.tm_hour = 0;
+  tm.tm_min = 0;
+  tm.tm_sec = 0;
+  tm.tm_isdst = 0;
+  return mktime(&tm);
+
+tough_cheese:
+  return (time_t) -1; /* default value */
+}
+
+int main(int argc, char **argv) {
+  time_t res;
+  if(argc<2) {
+    printf("usage: parsedate date_string_from_mail_header\n");
+    printf("returns date in seconds since the Epoch.\n");
+    exit(0); }
+  res = parse_rfc822_date(argv[1]);
+  if(res<0) exit(1);
+  //  printf("Date: %d (seconds since the Epoch)\n",res);
+  printf("%lld\n", (long long) res);
+  exit(0);
+}
diff --git a/src/zlibs/publish b/src/zlibs/publish
@@ -31,8 +31,8 @@ pubdb=""
 pubdb_create() {
     func "create PubDB"
     { test -r "$1" } && {
-	error "PubDBalready exists: $1"
-	return 1
+    error "PubDBalready exists: $1"
+    return 1
     }
     cat <<EOF | ${SQL} -batch "$1"
 CREATE TABLE published
@@ -44,8 +44,8 @@ CREATE TABLE published
 );
 EOF
     { test $? != 0 } && {
-	error "Error creating PubDB in $1"
-	return 1 }
+    error "Error creating PubDB in $1"
+    return 1 }
     # make sure is private
     chmod 600 "$1"
     chown $_uid:$_gid "$1"
@@ -69,11 +69,11 @@ pubdb_insert() {
     func "insert mail in pubdb: $_path"
     cat <<EOF | ${SQL} -batch "$pubdb"
 INSERT INTO published (uid, file, path, date)
-VALUES ("${uid}", "${_file}", "${_path}", "`pubdb_date`");
+VALUES ("${uid}", "${_file}", "${_path}", "`pubdb_date ${_path}`");
 EOF
     { test $? != 0 } && {
-	error "insert_mail: duplicate insert in $pubdb"
-	return 1
+    error "insert_mail: duplicate insert in $pubdb"
+    return 1
     }
     return 0
 }
@@ -83,14 +83,18 @@ pubdb_list() {
     cat <<EOF | ${SQL} -batch "$pubdb"
 .width 64 128
 SELECT path FROM published
-ORDER BY file DESC;
+ORDER BY date DESC;
 EOF
 }
 
 pubdb_getuid() {
     func "pubdb_getuid() $@"
+    # TODO: path should be file only, find through all maildir
     _path="$1"
-    { test -r "$_path" } || { error "path not found for getuid: $_path"; return 1 }
+    { test -r "$_path" } || {
+        error "path not found for getuid: $_path"
+        # TODO: remove from pubdb
+        return 1 }
     uid=`hdr "$_path" | awk '/^Message-ID:/ { gsub(/<|>|,/ , "" , $2); print $2 }'`
     uid="${(Q)uid%\\n*}" # trim
     { test "$uid" = "" } && { uid=`basename "$_path"` }
@@ -98,20 +102,38 @@ pubdb_getuid() {
 
 }
 
+# Takes an email file, parse headers and returns an RFC3339 formatted
+# date value that is suitable for both RSS and SQLITE use. Uses the
+# small C program parsedate for RFC822 parsing (borrowed from Mairix)
 pubdb_date() {
+    _path="$1"
+    { test -r "$_path" } || {
+        error "path not found for pubdb_date: $_path"
+        return 1 }
+    _datestring=`hdr "$_path" | awk '/^Date/ { print $0 }'`
+    func "pubdb_date parsed string: $_datestring"
+    _dateseconds=`${WORKDIR}/bin/parsedate "$_datestring"`
+    { test "$_dateseconds" = "-1" } && {
+        error "could not parse date: $_datestring"
+        return 1 }
+    func "pubdb_date parsed seconds: $_dateseconds"
+    _daterss=`date -d"@${_dateseconds}" --rfc-3339=seconds | sed 's/ /T/'`
+    print "${_daterss}"
+    return 0
+
     # ATOM spec wants a T where date puts a space
-    date --rfc-3339=seconds | sed 's/ /T/'
+    #    date --rfc-3339=seconds | sed 's/ /T/'
 }
 
 pubdb_update() {
     func "pubdb_update() $@"
     md="$1"
     { test "$md" = "" } && {
-	error "Pubdb_update: maildir not found: $md"
-	return 1 }
+    error "Pubdb_update: maildir not found: $md"
+    return 1 }
     { maildircheck "${md}" } || {
-	error "Pubdb_update: not a maildir: $md"
-	return 1 }
+    error "Pubdb_update: not a maildir: $md"
+    return 1 }
     pub="${md}/pub"; ${=mkdir} "$pub"
     pubdb="${md}/.pubdb"
     { test -r "$pubdb" } || { pubdb_create "$pubdb" }
@@ -120,13 +142,13 @@ pubdb_update() {
     mails=`${=find} "${md}/new" "${md}/cur" "${md}/tmp" -type f`
     notice "Publishing emails in $md"
     for m in ${(f)mails}; do
-	pubdb_getuid "$m"
-	u=`pubdb_lookup_uid "$uid"`
-	{ test "$u" = "" } && {
-	    # $u is a new message
-	    func "publish_rss: new message found with uid: $uid"
-	    pubdb_insert "$m"
-	}
+    pubdb_getuid "$m"
+    u=`pubdb_lookup_uid "$uid"`
+    { test "$u" = "" } && {
+        # $u is a new message
+        func "publish_rss: new message found with uid: $uid"
+        pubdb_insert "$m"
+    }
     done
     return 0
 }
@@ -150,68 +172,68 @@ pubdb_extract_body() {
     # check if it has already html
     _html=`mu extract "$_path" | awk '/text\/html/ {print $1; exit}'`
     { test "$_html" = "" } || {
-    	mu extract --overwrite --parts="$_html" "$_path"
-	# check if there is an html header to weed out
-	grep '<body>' "$_html".part > /dev/null
-	if [ $? = 0 ]; then
-	    awk '
+        mu extract --overwrite --parts="$_html" "$_path"
+    # check if there is an html header to weed out
+    grep '<body>' "$_html".part > /dev/null
+    if [ $? = 0 ]; then
+        awk '
 BEGIN { body=0 }
 /<body/ { body=1; next }
 /<\/body/ { body=0; next }
 { if(body==1) print $0 }' "$_html".part | iconv -c
-	else 
-	    cat "$_html".part | iconv -c
-	fi
-	rm "$_html".part
-	return 0 }
+    else
+        cat "$_html".part | iconv -c
+    fi
+    rm "$_html".part
+    return 0 }
 
     # use the first text/plain
     _text=`mu extract "$_path" | awk '/text\/plain/ {print $1; exit}'`
     { test "$_text" = "" } || {
-	mu extract --overwrite --parts="$_text" "$_path"
-	# here we tweak the origin to avoid headers in markdown
-	# preferring to interpret # as inline preformat
-	cat "$_text".part | sed '
+    mu extract --overwrite --parts="$_text" "$_path"
+    # here we tweak the origin to avoid headers in markdown
+    # preferring to interpret # as inline preformat
+    cat "$_text".part | sed '
 s/^#/    /g
-' | iconv -c | maruku --html-frag | sed '
+' | iconv -c | maruku --html-frag 2>/dev/null | sed '
 s|http://[^ |<]*|<a href="&">&</a>|g
 s|https://[^ |<]*|<a href="&">&</a>|g'
 # s|www\.[^ |<]*|<a href="http://&">&</a>|g'
-	rm "$_text".part
-	return 0
+    rm "$_text".part
+    return 0
     }
 
     # check if its an html only mail
     # _html=`mu extract "$_path" | awk '/text\/html/ {print $1; exit}'`
     # { test "$_html" = "" } || {
-    # 	mu extract --overwrite --parts="$_html" "$_path"
-    # 	elinks -dump "$_html".part
-    # 	rm "$_html".part
-    # 	return 0 }
+    #   mu extract --overwrite --parts="$_html" "$_path"
+    #   elinks -dump "$_html".part
+    #   rm "$_html".part
+    #   return 0 }
 
     return 0
 }
-    
-    
+
+
 # iterate through the pubdb and publish an rss
 pubdb_render_maildir() {
     func "publish_render_maildir() $@"
     md="$1"
     { test "$md" = "" } && {
-	error "Publish_render_maildir: not found: $md"
-	return 1 }
+    error "Publish_render_maildir: not found: $md"
+    return 1 }
     { maildircheck "${md}" } || {
-	error "Publish_render_maildir: not a maildir: $md"
-	return 1 }
+    error "Publish_render_maildir: not a maildir: $md"
+    return 1 }
     { test -r "${md}/pub" } || {
-	error "Publish_render_maildir: webnomad not found in ${md}"
-	error "Initialize Webnomad inside the maildir that you want published."
-	return 1 }
+    error "Publish_render_maildir: webnomad not found in ${md}"
+    error "Initialize Webnomad inside the maildir that you want published."
+    return 1 }
 
     pub="${md}/pub"
     pubdb="${md}/.pubdb"
     { test -r "$pubdb" } || {
-	error "Publish_render_maildir: first run update_pubdb for $md"; return 1 }
+    error "Publish_render_maildir: first run update_pubdb for $md"; return 1 }
 
     ${=mkdir} $TMPDIR/pubdb
 
@@ -230,7 +252,7 @@ pubdb_render_maildir() {
 <link href="${WEB_ROOT}" />
 <id>${WEB_ROOT}/atom.xml</id>
 
-<updated>`pubdb_date`</updated>
+<updated>`date --rfc-3339=seconds | sed 's/ /T/'`</updated>
 <generator uri="http://www.dyne.org/software/jaro-mail/">JaroMail</generator>
 
 <subtitle type="html">${DESCRIPTION}</subtitle>
@@ -251,88 +273,88 @@ EOF
     c=0
     for m in ${(f)mails}; do
 
-	# fill in uid and upath
-	pubdb_getuid "$m"
+    # fill in uid and upath
+    pubdb_getuid "$m"
 
-	# but skip entries no more existing in maildir
-	{ test -r "$m" } || { continue }
-	# TODO: remove $m from database if not in maildir
+    # but skip entries no more existing in maildir
+    { test -r "$m" } || { continue }
+    # TODO: remove $m from database if not in maildir
 
-	_from=`awk '/^From: / {print $0; exit}' "$m" | sed 's/^From: //; s/ *<[^>]*> *//; s/"//g'`
-	_to=`awk '/^To: / {print $0; exit}' "$m" | sed 's/^To: //; s/ *<[^>]*> *//; s/"//g'`
+    _from=`awk '/^From: / {print $0; exit}' "$m" | sed 's/^From: //; s/ *<[^>]*> *//; s/"//g'`
+    _to=`awk '/^To: / {print $0; exit}' "$m" | sed 's/^To: //; s/ *<[^>]*> *//; s/"//g'`
 
-	if [[ "$_from" =~ "=?UTF-8" ]]; then
-	    _fname=`print "${_from%?=}" | sed 's/^=?UTF-8?B?//' | base64 -d`
-	else _fname="${_from}"; fi
+    if [[ "$_from" =~ "=?UTF-8" ]]; then
+        _fname=`print "${_from%?=}" | sed 's/^=?UTF-8?B?//' | base64 -d`
+    else _fname="${_from}"; fi
 
-	if [[ "$_to" =~ "=?UTF-8" ]]; then
-	    _tname=`print "${_to%?=}" | sed 's/^=?UTF-8?B?//' | base64 -d`
-	else _tname="${_to}"; fi
+    if [[ "$_to" =~ "=?UTF-8" ]]; then
+        _tname=`print "${_to%?=}" | sed 's/^=?UTF-8?B?//' | base64 -d`
+    else _tname="${_to}"; fi
 
 #	_from=`hdr "$m" | ${WORKDIR}/bin/fetchaddr -x From -a`
 #	_to=`hdr "$m" | ${WORKDIR}/bin/fetchaddr -x To -a`
 #	_fname=`print ${(Q)_from[(ws:,:)2]} | iconv -c`
 #       _tname=`print ${(Q)_to[(ws:,:)2]} | iconv -c`
-	func "From: ${_fname}"
-	_subject=`hdr "$m" | awk '
+    func "From: ${_fname}"
+    _subject=`hdr "$m" | awk '
 /^Subject:/ { for(i=2;i<=NF;i++) printf "%s ", $i; printf "\n" }
 ' | pubdb_escape_html`
-	_date=`hdr "$m" | awk '/^Date:/ { print $0 }'`
 
-	# fill in uid and upath
-	pubdb_getuid "$m"
+    # fill in uid and upath
+    pubdb_getuid "$m"
+
+    # fill in the body
+    _body=`pubdb_extract_body $m`
 
-	# fill in the body
-	_body=`pubdb_extract_body $m`
+    { test "$_body" = "" } && { error "Error rendering $m" }
 
-	{ test "$_body" = "" } && { error "Error rendering $m" }
-	
-	(( ++c ))
-	if (( $c < ${FEED_LIMIT:=30} )); then
-	    
-	    # write out the atom entry
-	    cat <<EOF >> "$pub"/atom.xml
+    (( ++c ))
+    if (( $c < ${FEED_LIMIT:=30} )); then
+
+        # write out the atom entry
+        cat <<EOF >> "$pub"/atom.xml
 
 <entry>
-	<title type="html" xml:lang="en-US">$_subject</title>
-	<link href="${WEB_ROOT}${upath}" />
-	<id>${WEB_ROOT}${upath}</id>
-	<updated>`pubdb_date`</updated>
+    <title type="html" xml:lang="en-US">$_subject</title>
+    <link href="${WEB_ROOT}${upath}" />
+    <id>${WEB_ROOT}${upath}</id>
+    <updated>`pubdb_date "$m"`</updated>
 <content type="html" xml:lang="en-US">
 `print ${(f)_body} | pubdb_escape_html`
 </content>
 <author>
-	<name>${_fname}</name>
-	<uri>${WEB_ROOT}${upath}</uri>
+    <name>${_fname}</name>
+    <uri>${WEB_ROOT}${upath}</uri>
 </author>
 <source>
-	<title type="html">${_subject}</title>
-	<subtitle type="html">From: ${_fname}</subtitle>
-        <updated>`pubdb_date`</updated>
-	<link rel="self" href="${WEB_ROOT}${upath}" />
-	<id>${WEB_ROOT}${upath}</id>
+    <title type="html">${_subject}</title>
+    <subtitle type="html">From: ${_fname}</subtitle>
+        <updated>${_daterss}</updated>
+    <link rel="self" href="${WEB_ROOT}${upath}" />
+    <id>${WEB_ROOT}${upath}</id>
 </source>
 </entry>
 
 EOF
-	    
-	fi # FEED LIMIT not reached
-	
-	#######
-	# now build an index and the sitemap
-	
-
-	# if using webnomad write out also the message page
-	{ test -d "${md}/views" } && {    
-	    cat <<EOF > "${md}/views/${upath}"
+
+    fi # FEED LIMIT not reached
+
+    #######
+    # now build an index and the sitemap
+
+
+    # if using webnomad write out also the message page
+    { test -d "${md}/views" } && {
+        _datestring=`hdr "$_path" | awk '/^Date/ { print $0 }'`
+        cat <<EOF > "${md}/views/${upath}"
 <h2>${_subject}</h2>
-<h4>From: ${_fname} - sent to ${_tname} - ${_date}</h4>
+<h4>From: ${_fname} - sent to ${_tname} - ${_datestring}</h4>
 
 ${_body}
 
 EOF
-	    # add entry in index
-	    cat <<EOF >> "${md}/views/index.html"
+        # add entry in index
+        cat <<EOF >> "${md}/views/index.html"
 
 <tr>
 <td style="vertical-align:middle;"><a href="${WEB_ROOT}${upath}">${_fname}</a></td>
@@ -342,7 +364,7 @@ EOF
 </tr>
 
 EOF
-	}
+    }
     done # loop is over
 
     cat <<EOF >> "${pub}/atom.xml"
@@ -354,4 +376,3 @@ EOF
 EOF
 
 }
-