#!/bin/sh # Convert a list archive into HTML. # # Copyright © 2014 Guilhem Moulin # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program 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. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . set -ue fail () { echo Error: "$@" >&2 exit 1 } [ $# -eq 1 ] || { echo "Usage: $0 listdir"; exit; } listdir="${1%/}" [ -d "$listdir" ] || fail "No such directory: $listdir" localpart="${listdir##*/}" domainpart="${listdir%/$localpart}" domainpart="${domainpart##*/}" # Determine the rotation period rotation= [ -s "$listdir/control/archiverotate" ] && read rotation <"$listdir/control/archiverotate" # Subdir format (/!\ shouldn't be empty, and shouldn't contain spaces!), # and archive date format. case "${rotation:-month}" in '') subdirf='/' listpage='./'; archivef=;; year) subdirf="%Y"; listpage='../'; archivef="for %Y";; month) subdirf="%Y/%m"; listpage='../../'; archivef="for %B %Y";; day) subdirf="%Y/%m/%d"; listpage='../../../'; archivef="for %a, %d %b %Y";; *) fail "$rotation: unknown rotation period" esac # Look up for the send date in an email. Fall back to the creation date # if not found. printDate () { local filename date while read filename; do if ! [ "$rotation" ]; then # don't bother looking for a date date=0 else # stop as soon as the header is over date=$(sed -nr '/^Date:\s*(\S.*)$/I {s//\1/p;q}; /^([^[:cntrl:][:space:]]+:|\s)/ !q' \ "$filename") [ "$date" ] || date=@$(stat -c '%Y' "$filename") fi echo $(date -d "$date" +"%s $subdirf") "$filename" done } # Process a (single) subdirectory process () { local list="$1" subdir="$2" date="$3" [ -s "$list" ] || return 0 [ -d "$listdir/webarchive/$subdir" ] || mkdir -p "$listdir/webarchive/$subdir" # TODO: add a line to the index file xargs -a"$list" mhonarc -definevar ListName="'$localpart'" \ -definevar ListPage="'${listpage}index.html'" \ -definevar DirDate="'$date'" \ -rcfile /etc/mhonarc.rc \ -add \ -quiet \ -outdir "$listdir/webarchive/$subdir" \ || exit 1 # empty the list echo -n >"$list" } # Process all found emails processM () { local cursubdir= date= local timestamp subdir filename while read timestamp subdir filename; do if [ "$cursubdir" != "$subdir" ]; then process "$list" "$cursubdir" "$date" cursubdir="$subdir" date="$(date -d "@$timestamp" +"$archivef")" fi echo "$filename" >>"$list" done process "$list" "$cursubdir" "$date" } # The span of emails we'll touch during the current instance now=$(date +'%s') list=$(mktemp) || exit 1 trap 'rm -f "$list"' EXIT from=0 if [ -s "$listdir/.webarchive.date" ]; then read from <"$listdir/.webarchive.date" from=$(( $from - 30 )) # remove 30s to fight race conditions fi find "$listdir/archive/" -type f -a -newermt @"$from" | printDate | sort -n -k1,1 | processM echo "$now" > "$listdir/.webarchive.date"