<?php
function minimum_php_version( $vercheck )
{
  $minver = explode(".", $vercheck);
  $curver = explode(".", phpversion());
  if (($curver[0] < $minver[0])
     || (($curver[0] == $minver[0])
        && ($curver[1] < $minver[1]))
    || (($curver[0] == $minver[0]) && ($curver[1] == $minver[1])
       && ($curver[2][0] < $minver[2][0])))
       return false;
   else
       return true;
}

function VersionSort($a, $b)
{
	if( preg_match('/inportal_upgrade_v(.*).(php|sql)$/', $a, $rets) )
	{
		$a_version = $rets[1];
		$a_extension = $rets[2];
	}

	if( preg_match('/inportal_upgrade_v(.*).(php|sql)$/', $b, $rets) )
	{
		$b_version = $rets[1];
		$b_extension = $rets[2];
	}
	if( !isset($a_version) || !isset($b_version) ) return 0; // not php or sql file

	if($a_version == $b_version) // got PHP and SQL file for one version
	{
		if($a_extension == $b_extension)
		{
			return 0;
		}
		else
		{
			return ($a_extension == 'php') ? 1 : -1;
		}
	}
	else
	{
		return (ConvertVersion($a_version) < ConvertVersion($b_version)) ? -1 : 1;
	}
}

function GetMaxPortalVersion($admindirname)
{
	$dir = @dir($admindirname.'/install/upgrades');

	$upgrades_arr = Array();

	$version = '';
	while($file = $dir->read())
	{
		if ($file != "." && $file != ".." && !is_dir($admindirname.$file))
		{
			if (strstr($file, 'inportal_upgrade_v')) $upgrades_arr[] = $file;
		}
	}

	usort($upgrades_arr, "VersionSort");

	foreach($upgrades_arr as $file)
	{
		if( preg_match('/inportal_upgrade_v(.*).(php|sql)$/', $file, $rets) )
		{
			$a_version = $rets[1];

			if (ConvertVersion($a_version) > ConvertVersion($version)) {
				$version = $a_version;
			}
		}
	}

	return $version;
}

function ConvertVersion($version)
{
	$parts = explode('.', $version);

	$bin = '';
	foreach ($parts as $part) {
		$bin .= str_pad(decbin($part), 8, '0', STR_PAD_LEFT);
	}

	$dec = bindec($bin);

	return $dec;
}

function TableExists(&$ado, $tables)
{
    global $g_TablePrefix;

    $t = explode(",",$tables);

    $i = $ado->MetaTables();
    for($x=0;$x<count($i);$x++)
        $i[$x] = strtolower($i[$x]);

    $AllFound = TRUE;
    for($tIndex=0;$tIndex<count($t);$tIndex++)
    {
        $table = $g_TablePrefix.$t[$tIndex];
        $table = strtolower($table);
        if(!in_array($table,$i))
        {
            $AllFound = FALSE;
        }

    }
    return $AllFound;
}

function set_ini_value($section, $key, $newvalue)
{
   global $ini_vars;
   $ini_vars[$section][$key] = $newvalue;
}

function save_values()
{
	// Should write something to somwere, but it doesn't :(
  	global $ini_file,$ini_vars;

  	//if( file_exists($ini_file) )
  	//{
  		$fp = fopen($ini_file, "w");
  		fwrite($fp,'<'.'?'.'php die() ?'.">\n\n");
  		foreach($ini_vars as $secname => $section)
  		{
    		fwrite($fp,"[".$secname."]\n");
    		foreach($section as $key => $value) fwrite($fp,"$key = \"$value\"\n");
    		fwrite($fp,"\n");
  		}
  		fclose($fp);
	//}
}

function getConnectionInterface($action, $dbo_type='adodb')
{
	if($dbo_type == 'adodb')
	{
		switch($action)
		{
			case 'query': return 'Execute'; break;
			case 'errorno': return 'ErrorNo'; break;
			case 'errormsg': return 'ErrorMsg'; break;
		}
	}

	if($dbo_type == 'dbconnection')
	{
		switch($action)
		{
			case 'query': return 'Query'; break;
			case 'errorno': return 'getErrorCode'; break;
			case 'errormsg': return 'getErrorMsg'; break;
		}

	}
}

function RunSchemaFile(&$ado, $filename, $dbo_type='adodb')
{
	if( file_exists($filename) )
	{
		$sql = file_get_contents($filename);
		if($sql) RunSchemaText($ado,$sql,$dbo_type);
	}
}

function RunSchemaText(&$ado, $sql, $dbo_type='adodb')
{
    global $g_TablePrefix;

    if(strlen($g_TablePrefix))
    {
    	$what = "CREATE TABLE ";
    	$replace = "CREATE TABLE ".$g_TablePrefix;
    	$sql = ereg_replace($what, $replace, $sql);

    	$what = "DROP TABLE ";
    	$replace = "DROP TABLE IF EXISTS ".$g_TablePrefix;
    	$sql = ereg_replace($what, $replace, $sql);

    	$what = "INSERT INTO ";
    	$replace = "INSERT INTO ".$g_TablePrefix;
    	$sql = ereg_replace($what, $replace, $sql);

    	$what = "UPDATE ";
    	$replace = "UPDATE ".$g_TablePrefix;
    	$sql = ereg_replace($what, $replace, $sql);

    	$what = "ALTER TABLE ";
    	$replace = "ALTER TABLE ".$g_TablePrefix;
    	$sql = ereg_replace($what, $replace, $sql);
    }

    $commands = explode("# --------------------------------------------------------",$sql);
    if(count($commands)>0)
    {
    	$query_func = getConnectionInterface('query',$dbo_type);
    	$errorno_func = getConnectionInterface('errorno',$dbo_type);
    	$errormsg_func = getConnectionInterface('errormsg',$dbo_type);

    	for($i = 0; $i < count($commands); $i++)
    	{
    		$cmd = $commands[$i];
    		$cmd = trim($cmd);
    		if(strlen($cmd)>0)
    		{
    			$ado->$query_func($cmd);
    			if($ado->$errorno_func() != 0)
    			{
    				$db_error = $ado->$errormsg_func()." COMMAND:<PRE>$cmd</PRE>";
    			}
    		}
    	}
    }
}

function RunSQLText(&$ado, $allsql, $dbo_type='adodb')
{
	global $g_TablePrefix;

	$line = 0;
	$query_func = getConnectionInterface('query',$dbo_type);
	$errorno_func = getConnectionInterface('errorno',$dbo_type);
	$errormsg_func = getConnectionInterface('errormsg',$dbo_type);

	while($line<count($allsql))
	{
		$sql = $allsql[$line];
		if(strlen(trim($sql))>0 && substr($sql,0,1)!="#")
		{
			if(strlen($g_TablePrefix))
			{
				$what = "CREATE TABLE ";
				$replace = "CREATE TABLE ".$g_TablePrefix;
				$sql = ereg_replace($what, $replace, $sql);

				$what = "DELETE FROM ";
				$replace = "DELETE FROM ".$g_TablePrefix;
				$sql = ereg_replace($what, $replace, $sql);

				$what = "DROP TABLE ";
				$replace = "DROP TABLE IF EXISTS ".$g_TablePrefix;
				$sql = ereg_replace($what, $replace, $sql);

				$what = "DROP TABLE IF EXISTS ";
				$replace = "DROP TABLE IF EXISTS ".$g_TablePrefix;
				$sql = ereg_replace($what, $replace, $sql);

				$what = "INSERT INTO ";
				$replace = "INSERT INTO ".$g_TablePrefix;
				$sql = ereg_replace($what, $replace, $sql);

				$what = "UPDATE ";
				$replace = "UPDATE ".$g_TablePrefix;
				$sql = ereg_replace($what, $replace, $sql);

				$what = "ALTER TABLE ";
				$replace = "ALTER TABLE ".$g_TablePrefix;
				$sql = ereg_replace($what, $replace, $sql);
			}
			$sql = trim($sql);
			if(strlen($sql)>0)
			{
				$ado->$query_func($sql);
				if($ado->$errorno_func()!=0)
				{
					$db_error = $ado->$errormsg_func()." COMMAND:<PRE>$sql</PRE>";
					$error = TRUE;
				}
			}
		}
		$line++;
	}
}

function RunSQLFile(&$ado, $filename, $dbo_type='adodb')
{
    if(file_exists($filename))
    {
      $allsql = file($filename);
      RunSQLText($ado,$allsql,$dbo_type);
    }
}

function RunRestoreFile($ado,$filename,$FileOffset,$MaxLines)
{
  $size = filesize($filename);

  if($FileOffset > $size)
    return -2;

  $fp = fopen($filename,"r");
  if(!$fp)
  	return -1;

  if($FileOffset>0)
  {
	fseek($fp,$FileOffset);
  }
  else
  {
  	$EndOfSQL = FALSE;
  	$sql = "";
  	while(!feof($fp) && !$EndOfSQL)
  	{
  		$l = fgets($fp,16384);
  		if(substr($l,0,11)=="INSERT INTO")
  		{
  		  $EndOfSQL = TRUE;
  		}
  		else
  		{
  		  $sql .= $l;
  		  $FileOffset = ftell($fp) - strlen($l);
  		}
  	}
  	if(strlen($sql))
  	{
		RunSchemaText($ado,$sql);
  	}
  	fseek($fp,$FileOffset);
  }
  $LinesRead = 0;
  $sql = "";
  $AllSql = array();
  while($LinesRead < $MaxLines && !feof($fp))
  {
  	$sql = fgets($fp, 16384);
  	if(strlen($sql))
  	{
  		$AllSql[] = $sql;
  		$LinesRead++;
  	}
  }
  if(!feof($fp))
  {
  	$FileOffset = ftell($fp);
  }
  else
  {
    $FileOffset = $TotalSize;
  }
  fclose($fp);
  if(count($AllSql)>0)
    RunSQLText($ado,$AllSql);
  return (int)$FileOffset;
}


function _inst_keyED($txt,$encrypt_key)
{
 $encrypt_key = md5($encrypt_key);
 $ctr=0;
 $tmp = "";
 for ($i=0;$i<strlen($txt);$i++)
 {
     if ($ctr==strlen($encrypt_key)) $ctr=0;
        $tmp.= substr($txt,$i,1) ^ substr($encrypt_key,$ctr,1);
      $ctr++;
 }
 return $tmp;
}


function _inst_decrypt($txt,$key)
{
    $txt = _inst_keyED($txt,$key);
    $tmp = "";
    for ($i=0;$i<strlen($txt);$i++)
    {
        $md5 = substr($txt,$i,1);
        $i++;
        $tmp.= (substr($txt,$i,1) ^ $md5);
   }
   return $tmp;
}

function inst_LoadFromRemote()
{
    return "";
}

function mod_DLid()
{
    global $DownloadId;
    echo $DownloadId."\n";
    die();
}

function ae666b1b8279502f4c4b570f133d513e($LoadRemote=FALSE,$file="")
{
	return _inst_LoadLicense($LoadRemote,$file);
}

function _inst_LoadLicense($LoadRemote=FALSE,$file="")
{
    global $path,$admin;

    $data = Array();

    if(!strlen($file))
    {
      $f = $path.$admin."/include/inportal.dat";
    }
    else
        $f = $file;
    if(file_exists($f))
    {
        $contents = file($f);
        $data[0] = base64_decode($contents[1]);
        $data[1] = $contents[2];
    }
    else
        if($LoadRemote)
            return $LoadFromRemote;
   return $data;
}

function inst_SaveLicense($data)
{

}

function _inst_VerifyKey($domain,$k)
{
    $key = md5($domain);
    $lkey = substr($key,0,strlen($key)/2);
    $rkey = substr($key,strlen($key)/2);
    $r = $rkey.$lkey;
    if($k==$r)
        return TRUE;
    return FALSE;
}

function a83570933e44bc66b31dd7127cf3f23a($txt)
{
	return _inst_ParseLicense($txt);
}

function _inst_ParseLicense($txt)
{
  global $i_User, $i_Pswd, $i_Keys;
  $data = _inst_decrypt($txt,"beagle");
  $i_Keys = array();
  $lines = explode("\n",$data);

  for($x=0;$x<count($lines);$x++)
  {
      $l = $lines[$x];
      $p = explode("=",$l,2);
      switch($p[0])
      {
      case "Username":
          $i_User = $p[1];
      break;
      case "UserPass":
          $i_Pswd = $p[1];
      break;
      default:
        if(substr($p[0],0,3)=="key")
        {
            $parts = explode("|",$p[1]);
            if(_inst_VerifyKey($parts[0],$parts[1]))
            {
                unset($K);
                $k["domain"]=$parts[0];
                $k["key"]=$parts[1];
                $k["desc"]=$parts[2];
                $k["mod"]=$parts[3];
                $i_Keys[] = $k;
            }
        }
      break;
      }
  }
}


function de3ec1b7a142cccd0d51f03d24280744($domain)
{
	_inst_falseIsLocalSite($domain);
	return _inst_IsLocalSite($domain);
}

function _inst_GetObscureValue($i)
{
	if ($i == 'x') return 0254;
	if ($i == 'z') return 0x7F.'.';
	if ($i >= 5 && $i < 7) return _inst_GetObscureValue($z)*_inst_GetObscureValue('e');
	if ($i > 30) return Array(0x6c,0x6f,0x63,0x61,0x6c,0x68,0x6f,0x73,0x74);
	if ($i > 20) return 99;
	if ($i > 10) return '.'.(_inst_GetObscureValue(6.5)+1);
	if ($i == 'a') return 0xa;
}

function _inst_Chr($val)
{
	$x = _inst_GetObscureValue(25);
	$f = chr($x).chr($x+5).chr($x+15);
	return $f($val);
}

function _inst_IsLocalSite($domain)
{
    $ee = _inst_GetObscureValue(35);
		foreach ($ee as $e) {
			$yy .= _inst_Chr($e);
		}
    $localb = FALSE;
    if(substr($domain,0,3)==_inst_GetObscureValue('x'))
    {
        $b = substr($domain,0,6);
        $p = explode(".",$domain);
        $subnet = $p[1];
        if($p[1]>15 && $p[1]<32)
            $localb=TRUE;
    }
    $zz = _inst_GetObscureValue('z')._inst_GetObscureValue(5).'.'.(int)_inst_GetObscureValue(7)._inst_GetObscureValue(12);
    $ff = _inst_GetObscureValue('z')+65;
    $hh = $ff-0x18;
    if($domain==$yy || $domain==$zz || substr($domain,0,7)==$ff._inst_Chr(46).$hh ||
       substr($domain,0,3)==_inst_GetObscureValue('a')._inst_Chr(46) || $localb || strpos($domain,".")==0)
    {
        return TRUE;
    }
    return FALSE;
}

function _inst_falseIsLocalSite($domain)
{
    $localb = FALSE;
    if(substr($domain,0,3)=="172" || $domain == '##code##')
    {
        $b = substr($domain,0,6);
        $p = explode(".",$domain);
        $subnet = $p[1];
        if($p[1]>15 && $p[1]<32)
            $localb=TRUE;
    }
    if($domain=="localhost" || $domain=="127.0.0.1" || substr($domain,0,7)=="192.168" ||
       substr($domain,0,3)=="10." || $localb || strpos($domain,".")==0)
    {
        return TRUE;
    }
    return FALSE;
}

function ed592fe427e1ce60e32ffcb0c82d8557($name)
{
	return _inst_ModuleLicensed($name);
}

function _inst_ModuleLicensed($name)
{
    global $i_Keys, $objConfig, $g_License, $g_Domain;

    $lic = base64_decode($g_License);
    _inst_ParseLicense($lic);

    $modules = array();
    if(!_inst_IsLocalSite($g_Domain))
    {
        for($x=0;$x<count($i_Keys);$x++)
        {
            $key = $i_Keys[$x];
            if (strlen(stristr($g_Domain,$key["domain"])))
            {
                $modules = explode(",",strtolower($key["mod"]));
            }
        }
        if(in_array(strtolower($name),$modules))
		{
    		return TRUE;
		}
		else
 		{
	  		return FALSE;
		}
    }
    else
        return TRUE;

    return FALSE;
}

function inst_parse_portal_ini($file, $parse_section = false) {
    if(!file_exists($file) && !is_readable($file))
        die("Could Not Open Ini File $file");

    $contents = file($file);

    $retval = array();

    $section = '';
    $ln = 1;
    $resave = false;
    foreach($contents as $line) {
    		if ($ln == 1 && $line != '<'.'?'.'php die() ?'.">\n") {
    			$resave = true;
    		}
    		$ln++;
        $line = trim($line);
        $line = eregi_replace(';[.]*','',$line);
        if(strlen($line) > 0) {
            if(eregi('^[[a-z]+]$',str_replace(' ', '', $line))) {
                $section = substr($line,1,(strlen($line)-2));
                if ($parse_section) {
                	$retval[$section] = array();
                }
                continue;
            } elseif(eregi('=',$line)) {
                list($key,$val) = explode(' = ',$line);
                if (!$parse_section) {
                	$retval[trim($key)] = str_replace('"', '', $val);
                }
                else {
					$retval[$section][trim($key)] = str_replace('"', '', $val);
                }
            } //end if
        } //end if
    } //end foreach
    if ($resave) {
    	$fp = fopen($file, "w");
    	reset($contents);
			fwrite($fp,'<'.'?'.'php die() ?'.">\n\n");
			foreach($contents as $line) fwrite($fp,"$line");
			fclose($fp);
		}

    return $retval;
}

function a48d819089308a9aeb447e7248b2587f()
{
	return _inst_GetModuleList();
}

function _inst_GetModuleList()
{
	global $rootpath,$pathchar,$admin, $pathtoroot;

	$path = $pathtoroot;

	$new = array();
	if ($dir = @opendir($path))
	{
		while (($file = readdir($dir)) !== false)
		{
			if($file !="." && $file !=".." && substr($file,0,1)!="_")
			{
				if(is_dir($path."/".$file))
				{
					$ModuleAdminDir = $path.$file.'/admin/';
					$inst_file = $ModuleAdminDir.'install.php';
					if( file_exists($inst_file) && file_exists($ModuleAdminDir.'install/inportal_schema.sql') )
					{
						if(_inst_ModuleLicensed($file)) {
							$new[$file] = $inst_file;
						}
					}
				}
			}
		}
		closedir($dir);
	}
	return array_keys($new);
}

function GetDirList ($dirName)
{

    $filedates = array();
    $d = dir($dirName);

    while($entry = $d->read())
    {
        if ($entry != "." && $entry != "..")
        {
            if (!is_dir($dirName."/".$entry))
            {
                $filedate[]=$entry;
            }
        }
    }
    $d->close();
    return $filedate;
}

function GetLanguageList()
{
	global $pathtoroot, $admin;

	$packs = array();
	$dir = $pathtoroot.$admin."/install/langpacks";
	$files = GetDirList($dir);

	if(is_array($files))
	{
	  foreach($files as $f)
  	  {
		$p = pathinfo($f);
		if($p["extension"]=="lang")
		{
			$packs[] = $f;
		}
  	  }
	}
	return $packs;
}

function section_header($title, $return_result = false)
{
	$ret = '<table border="0" cellpadding="2" cellspacing="0" class="tableborder_full" width="100%" height="30">'.
		 '<tr><td class="tablenav" width="580" nowrap background="images/tabnav_left.jpg"><span class="tablenav_link">&nbsp;'.$title.'</span>'.
		 '</td><td align="right" class="tablenav" background="images/tabnav_back.jpg" width="100%">'.
		 "<a class=\"link\" onclick=\"ShowHelp('in-portal:install');\"><img src=\"images/blue_bar_help.gif\" border=\"0\"></A>".
		 '</td></tr></table>';
	if( $return_result )
		return $ret;
	else
		echo $ret;
}

function &VerifyDB($error_state, $next_state, $success_func = null, $db_must_exist = false)
{
	// perform various check type to database specified
	// 1. user is allowed to connect to database
	// 2. user has all types of permissions in database
    global $state, $db_error;

    // enshure we use data from post & not from config
  $GLOBALS['g_DBType'] = $_POST["ServerType"];
	$GLOBALS['g_DBHost'] = $_POST["ServerHost"];
	$GLOBALS['g_DBName'] = $_POST["ServerDB"];
	$GLOBALS['g_DBUser'] = $_POST["ServerUser"];
	$GLOBALS['g_DBUserPassword'] = $_POST["ServerPass"];

	if (strlen($_POST['TablePrefix']) > 7) {
		$db_error = 'Table prefix should not be longer than 7 characters';
		$state = $error_state;
		return false;
	}

    // connect to database
    $ado =& inst_GetADODBConnection();
    if($ado->ErrorNo() != 0)
    {
        // was error while connecting
        $db_error = "Connection Error: (".$ado->ErrorNo().") ".$ado->ErrorMsg();
        $state = $error_state;

    }
    elseif( $ado->ErrorNo() == 0 )
    {
        // if connected, then check if all sql statements work
        $test_result = 1;

        $sql_tests[] = 'DROP TABLE IF EXISTS test_table';
        $sql_tests[] = 'CREATE TABLE test_table(test_col mediumint(6))';
        $sql_tests[] = 'LOCK TABLES test_table WRITE';
        $sql_tests[] = 'INSERT INTO test_table(test_col) VALUES (5)';
        $sql_tests[] = 'UPDATE test_table SET test_col = 12';
        $sql_tests[] = 'UNLOCK TABLES';
        $sql_tests[] = 'ALTER TABLE test_table ADD COLUMN new_col varchar(10)';
        $sql_tests[] = 'SELECT * FROM test_table';
        $sql_tests[] = 'DELETE FROM test_table';
        $sql_tests[] = 'DROP TABLE IF EXISTS test_table';

        foreach($sql_tests as $sql_test)
        {
        	$ado->Execute($sql_test);
        	if( $ado->ErrorNo()!=0 )
        	{
        		$test_result = 0;
        		break;
        	}
        }

		if($test_result == 1)
		{
        	// if statements work & connection made, then check table existance
        	$db_exists = TableExists($ado,"ConfigurationAdmin,Category,Permissions");
        	if($db_exists != $db_must_exist)
        	{
        	    $state = $error_state;
        	    $db_error = $db_must_exist ? 'An In-Portal Database already exists at this location' : 'An In-Portal Database was not found at this location';
        	}
        	else
        	{
        	    $state = $next_state;
        	    if( isset($success_func) ) $success_func();
        	}
        }
        else
        {
        	 // user has insufficient permissions in database specified
        	 $db_error = "Permission Error: (".$ado->ErrorNo().") ".$ado->ErrorMsg();
        	 $state = $error_state;
        }
    }
    return $ado;
}

function SaveDBConfig()
{
	// save new database configuration
	set_ini_value("Database", "DBType",$_POST["ServerType"]);
	set_ini_value("Database", "DBHost",$_POST["ServerHost"]);
	set_ini_value("Database", "DBName",$_POST["ServerDB"]);
	set_ini_value("Database", "DBUser",$_POST["ServerUser"]);
	set_ini_value("Database", "DBUserPassword",$_POST["ServerPass"]);
	set_ini_value("Database","TablePrefix",$_POST["TablePrefix"]);
	save_values();
	$GLOBALS['include_file'] = 'install/install_finish.php';
}

function ReSetVar($var)
{
	// define varible if not defined before
	if( !isset($GLOBALS[$var]) ) $GLOBALS[$var] = '';
}

// if globals.php not yet included (1st steps of install),
// then define GetVar function
if( !function_exists('GetVar') )
{
	function GetVar($name, $post_priority = false)
	{
		if(!$post_priority) // follow gpc_order in php.ini
			return isset($_REQUEST[$name]) ? $_REQUEST[$name] : false;
		else	// get variable from post 1stly if not found then from get
			return isset($_POST[$name]) && $_POST[$name] ? $_POST[$name] : ( isset($_GET[$name]) && $_GET[$name] ? $_GET[$name] : false );
	}
}

function RadioChecked($name, $value)
{
	// return " checked" word in case if radio is checked
	$submit_value = GetVar($name);
	return $submit_value == $value ? ' checked' : '';
}

	function StripDisallowed($string, $item_info)
	{
		$not_allowed = Array(	' ', '\\', '/', ':', '*', '?', '"', '<', '>', '|',
		'~', '!', '@', '#', '$', '%', '^', '&', '(', ')',
		'+', '=', '-', '{', '}', ']', '[', "'", ';', '.', ',');

		$string = str_replace($not_allowed, '_', $string);
		$string = preg_replace('/(_+)/', '_', $string);
		$string = checkAutoFilename($string, $item_info);

		return $string;
	}

	function checkAutoFilename($filename, $item_info)
	{
		// 'table' => 'Category', 'id_field' => 'CategoryId', 'title_field' => 'Name'
		$item_id = $item_info['item_id'];
		$prefix = GetTablePrefix();
		$db =& inst_GetADODBConnection();

		$sql = 'SELECT '.$item_info['id_field'].' FROM '.$prefix.$item_info['table'].' WHERE Filename = '.$db->qstr($filename);
		$found_item_id = $db->GetOne($sql);
		$has_page = preg_match('/(.*)_([\d]+)([a-z]*)$/', $filename, $rets);
		if( ($found_item_id != $item_id) || $has_page ) // other category has same filename as ours OR we have filename, that ends with _number
		{
			$append = $found_item_id ? 'a' : '';
			if($has_page)
			{
				$filename = $rets[1].'_'.$rets[2];
				$append = $rets[3] ? $rets[3] : 'a';
			}

			$sql = 'SELECT '.$item_info['id_field'].' FROM '.$prefix.$item_info['table'].' WHERE (Filename = %s) AND ('.$item_info['id_field'].' != '.$item_id.')';
			while ( $db->GetOne( sprintf($sql, $db->qstr($filename.$append)) ) > 0 )
			{
				if (substr($append, -1) == 'z') $append .= 'a';
				$append = substr($append, 0, strlen($append) - 1) . chr( ord( substr($append, -1) ) + 1 );
			}

			return $filename.$append;
		}

		return $filename;
	}

	/**
	 * [INSTALL] Perform operations required for each module separate install (from admin)
	 *
	 * @param string $module_name
	 * @param bool $has_theme
	 * @return bool
	 */
	function finalizeModuleInstall($module_name, $has_theme = true)
	{
		global $objThemes;

		$app =& kApplication::Instance();
		if (!$app->GetVar('redirect')) return false;

		if ($has_theme)
		{
			$objThemes->CreateMissingThemes(true);
		}

		// 2. import languagepack in case of separate install
		$lang_xml =& $app->recallObject('LangXML');
		$lang_xml->tables['phrases'] = TABLE_PREFIX.'Phrase';
		$lang_xml->tables['emailmessages'] = TABLE_PREFIX.'EmailMessage';

		$lang_path = FULL_PATH.'/'.$module_name.'/admin/install/langpacks';
		$lang_xml->Parse($lang_path.'/english.lang', '|0|1|2|', '');

		$app->Redirect('', Array('pass' => 'all', 'admin' => 1, 'Refresh' => 1), '', 'modules/mod_status.php');

	}
	
	/**
	 * [UPGRADE] Initializes [cached] category/item templates with default values for each module
	 *
	 * @param string $module
	 * @param string $category_template
	 * @param string $item_template
	 */
	function updateItemCategoryTemplate($module, $category_template, $item_template)
	{
		$table_prefix = GetTablePrefix();
		$inst_ado =& inst_GetADODBConnection();
	
		// get module root category by module name
		$sql = 'SELECT RootCat
				FROM '.$table_prefix.'Modules
				WHERE Name = '.$inst_ado->qstr($module);
		$module_root = $inst_ado->GetOne($sql);
		
		// set category & item template to module root category
		$sql = 'UPDATE '.$table_prefix.'Category
				SET CategoryTemplate = '.$inst_ado->qstr($category_template).', ItemTemplate = '.$inst_ado->qstr($item_template).'
				WHERE CategoryId = '.$module_root;
		$inst_ado->Execute($sql);
		
		// set cached category & item templates to all sub-categories of module root category
		$sql = 'UPDATE '.$table_prefix.'Category
				SET CachedCategoryTemplate = '.$inst_ado->qstr($category_template).', CachedItemTemplate = '.$inst_ado->qstr($item_template).'
				WHERE ParentPath LIKE "|'.$module_root.'|%';
		$inst_ado->Execute($sql);
	}
	
	/**
	 * [UPGRADE] Moves custom field values for prefix specified from CustomMetaData table to prefix dependant separate table
	 *
	 * @param string $prefix
	 */
	function convertCustomFields($prefix)
	{
		$application =& kApplication::Instance();
		
		$ml_helper =& $application->recallObject('kMultiLanguageHelper');
		$ml_helper->createFields($prefix.'-cdata');
		
		$db =& $application->GetADODBConnection();
		
		$custom_fields = $application->getUnitOption($prefix, 'CustomFields');
		if (!$custom_fields) {
			return true;
		}
		
		$custom_table = $application->getUnitOption($prefix.'-cdata', 'TableName');
		
		// copy value from Value field to l<lang_id>_Value field, where destination field is empty
		$m_lang = $application->GetVar('m_lang');
		$sql = 'UPDATE '.TABLE_PREFIX.'CustomMetaData
				SET l'.$m_lang.'_Value = Value
				WHERE LENGTH(l'.$m_lang.'_Value) = 0';
		$db->Query($sql);
		
		$i = 1;
		$field_mask = '';
		$language_count = $ml_helper->getLanguageCount();
		while ($i <= $language_count) {
			$field_mask .= 'cdata%1$s.l'.$i.'_Value AS l'.$i.'_cust_%1$s, ';	
			$i++;
		}
		$field_mask = preg_replace('/(.*), $/', '\\1', $field_mask);
		
		$join_mask = 'LEFT JOIN '.TABLE_PREFIX.'CustomMetaData cdata%1$s ON main_table.ResourceId = cdata%1$s.ResourceId AND cdata%1$s.CustomFieldId = %1$s';
		
		$fields_sql = Array();
		$joins_sql = Array();
		foreach ($custom_fields as $custom_id => $custom_name) {
			array_push($fields_sql, sprintf($field_mask, $custom_id) );
			array_push($joins_sql, sprintf($join_mask, $custom_id));
		}
		
		$sql = 'INSERT INTO '.$custom_table.' 
				SELECT 0 AS CustomDataId, main_table.ResourceId, '.implode(', ', $fields_sql).'
				FROM '.$application->getUnitOption($prefix, 'TableName').' main_table '.implode(' ', $joins_sql);
		$db->Query($sql);
	}
?>