<?php
/*
* Copyright (c) 2009-2010 ATMAIL. All rights reserved
* See http://atmail.com/license.php for license agreement
*/

/**
 * Migrate users from the IMAP server to user Maildirs on this server
 * Usage
 * php migrate-imap.php < list-of-users.csv
 *
 * Where list-of-users contains :
 * username,password,domain,mailserver,download-all-folders
 * ben,mypass,atmail.nl,mail.atmail.nl,0
 * Any number of users , each separated by a newline.
 *
 * The download-all-folders by default is zero; and will only download the users subscribed
 * messages via IMAP ( recommended ) Set download-all-folders to 1 to download all
 * folders on the remote IMAP server including unsubscribed folders
 *
 * -i will switch on interactive mode so that you can see more progress information on the migration
 */

function printError( $string )
{
	
	fwrite(STDOUT, "\033[1;31m" . $string . "\033[0;39m\n");
	
}   

function printSuccess( $string )
{
	
	fwrite(STDOUT, "\033[1;32m" . $string . "\033[0;39m\n");
	
}   

function printWarning( $string )
{
	
	fwrite(STDOUT, "\033[1;33m" . $string . "\033[0;39m\n");
	
}   


ini_set('memory_limit', "64M");
error_reporting(E_ALL & ~E_NOTICE);

// Do not allow access via web
if (isset($_SERVER['GATEWAY_INTERFACE']))
{
	header("Content-Type: text/html");

	print <<<EOF
<h1>Installation Script Error</h1>
<p>The migrate-imap-exchange-calendar.php script can only be run via the command-line. Please read
<a href='http://support.atmail.com/'>http://support.atmail.com/</a> for more information.
</p>
EOF;
	exit;
}


//Set up application env
require_once('bootloader.php');

//get admin cridentials for all these actions
$dbTables = new dbTables();
$dbAdapter = Zend_Registry::get('dbAdapter');
$adminInfo = $dbAdapter->select()
					   ->from($dbTables->AdminUsers)
					   ->where("UMasterAdmin = 1")
					   ->query()
					   ->fetchAll();
                       
$Username = $adminInfo[0]['Username'];

$api = new api( array('directApi' => 1, 'Username' => $Username) );

//process args
$args = array();
foreach($_SERVER['argv'] as $arg) 
{

	$arr = explode("=", $arg);
	$arr[0] = str_replace('--', '', $arr[0]);
	if( substr($arr[0], 0, 1) == '-' )
	{
		
		$arr[0] = substr($arr[0], 1);
		
	}
		
	if(empty($arr[1]))
	{
		
		$arr[1] = true;		
		
	}
	
	$args[$arr[0]] = $arr[1];
	
}

//foreach($args as $key => $value)
//	echo "$key => $value\n";
//die(  );

// Display the welcome message
$msg = <<<EOF
\033[1;32mWelcome to Atmail {$pref['version']} Exchange Calendar via IMAP Migration script\033[0;39m
----------------------------------

This script will accept a CSV file as input and batch migrate calendar data store in exchange IMAP accounts from a remote server to this server.

When requesting your input during the installation the default values are
presented within square brackets -- to choose the default value, hit "Enter"

EOF;
if ( isset($args['i']) )
{
	
	fwrite(STDOUT, $msg);
	
}


// Make sure we are running as root
$ps = shell_exec("ps aux | grep 'php .*migrate-imap-exchange-calendar.php'");

if (preg_match("/^(.+?)\s+.+?php .*?migrate-imap-exchange-calendar\.php/m", $ps, $m))
{
    if (trim($m[1]) != 'root')
        exit("\nThe migrate-imap-exchange-calendar.php must be run as root. Please su to root, and consult the migration details for further information.\n\n");
}
else
{

    fwrite(STDOUT, "\nCould not detect what user migrate-imap-exchange-calendar.php is running as. If you are not running the migration as root please do so.\n");

}

while( ( $line = fgetcsv(STDIN, 10000, ",") ) !== FALSE )
{

	//printSuccess("Processing\n" . print_r($line,1) );
	
	//TODO: ignore header/column heading lines
	// Skip blank lines
	if ( is_null($line[0]) || count($line) < 5 )
	{
	
		printError("Unable to find user record while processing current input\n" . print_r($line,1) );
		continue;
	
	}

    list($user, $pass, $domain, $imapserver, $allfolders) = array_map('trim', $line);
	migrateUserCalendarData( $user, $pass, $domain, $imapserver, $allfolders );
}

function migrateUserCalendarData( $user, $pass, $domain, $imapserver, $allfolders = true )
{
	
	global $api;
	
	printSuccess("Processing $user@$domain ( $imapserver ) ...");
	
	if( !isset($imapserver) || $imapserver == '' || $imapserver == null || strlen($imapserver) < 1 || strpos($imapserver, '(') !== false || strpos($imapserver, ':') !== false )
	{
		
		printError("Bad remote host name found while processing current input: " . $imapserver . '. SKIPPING.' );
		return;
		
	}
	                                
	                                
	if( !isset($domain) || $domain == '' || $domain == null || strlen($domain) < 1 || strpos($domain, '(') !== false || strpos($domain, ':') !== false )
	{
		
		printError("Bad email domain name found while processing current input: " . $domain . '. SKIPPING.' );
		return;
		
	}

	$localBaseDir = $userRecord['MailDir'];
	
	//try connect to remote server and user account
	//$remoteMailStoreConfig = array( 'user' =>  $user . '@' . $domain, 'host' => $imapserver, 'password' => $pass, 'protocol' => 'IMAP');
	$_remoteProtocol = null;
	unset( $_remoteProtocol );
    $_remoteProtocol = new Zend_Mail_Protocol_Imap();
    try
	{
	
		$_remoteProtocol->connect($imapserver, null, false);
	
	}
	catch( Exception $e ) 
	{
    
    	printError("Unable to connect to remote host while processing current input:" . $imapserver . ': ' . $e->getMessage() . ' SKIPPING.' );
		return;
    
	}
	
	try
	{
	
		$result = $_remoteProtocol->login($user . '@' . $domain, $pass);
		if( !$result )
		{
			
			throw new Exception("Unable to log in to remote mailbox with username $user@$domain ( $imapserver )");
			
		}
	    printSuccess("Logged in to remote mailbox with username $user@$domain ( $imapserver )");
	
	}
	catch( Exception $e ) 
	{
    
    	try
		{
			
			$result = $_remoteProtocol->login($user, $pass);
			if( !$result )
			{

				throw new Exception("Unable to log in to remote mailbox with username $user@$domain ( $imapserver )");

			}
			printSuccess("Logged in to remote mailbox with username $user ( $imapserver )");
			
		}
		catch( Exception $e )
		{
			
			printError('Unable to login to remote host while processing current account. SKIPPING.' );
			return;
			
		}

	}
	$remoteMailStore = new Zend_Mail_Storage_Imap($_remoteProtocol);
	
	$remoteFoldersObject = $remoteMailStore->getFolders();
	$Calendar_found = false;
		
	// go through each folder
	$remoteFolders = new RecursiveIteratorIterator( $remoteFoldersObject, RecursiveIteratorIterator::SELF_FIRST );
	
	foreach ($remoteFolders as $remoteLocalName => $remoteFolderObject) 
	{
	
		if( $remoteFolderObject->getGlobalName() != "Calendar")
		{
			
			continue;
			
		}
		
		$Calendar_found = true;

		$localFolderPath = '';
		printSuccess('Processing calendar folder ' . $remoteFolderObject->getGlobalName() );

		if (!$remoteFolderObject->isSelectable()) 
		{
			
			printError('Skipping un-selectable folder: ' . $remoteLocalName );
					
		}
		else
		{
			$remoteMailStore->selectFolder( $remoteFolderObject->getGlobalName() );
			$internalDates = $_remoteProtocol->fetch( 'INTERNALDATE', 1, INF);
			echo $remoteMailStore->countMessages() . " entries found\n"; 
			foreach ($remoteMailStore as $id => $message) 
			{	
				$rawMessage = $remoteMailStore->getRawHeader($id) . Zend_Mime::LINEEND . $remoteMailStore->getRawContent($id);

				list($junk, $vcard) = explode('BEGIN:VCALENDAR', $rawMessage);
				list($vcard, $junk) = explode('END:VCALENDAR', $vcard);
				$vcard = "BEGIN:VCALENDAR" . $vcard . "END:VCALENDAR";
				
				//ensure no multiline uid
				list($top, $bottom) = explode('UID:', $vcard);
				$multi_line_check = explode("\n", $bottom);
				$line_no = 0;
				while(strpos($multi_line_check[$line_no], ':') == FALSE)
				{
					
					$line_no ++;
					
				}
				
				$vcard = $top . "UID:" . $multi_line_check[0] . "\n";
				
				for($a=0; $a < $line_no; $a++)
				{
					
					unset($multi_line_check[$a]);
					
				}

				foreach($multi_line_check as $line)
				{
					
					$vcard .= $line . "\n";
					
				}
				
				file_put_contents("./temp_vcard", $vcard);
				system('php ' . APP_ROOT . 'utilities/calendar/insert_raw_ics.php ' . $user . '@' . $domain . ' ' . $pass . ' < ./temp_vcard');
				unlink('./temp_vcard');				
			}
			
		}
		echo "\n";
	}
	if( !$Calendar_found )
	{
			
		printError('Calendar folder not found.');
			
	}
	
	$remoteMailStore->close();
}