<?php

/**
 * Import IMail email data into Atmail6
 *
 * @author Brad Kowalczyk
 */
 
require_once("../../nfc-bootloader.php");

$dir  = $_SERVER['argv'][1];

if (!$dir) {
	print "Usage: php migrate-msgs.php [directory of domains] [admin username]\n";
	exit;
}

require_once('application/models/api.php');
$_SERVER['PHP_AUTH_USER'] = $_SERVER['argv'][2];
$api = new api( array('directApi' => 1) );

$domList = $api->domainList();
$existingDomains = array();
foreach ($domList as $dom) {
    $existingDomains[] = $dom['DomainName'];    
}

$dh = opendir("$dir/") or die("Cannot opendir $dir/\n");

$newDomains = array();

while (false !== $d = readdir($dh)) {
    if (is_dir("$dir/$d") && $d != '.' && $d != '..') {
        $domains[] = $d;
    }
}

foreach ($domains as $domain) {

	if ($domain == "." || $domain == ".." || !in_array($domain, $existingDomains)) {
	   fwrite(STDOUT, "domain \"$domain\" does not exist on Atmail server, create first. Skipping all users under this domain.\n"); 
	   continue;
	}
	
	fwrite(STDOUT, "Migrating msgs for users from $domain...\n");
	if (is_dir("$dir/$domain/Users")) {
		$mydir = "$dir/$domain/Users";
	} elseif (is_dir("$dir/$domain/users")) {
		$mydir = "$dir/$domain/users";
	} else {
		fwrite(STDOUT, "No Users dir found, skipping\n");
		continue;
	}

	if (!$dh = opendir($mydir)) {
		fwrite(STDOUT, "Couldn't open users dir at $mydir, skipping\n");
		continue;
	}

	while (false !== $user = readdir($dh)) {
		if (!is_dir("$mydir/$user") || $user == '.' || $user == '..') {
			continue;
		}
		
		fwrite(STDOUT, "Migrating msgs from $mydir/$user\n");
		migrate_message($user, $domain, "$mydir/$user");
	}
}

if (strpos(strtoupper(PHP_OS), 'WIN') !== 0) {
    fwrite(STDOUT, "Changing permissions on /usr/local/atmail/users to atmail username\n");
    fwrite(STDOUT, "Please standby ...\n");
    system("chown -R atmail /usr/local/atmail/users");
}

// All Done
fwrite(STDOUT, "Congratulations. Email Data migration complete!\n");


// Function to migrate messages

function migrate_message($user, $domain, $dir, $sub='')
{
	global $dbAdapter;

	if (!$dh = opendir("$dir/$sub")) {
	    fwrite(STDOUT, "Cannot opendir $dir/$sub. Skipping $user@$domain\n");
	    return;
	}

	while (false !== $msgbox = readdir($dh)) {

        if ($msgbox == "." || $msgbox == "..")
            continue;

        // If we find a user forward file, forward the users mail as expected
        if (strpos($msgbox, '.ima') !== false) {
            $forward = trim(file_get_contents("$dir/$sub/$msgbox"));
        	fwrite(STDOUT, "Found users forward for $user@$domain => $forward\n");
        	$dbAdapter->query("INSERT INTO MailAliases (AliasName, AliasTo) VALUES(?, ?)", array("$user@$domain", $forward));
        	continue;
        } 

        if (is_dir("$dir/$sub/$msgbox")) {
        	fwrite(STDOUT, "Found subdirectory $dir/$sub/$msgbox ...\n");
        	migrate_message($user, $domain, "$dir/$sub", "$msgbox");
        	continue;
        }

		if (strpos($msgbox, '.mbx') === false)
		  continue;

		fwrite(STDOUT, "Reading $dir/$sub/$msgbox ...\n");

		// Open the users mailbox location
		if ($fh = fopen("$dir/$sub/$msgbox", 'r')) {

    		$folder = $msgbox;
    		$folder = str_replace('.mbx', '', $folder);
    		if (strtolower($msgbox) == 'main.mbx')
                $folder = "Inbox";
    		if (strtolower($msgbox) == 'deleted.mbx')
                $folder = "Trash" ;
    		if (strtolower($msgbox) == 'draft.mbx')
                $folder = "Drafts" ;

    		// Check the folder exists
    		if (strtolower($sub) != "inbox") {
                $folder = "$sub.$folder";
    		}

    		if ($folder == ".Inbox") $folder = "";

		if (!newMailDirFolder("$user@$domain", $folder)) {
    		    fwrite(STDOUT, "Could not create folder \"$folder\", skipping contents.");
    		    continue;    
    		}

    		while (false !== $line = fgets($fh)) {

    			if ($msg != '' && preg_match('/^From .*?\d{4}$/', trim($line), $m)) {

        			$cnt++;
        			fwrite(STDOUT, "Copying message $cnt - ");

        			// Change the date into something more readable
        			$dateepoch = strtotime($date);

        			$days = intval( (time() - $dateepoch) / 86400);
        			if (is_numeric($skip)) {
					    $diff = $days - $skip;
				    }

           			fwrite(STDOUT, "Message $days days old ...\n");
    
           			if ($skip && $days > $skip)	{
           				fwrite(STDOUT, "Message skipped - Days $days > $skip\n");
           			}
    
           			// Save the message into the database server - Folder Inbox
           			appendMessage("$user@$domain", $folder, $msg, "S", $dateepoch);
    
           			fwrite(STDOUT, " ...\n");
           			$head = 0;
    
           			// Reset the temp array for next msg
           			unset($msg);
    
    				continue;
    
                } else {

    				if (preg_match('/^Date: (.*?\d+:\d+:\d+\s+.*)/', $line, $m) && !$head) {
				        $date = $m[1];
    				}

    				$msg .= $line;

    				if (trim($line) == '') {
    				    $head++;
    				}
				
				    continue;
    			}
		    }
		
    		if ($msg) {
    			$cnt++;
    			$epoc = strtotime($date);
    	   		fwrite(STDOUT, "Migrating last message\n");
        			// Save the message into the database server - Folder Inbox
        			// Save the message date in EPOC for the file timestamp on disk
        			appendMessage("$user@$domain", $folder, $msg, "S", $epoc);
    		}
    
    		fwrite(STDOUT, "Migrated $cnt messages in $folder\n\n");
    
    		fclose($fh);
    	} else {
            frwite(STDOUT, "Cannot open $dir/$msgbox\n");
        }
    }

	closedir($dh);
}


function newMailDirFolder($account, $folder)
{
	$path = getMailDirPath($account);
    
    if (!is_dir($path)) {
        return false;
    }
    
    if (is_dir("$path/$folder")) {
        return true;    
    }
    
    fwrite(STDOUT, "Creating MailDir folders for $account");
    if (mkdir("$path/$folder", 0700) &&
    mkdir("$path/$folder/new", 0700) &&
    mkdir("$path/$folder/tmp", 0700) &&
    mkdir("$path/$folder/cur", 0700)) {
        return true;    
    }
    
    return false;
}


function getMailDirPath($account)
{
	$a = substr($account, 0, 1);
	$b = substr($account, 1, 1);
	
	if (!preg_match("/[a-z]+/i", $a)) {
		$a = "other";
	}
	
	if (!preg_match("/[a-z]+/i", $b)) {
		$b = "other";
	}
	
    return "/usr/local/atmail/users/$a/$b/$account";
}

function appendMessage($account, $folder, $msg, $flag, $epoc)
{
    $path = getMailDirPath($account);
	$id = generateid_file("$path/$folder", $account);

	// Specify the maildir msg with Epoc time if supplied
   	if(!is_null($epoc) && $epoc > 0) {
   	   $id = preg_replace('/^\d+\./', "$epoc.", $id);
   	}

	// Append some IMAP flags if specified
	if ($flag)
		$id .= ":2,$flag";

	// First, write the message to the temporary directory
	$fh = fopen("$path/$folder/tmp/$id", 'w');
	if (!is_resource($fh)) {
		//echo "Cannot write to $this->MailDir/$folder/tmp/$id";
		return false;
	}

	// Format messages correctly with line-feeds, don't cause blank headers in Outlook
	$msg = str_replace("\r\n", "\n", $msg);

	fwrite($fh, $msg);
	fclose($fh);

	// Next, move the message into the 'new' directory
	if (!rename("$path/$folder/tmp/$id", "$path/$folder/new/$id")) {   
	    fwrite(STDOUT, "Cannot rename $path/$folder/tmp/$id to $path/$folder/new/$id");
	}

	// If Epoch defined, e.g from migration script, change the date modified on disk to reflect date of email
	// Otherwise some Outlook versions will not parse the date correctly on message summary
	if (!is_null($epoc) && $epoc > 0) {
       	// The modification time on disk must be the message date for some IMAP folders
       	touch("$path/$folder/new/$id", $epoc, $epoc);
    }

	return true;
}

function generateid_file($folder, $account)
{
	$id;
    $h = "H";
    $pid = "P" . getmypid();
    list(,$domain) = explode('@', $account);

    // Generate key
	for(;;) {
		$secs = time();

	    for ($i=0; $i<6; $i++)
	        $h .= intval(rand(0,9));

		$id = "$secs.$h$pid.$domain";

	    // Generate another key if it already exists
	    if (!file_exists("$folder/$id"))
			return $id;
	}
}
