<?php
/*
* Copyright (c) 2009-2010 Atmail.
* See http://atmail.com/license.php for license agreement
* Author : Atmail
*/

// Lets give the script some ram and remove php time limit!
ini_set('memory_limit', -1);
set_time_limit(0);

function testExit(Exception $e)
{
	if(strstr($e->getMessage(),"Duplicate entry") == null)
	{
		echo $e;
		exit;
	}	
}

function showHelp($options)
{
	displayHelp($options);
	displayOptions($options);
}

function displayOptions($options)
{
	foreach($options as $option)
	{
		fwrite(STDOUT, "\t\t --" . $option[0] . " : " . $option[1] . " (default : " . $option[2] . ")\n");
	}
}

function loadDefaults($options)
{
	$arguments = array();
	// asign defaults
	foreach($options as $option)
	{
		$arguments[$option[0]] = $option[2];
		if($option[2] == 'false')
		{
			$arguments[$option[0]] = 0;
		}
		if($option[2] == 'true')
		{
			$arguments[$option[0]] = 1;
		}
	}
	
	return $arguments;
}

function str_to_nts($value) {
  return "$value\0";
}

function str_from_mem(&$value) {
  $i = strpos($value, "\0");
  if ($i === false) {
   return $value;
  }
  $result =  substr($value, 0, $i);
  return $result;
}

if(!function_exists('ftok'))
{
	function ftok($pathname, $proj_id)
	{
    	$st = @stat($pathname);
    	if (!$st)
		{
        	return -1;
    	}
   
    	$key = sprintf("%u", (($st['ino'] & 0xffff) | (($st['dev'] & 0xff) << 16) | (($proj_id & 0xff) << 24)));
    	return $key;
	}
}

function processOptions($argc, $argv, $options)
{
	
	if($argc == 1)
	{
		showHelp($options);
		exit;
	}
	
	$arguments = loadDefaults($options);
	
	for ($i = 1; $i < $argc; $i++)
	{
		$found = false;
		foreach($options as $option)
		{
			switch($argv[$i])
			{
				case "-v":
				case "--version":
					$found = true;
					echo  $argv[0]." v6.20.2\n";
					exit;
				break;
				case "--" . $option[0]:
					$found = true;
					if(isset($argv[$i+1]) && strpos($argv[$i+1], '--') === false)
					{
						$arguments[$option[0]] = $argv[++$i];
					}
					else
					{
						$arguments[$option[0]] = 1;
					}
					break;
				case "-?":
				case "-h":
				case "--help":
					$found = true;
					showHelp($options);
					exit;
				break;
			}
		}
		if(!$found)
		{
			fwrite(STDOUT, "Invalid option : " .  $argv[$i] ."\n");
			showHelp($options);
			exit;
		}
	}
	
	return $arguments;
}

function checkA5Schema($db)
{
	fwrite(STDOUT, "Checking old database version has the 5.6x schema version... ");

	try
	{
		$db->getConnection();
		$describe = $db->describeTable("Groups");
	}
	catch(Exception $e)
	{
		$describe = false;
	}
	if(!isset($describe['PushSupport']))
	{
		fwrite(STDOUT, "\n\n*WARNING* Could not detect old database has been upgraded to the 5.62 schema.\n");
		fwrite(STDOUT, "Please check you have run the a5-upgrade.php script correctly, and your old database\n");
		fwrite(STDOUT, "is at the required schema version to proceed with the Atmail 6 migration.\n");
		exit;
	}
	else
	{
		fwrite(STDOUT, "Ok.\n\n");
	}
}

function getTableCount($db, $tablename, $largeSchema = false, $notIncluding = NULL)
{
	$num = 0;
	$notstr='';
	if($notIncluding != NULL)
	{
		$notstr = " where " . $notIncluding . " not in (select Account from UserSession)";	
	}
	if($largeSchema && $tablename != 'Calander_other')
	{
		$temp_range = range('a', 'z');
		foreach($temp_range as $current_letter)
		{
			unset($stmt);
			$stmt = $db->query("select count(*) as total from " . $tablename . $current_letter . $notstr);
			$total_temp = $stmt->fetch();
			$num += $total_temp->total;
		}
	}
	else
	{
		unset($stmt);
		$stmt = $db->query("select count(*) as total from " . $tablename . $notstr);
		$total_temp = $stmt->fetch();
		$num = $total_temp->total;
	}
	
	return $num;
}

function isSchemaTypeLarge($db)
{
	try
	{
		$db->getConnection();
		$describe = $db->describeTable("UserSettings_aa");
		return true;
	}
	catch (Exception $e)
	{
		return false;
	}
}

function getSchemaRange($db, $min, $max, $other, $simple = false)
{
	// Which install type are we?
	if($simple)
	{
		$range = range($min, $max);
	}
	else
	{
		if(isSchemaTypeLarge($db))
		{
			$range = array();
			foreach(range($min, $max) as $a)
			{
				foreach(range('a', 'z') as $b)
				{
					$range[] = $a . $b;
				}
			}
		}
		else
		{
			// Normal DB schema
			$range = range($min, $max, $other);
		}
	}
	if($other)
	{
		$range[] = 'other';
	}
	
	return $range;
}

function user_search($users, $users_hashes, $username)
{
	$username = strtolower($username);
	$hash = md5($username);
	if(isset($users[$hash]))
	{
		return $users[$hash];
	}
	else
		return false;
}

function prune_user_search($users, $total)
{
	global $current_found_users;
	$current = count($users);
	if($current > $total)
	{
		return array_slice($users, $current - $total);
	}
	return $users;
}

$found_users = array(md5('global') => array('username' => 'global', 'password' => '', 'found' =>'true'), 
					md5('@global') => array('username' => '@global', 'password' => '', 'found' =>'true')
					);

function fetchUser($db, $entry_username)
{
	global $oldParams;
	global $pdoParams;
	global $found_users;
	global $found_users_hashes;
	global $arguments;
	$user_array = false;
	
	if(!($user_array = user_search($found_users, $found_users_hashes, $entry_username)))
	{
		$found = true;
		$ok = false;
		while(!$ok)
		{
			$ok = false;
			unset($stmt2);
			try
			{
				if(!isset($db))
				{
					throw new Exception();
				}
				
				$db->getConnection();
				$stmt2 = $db->query("select * from UserSession where Account = \"" . $entry_username ."\"");
				$ok = true;
			}
			catch(Exception $e)
			{
				fwrite(STDOUT, "\rHaving connection issues...");
				if(isset($db))
				{
					$db->closeConnection();
				}

				try
				{
					$db = null;
					$db = Zend_Db::Factory('Pdo_Mysql', $oldParams, $pdoParams);
					$db->getConnection();
					$stmt2 = $db->query("select * from UserSession where Account = \"" . $entry_username ."\"");
					$ok = true;
				}
				catch (Exception $e)
				{
					$ok = false;			
				}
				$db->getConnection();
				sleep(2);
			}
		}
		$password = '';
		if(!($row = $stmt2->fetch()))
		{
			$handle = fopen("./orphaned.entires", "a");
			fwrite($handle, "Unable to find user/pass " . $entry_username . " in UserSession\n");	
			fclose($handle);
			$found=false;
		}
		else
		{
			$password = $row->Password;
		}

		unset($row);
		unset($stmt2);
		
		$found_users[md5(strtolower($entry_username) . ':' . $found)] = $user_array = array('username'=> strtolower($entry_username), 'password' => $password, 'found' => $found);
	}

	$found_users = prune_user_search($found_users, $arguments['userCacheSize']);
	
	if(!$user_array['found'])
		return false;

	return $user_array;
}

?>
