#!/bin/sh
#
# Export a Kmail message store using IMAP
#
####
# Version 1.1
# Copyright (C) 2006 Graham R. Cobb
#               2010 Markus Kroetzsch
# This script is released under the GPL.
# 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 script 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.
# See http://www.gnu.org/licenses/ for a copy of the GPL license.
####
#
# This creates a directory tree for use with the dovecot IMAP server
# containing softlinks to appropriate folders in the Kmail directory.
# See http://korrekt.org/page/Migrating_Emails_from_KMail for a manual
# of how to do this. The script is supposed to run under most Unix-like
# environments, including Mac OS X 10.6.
#
# Note: maildir folders are exported to the target directory but mbox
# folders are exported to a separate .../mbox directory.  This is because
# dovecot cannot handle maildir and mbox in the same directory.
#
# Usage: imap-export <Kmail-root> <Dovecot-root>
#
# Note: if rebuilding the directory tree it may be easiest just to 
# completely remove the dovecot tree (e.g. with rm -rf ~/dovecot)
# before running this.  If not, you may want to set the "force"
# flag to "-f".
#
####

# Do we want to overwrite existing links?
#force="-f"
force=""

# This function calculates the mail folder containment 
# hierarchy corresponding to a Kmail on-disk directory
#
# $1 - directory filespec
# $2 - base directory
#
# The function outputs the hierarchy in the form
# /<folder>/subfolder/...
#
function get_hierarchy () {

    h=$1

    # Remove the base directory prefix
    if [[ $h == $2* ]]
    then
	l=${#2}
	h=${h:$l}
    fi
#    echo $h

    # Replace each occurence of /.<somefolder>.directory
    # with /<somefolder>
    re='(.*)/\.([^/]*)\.directory(.*)'
    while [[ $h =~ $re ]]
    do
#      echo $h analyses as ${BASH_REMATCH[1]} ${BASH_REMATCH[2]} ${BASH_REMATCH[3]}
      h=${BASH_REMATCH[1]}/${BASH_REMATCH[2]}${BASH_REMATCH[3]}
    done
    echo $h
}

#
# Argument handling
#
if [[ $# == 4 && "$1" == --recurse ]]
then
    # Recursive invocation: record subdir and calculate hierarchy
    subdir=$2
    kmailroot=$3
    imaproot=$4
    hierarchy=`get_hierarchy "$subdir" "$kmailroot"`
#    echo Subdir: $subdir Kmailroot: $kmailroot Imaproot: $imaproot Hierarchy: $hierarchy

elif [[ $# != 2 || -z "$1" || -z "$2" ]]
then
	echo "Wrong arguments($#):" $0 $*
	echo Usage: $0 "<Kmail-root>" "<Dovecot-root>"
	# Note the --recurse flag is for internal use only
	exit 2

else
    # User invocation
    kmailroot=$1
    subdir=$1
    imaproot=$2
    hierarchy=""
fi

mboxroot=$imaproot/mbox

#
# There are four types of files to worry about:
#
# 1) Maildir folders.  These are directories, which contain a cur/ directory,
# and are not of the form ".<something>.directory".
# They are linked into the appropriate place in the dovecot directory.
# Note that any dots are removed from these folder names (and any parent folders)
#
# 2) Mbox folders.  These are ordinary files, the name does not start with a dot,
# the contents start with "From".  They are linked into the dovecot mbox hierarchy.
#
# 3) Subfolders.  These are directories with names of the form ".<subfolder-name>.directory".
# They are recursed into.
#
# 4) Everything else is ignored.  This includes ordinary directories.
#
# There are some special cases:
#
# Any maildir called "inbox" will be renamed "real-inbox"
#

for f in "$subdir"/* "$subdir"/.*
do
#	echo $f

	fname=`basename "$f"`
	if [[ $fname == . || $fname == .. ]] ; then continue; fi

#	echo $fname

	# Is it a maildir directory?
	if [[ -d "$f" && -d "$f/cur" && $fname != .*.directory ]]
	then
	    echo Maildir folder $fname

	    # Special case "inbox"
	    if [[ $fname == inbox ]] ; then fname=real-inbox ; fi

	    # The directory hierarchy must be turned into a filename
	    # hierarchy...
	    # Remove any . from name
	    newname=${fname//./}
	    # Remove any . from hierarchy
	    h=${hierarchy//./}
	    # Replace / in hierarchy with . 
	    h=${h//\//.}

	    ln -s $force "$f" "$imaproot/$h.$newname"

	    # Maildir done

	# Is it mbox?
	elif [[ -f "$f" && -s "$f" && $fname != .*
		    && `head -c 4 "$f"` == From ]]
	then
	    echo Mbox folder $fname

	    # As mbox doesn't allow a folder to contain both messages
	    # and other folders at the same time, we modify the
	    # parent directory hierarchy so each containing folder name 
	    # ends with a dot.
	    # To do this we replace each / with ./ add an extra dot
	    # at the end and remove the unwanted dot at the start
	    h=${hierarchy//\//.\/}.
	    h=${h:1}

	    mkdir -p "$mboxroot$h"
	    ln -s $force "$f" "$mboxroot$h/$fname"

	    # Mbox done

	# Subfolder ?
	elif [[ -d "$f" && $fname == .*.directory ]]
	then
	    echo Subfolder $fname

	    # Remove leading dot
	    sub=${fname:1}
	    # Remove trailing .directory
	    sub=${sub%.directory}

	    # Recursively call script to handle the subdirectory
            echo "Recursively process subdirectories: $0 --recurse $f $kmailroot $imaproot\n"
	    $0 --recurse "$f" "$kmailroot" "$imaproot"

	else
:	    echo Ignored $fname
	fi
done

