<?php
class Frontpage extends Module {
	protected $_filters = array(
        'check_admin' => '{index}{dologin}'
    );
    
    public function index() {
    	if(ACL::requireRoles(array('admin')))
    	{
    	    Content::redirect(Html::uriquery('frontpage', 'dashboard'));
    	}
    	$this->_layout = 'login';
    	$this->setVar('page_title', __('Administrator Login'));
    }
    
    public function dologin() {
        if (!RandMath::checkResult(ParamHolder::get('rand_rs'))) {
            $this->setVar('json', Toolkit::jsonERR(__('Sorry! Please have another try with the math!')));
            return '_result';
        }

        if (ACL::loginUser(ParamHolder::get('login_user', ''), 
            ParamHolder::get('login_pwd', ''))) {
            if (!ACL::requireRoles(array('admin'))) {
                $this->setVar('json', Toolkit::jsonERR(__('Username and password mismatch!')));
                return '_result';
            }
            $xml = new DOMDocument('1.0','utf-8');
			$xml->load('SitestarMaker/SitestarMaker.xml');
			$xml->getElementsByTagName('logoin')->item(0)->nodeValue = 'yes';
			$xml->save('SitestarMaker/SitestarMaker.xml');
            $this->setVar('json', Toolkit::jsonOK(array('forward' => Html::uriquery('frontpage', 'dashboard'))));
        } else {
            $this->setVar('json', Toolkit::jsonERR(__('Username and password mismatch!')));
        }
        
        
        return '_result';
    }
    
    public function dologout()
    {
    	$xml = new DOMDocument('1.0','utf-8');
		$xml->load('SitestarMaker/SitestarMaker.xml');
		$xml->getElementsByTagName('logoin')->item(0)->nodeValue = 'no';
		$xml->save('SitestarMaker/SitestarMaker.xml');
    	
        SessionHolder::destroy();
        Content::redirect('index.php');
    }
    
    public function dashboard() {
        $this->_layout = 'dashboard';
        $o_admin_short = new AdminShortcut();
        $shortcuts =& $o_admin_short->findAll(false, false, "ORDER BY `priority`");
        
        $this->assign('shortcuts', $shortcuts);
        
        $curr_locale = trim(SessionHolder::get('_LOCALE'));
        
        $o_article_category = new ArticleCategory();
        $cate_a_count = $o_article_category->count("id<>'1' AND s_locale=?", array($curr_locale));
        $o_article = new Article();
        $article_count = $o_article->count("s_locale=?", array($curr_locale));
        
        $o_prod_category = new ProductCategory();
        $cate_p_count = $o_prod_category->count("id<>'1' AND s_locale=?", array($curr_locale));
        $o_product = new Product();
        $prod_count = $o_product->count("s_locale=?", array($curr_locale));
        
        $this->assign('cate_a_count', $cate_a_count);
        $this->assign('article_count', $article_count);
        $this->assign('cate_p_count', $cate_p_count);
        $this->assign('prod_count', $prod_count);
    }
    
    /**
     * Auto upgrade 
     */
    public function auto_upgrade()
    {
    	/**
    	 * Remote download upgrade.zip
    	 */
		try {
		    /*$client = new SoapClient('http://upgrade.sitestar.cn/soapserver/upgrade.wsdl', 
				          array(
				              'soap_version' => SOAP_1_2,
				              'encoding' => 'UTF-8',
				              'cache_wsdl' => WSDL_CACHE_NONE
				          ));
		    
		    $tpl_info = unserialize($client->getUpgradeFile('upgrade.zip'));*/
		    $tpl_info = array(
		                	'archive' => 'upgrade.zip',
		        			'package_url' => 'http://upgrade.sitestar.cn/upgrade.zip'
		                );
		    /*if (!$tpl_info) {
		        $this->setVar('json', Toolkit::jsonERR(__('Remote request failed!')));
		    }*/
		    
		    // Check whether the target download dir is writable
		    if (!is_writable(ROOT)) {
		        $this->setVar('json', Toolkit::jsonERR(__('The wwwroot can\'t write!')));
		    }

			// Check whether there is a template with the same name
		    $folder_name = substr($tpl_info['archive'], 0, -strlen('.zip'));
		    if(file_exists(ROOT.DS.$folder_name)) {
		        $this->remove_file(ROOT.DS.$folder_name);
		    }
		    
		    // Try to download the file
		    $remote_file = fopen($tpl_info['package_url'], 'rb');
		    if (!$remote_file) {
		        $this->setVar('json', Toolkit::jsonERR(__('The remote file(s) can\'t read!')));
		    }
		    $local_file = fopen(ROOT.DS.$tpl_info['archive'], 'wb');
		    while (!feof($remote_file)) {
		        fwrite($local_file, 
		            fread($remote_file, 4096), 
		            4096);
		    }
		    fclose($local_file);
		    fclose($remote_file);
		    
		    // Download finished. Now extract.
		    if (filesize(ROOT.DS.$tpl_info['archive'])) {
		    	if(extension_loaded('zip'))
		    	{
			    	$tpl_zip = new ZipArchive(); 
				    $tpl_zip->open(ROOT.DS.$tpl_info['archive']); 
				    $tpl_zip->extractTo(ROOT.DS.$folder_name); 
				    $tpl_zip->close();
		    	}
		    	else
		    	{
				    include_once(P_LIB.'/zip.php');
				    if (!file_exists(ROOT.DS.$folder_name)) mkdir(ROOT.DS.$folder_name, 0755);
				    $tpl_zip = new zipper();
					$tpl_zip->ExtractTotally(ROOT.DS.$tpl_info['archive'], ROOT.DS.$folder_name);
		    	}
			    unlink(ROOT.DS.$tpl_info['archive']);
		    }
		} catch(SoapFault $fault) {
		    //echo "Error: ",$fault->faultcode,", string: ",$fault->faultstring;
		    $this->setVar('json', Toolkit::jsonERR($fault->faultstring));
		}
		
		/**
    	 * Update file(s)
    	 */
    	if (file_exists(ROOT.DS.'upgrade')) {
    		$this->update_file(ROOT.DS.'upgrade', 'upgrade/');
    	}
    	
    	/**
    	 * Update table(s)
    	 */
    	if (file_exists(ROOT.DS.'upgrade/basic.sql')) {
    		global $db;
    		$upgrade_sql = file_get_contents(ROOT.DS.'upgrade/basic.sql');
			$sql = <<<EOT
$upgrade_sql
EOT;
    		$this->dbupdate($sql, $db);
    	}
    	 
    	/**
    	 * Remove cache file(s)
    	 */
    	$this->remove_file(ROOT.DS.'cache', false);
    	
    	$this->setVar('json', Toolkit::jsonOK());
    	return '_result';
    }
    
    /**
     * delete file(s)
     */
    private function remove_file($dirname, $rm = true)
	{
		if(!is_dir($dirname))
	    {
	   		@unlink($dirname);
	        return false;
	    }
	    $handle = @opendir($dirname);
	    while(($file = @readdir($handle)) !== false)
	    {
	        if($file != '.' && $file != '..')
	        {
	            $dir = $dirname.'/'.$file;
	            is_dir($dir) ? $this->remove_file($dir) : @unlink($dir);
	        }
	    }
	    closedir($handle);
	    return $rm ? rmdir($dirname) : true;
	}
	
	/**
	 * update file(s)
	 */
	private function update_file($topath, $replace)
	{
		$files = sizeof(glob($topath.'/*')) ? glob($topath.'/*') : array();
		foreach ($files as $file) {
			if ((strtolower(substr(strrchr($file, '.'), 1)) == 'txt') 
			    || (strtolower(substr(strrchr($file, '.'), 1)) == 'sql') 
			    || ($file == $topath.'/index.php')) {
				continue;
			} else {
				$dest = str_replace($replace, '', $file);
				if (is_dir($file)) {
					if (!file_exists($dest)) mkdir($dest, 0755);
					$this->update_file($file, $replace);
				} else {
					// for (un)install
					if (in_array($file, array($topath.'/load.php',$topath.'/admin/load.php'))) {
						$local = file_get_contents($dest);
						preg_match("/define\(\'IS_INSTALL\'\,\s[1|0]\)/i", $local, $match);
						if ($match[0]) {
							$upgrade = file_get_contents($file);
							$newstr = preg_replace("/define\(\'IS_INSTALL\'\,\s[1|0]\)/i", $match[0], $upgrade);
							file_put_contents($file, $newstr);
						}
					}
					if (!copy($file, $dest)) {
						$this->setVar('json', Toolkit::jsonERR(__('Upate file(s) failed!')));
					}
				}
			}
		}
	}
	
	/**
	 * Update table(s)
	 */
    private function dbupdate($query, $db) 
	{
		$query = str_replace("\r", "\n", str_replace(' `es_', ' `'.Config::$tbl_prefix, $query));
		$expquery = explode(";\n", $query);

		foreach($expquery as $sql) {
			$sql = trim($sql);
			
			if($sql == '' || $sql[0] == '#') continue;

			if(strtoupper(substr($sql, 0, 12)) == 'CREATE TABLE') {
				$db->query($this->createtable($sql, Config::$mysqli_charset));
			} elseif (strtoupper(substr($sql, 0, 11)) == 'ALTER TABLE') {
				$this->runquery_altertable($sql, $db);
			} else {
				$db->query($sql);
			}
		}
	}

	private function createtable($sql, $dbcharset) 
	{
		$type = strtoupper(preg_replace("/^\s*CREATE TABLE\s+.+\s+\(.+?\).*(ENGINE|TYPE)\s*=\s*([a-z]+?).*$/isU", "\\2", $sql));
		$type = in_array($type, array('MYISAM', 'HEAP')) ? $type : 'MYISAM';
		return preg_replace("/^\s*(CREATE TABLE\s+.+\s+\(.+?\)).*$/isU", "\\1", $sql).
		($this->version() > '4.1' ? " ENGINE=$type default CHARSET=".$dbcharset : " TYPE=$type");
	}

	private function runquery_altertable($sql, $db) 
	{
		$tablepre = Config::$tbl_prefix;
		$dbcharset = Config::$mysqli_charset;

		$updatesqls = $this->parse_alter_table_sql($sql);

		foreach($updatesqls as $updatesql) {
			$successed = TRUE;

			if(is_array($updatesql) && !empty($updatesql[0])) {

				list($table, $action, $field, $sql) = $updatesql;

				if(empty($field) && !empty($sql)) {
					$query = "ALTER TABLE {$tablepre}{$table} ";
					if($action == 'INDEX') {
						$successed = $db->query("$query $sql", "SILENT");
					} elseif ($action == 'UPDATE') {
						$successed = $db->query("UPDATE {$tablepre}{$table} SET $sql", 'SILENT');
					}
				} elseif($tableinfo = $this->get_table_columns($tablepre.$table, $db)) {
					$fieldexist = isset($tableinfo[$field]) ? 1 : 0;

					$query = "ALTER TABLE {$tablepre}{$table} ";

					if($action == 'MODIFY') {
						$query .= $fieldexist ? "MODIFY $field $sql" : "ADD $field $sql";
						$successed = $db->query($query, 'SILENT');
					} elseif($action == 'CHANGE') {
						$field2 = trim(substr($sql, 0, strpos($sql, ' ')));
						$field2exist = isset($tableinfo[$field2]);

						if($fieldexist && ($field == $field2 || !$field2exist)) {
							$query .= "CHANGE $field $sql";
						} elseif($fieldexist && $field2exist) {
							$db->query("ALTER TABLE {$tablepre}{$table} DROP $field2", 'SILENT');
							$query .= "CHANGE $field $sql";
						} elseif(!$fieldexist && $fieldexist2) {
							$db->query("ALTER TABLE {$tablepre}{$table} DROP $field2", 'SILENT');
							$query .= "ADD $sql";
						} elseif(!$fieldexist && !$field2exist) {
							$query .= "ADD $sql";
						}
						$successed = $db->query($query);
					} elseif($action == 'ADD') {
						$query .= $fieldexist ? "CHANGE $field $field $sql" :  "ADD $field $sql";
						$successed = $db->query($query);
					} elseif($action == 'DROP') {
						if($fieldexist) {
							$successed = $db->query("$query DROP $field", "SILENT");
						}
						$successed = TRUE;
					}
				} else {
					$successed = 'TABLE NOT EXISTS';
				}
			}
		}
		return $successed;
	}

	private function parse_alter_table_sql($s) 
	{
		$arr = array();
		// \`\` - for upgrade basic.sql
		preg_match("/ALTER TABLE \`(\w+)\`/i", $s, $m);
		$tablename = substr($m[1], strlen(Config::$tbl_prefix));
		preg_match_all("/add column (\w+) ([^\n;]+)/is", $s, $add);
		preg_match_all("/drop column (\w+)([^\n;]*)/is", $s, $drop);
		preg_match_all("/change (\w+) ([^\n;]+)/is", $s, $change);
		preg_match_all("/add key ([^\n;]+)/is", $s, $keys);
		preg_match_all("/add unique ([^\n;]+)/is", $s, $uniques);
		foreach($add[1] as $k => $colname) {
			$attr = preg_replace("/(.+),$/", "\\1", trim($add[2][$k]));
			$arr[] = array($tablename, 'ADD', $colname, $attr);
		}
		foreach($drop[1] as $k => $colname) {
			$attr = preg_replace("/(.+),$/", "\\1", trim($drop[2][$k]));
			$arr[] = array($tablename, 'DROP', $colname, $attr);
		}
		foreach($change[1] as $k => $colname) {
			$attr = preg_replace("/(.+),$/", "\\1", trim($change[2][$k]));
			$arr[] = array($tablename, 'CHANGE', $colname, $attr);
		}
		foreach($keys[1] as $k => $colname) {
			$attr = preg_replace("/(.+),$/", "\\1", trim($keys[0][$k]));
			$arr[] = array($tablename, 'INDEX', '', $attr);
		}
		foreach($uniques[1] as $k => $colname) {
			$attr = preg_replace("/(.+),$/", "\\1", trim($uniques[0][$k]));
			$arr[] = array($tablename, 'INDEX', '', $attr);
		}
		return $arr;
	}

	private function get_table_columns($table, $db) 
	{
		$tablecolumns = array();
		
		if($this->version() > '4.1') {
			$query =& $db->query("SHOW FULL COLUMNS FROM $table");
		} else {
			$query =& $db->query("SHOW COLUMNS FROM $table");
		}
		
		while($field =& $query->fetchRow()) {
			$tablecolumns[$field['Field']] = $field;
		}
		return $tablecolumns;
	}
	
	/**
	 * MySQL version
	 */
	private function version() {
		global $db;
		return mysql_get_server_info();
	}
}
?>