<?php 

/**
 *	CloudFw Uploader Class
 *	
 *	@class CloudFw_Upload_Xhr
 *
 *	@since 1.0
 */
class CloudFw_Uploader {  

    function save($path) {
        if(!move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $path)){
            return false;
        }
        return $path;
    }
    function getName() {
        return $_FILES['uploadedfile']['name'];
    }
    function getSize() {
        return $_FILES['uploadedfile']['size'];
    }
    function getPathInfo() {
        return pathinfo($this->getName());
    }
    function detectMode(){
        //print_r ($_FILES['uploadedfile']);
        switch ( $_FILES['uploadedfile']['type'] ) {
            case 'application/octet-stream':
                return 'cfile';
            break;
            case 'application/zip':
            case 'application/x-zip-compressed':
            case 'application/s-compressed':
                return 'zip';
            default:
                return 'unknown';
            break;
        }
                 
    }

}

/**
 *	CloudFw Import/Export Class
 *	
 *	@class CloudFw_Import
 *
 *	@since 1.0
 *
 *	@param $args array
 *	@return NULL
 */
class CloudFw_Import {  
    private $allowedTypes = array();
    private $sizeLimit = 8388608;
    private $uploadFolder;
    private $zipFolder;
    private $mode;
    private $message;
    private $status = true;
    private $file;


    function __construct( array $args = array() ){
    
		extract(shortcode_atts(array(
			'allowedTypes'	=> array(),
			'sizeLimit'		=> NULL,
			'type'			=> '',
			'uploadFolder'	=> ''
		), $args));
    	                
        $this->allowedTypes =  array_map("strtolower", $allowedTypes);        
        $this->sizeLimit = $sizeLimit;
        $this->uploadFolder = $uploadFolder;
        $this->type = $type;      

    }

    function result(){

        $this->checkServerSettings();
        
        if ($this->status()) {
            
            if (isset($_FILES['uploadedfile'])) {
                $this->file = new CloudFw_Uploader();
            } else {
                $this->file = false; 
            }

            # Detect Mode
            $this->mode = $this->file->detectMode();

            if ($this->mode == 'zip')
                $this->uploadFolder = CLOUD_UPLOAD_DIR;
            elseif ($this->mode == 'cfile')
                $this->uploadFolder = CLOUD_UPLOAD_DIR;
            else 
                return $this->message(9021, false); // not valid file type

            return $this -> handleUpload();
        }
                
        return $this->getMessage();

    }

    /*
     *	Check Server Settings
     *
     *	@since 1.0
    **/
    private function checkServerSettings(){        
        $postSize = cloudfw_toBytes(ini_get('post_max_size'));
        $uploadSize = cloudfw_toBytes(ini_get('upload_max_filesize'));
        
        if ($postSize < $this->sizeLimit || $uploadSize < $this->sizeLimit){
            $size = max(1, $this->sizeLimit / 1024 / 1024) . 'M';
            $this->message(1024, false); // increase post_max_size and upload_max_filesize to $size

        }        
    }


    /*
     *	Handler
     *
     *	@since 1.0
    **/
    function handleUpload(){
    	$uploadDirectory = $this->uploadFolder;

        if (!is_writable($uploadDirectory))
            return $this->message(9009, false); // Server error. Upload directory isn't writable.
        
        if (!$this->file)
            return $this->message(9003, false); // please upload a file
        
        $size = $this->file->getSize();
        
        if ($size == 0) 
            return $this->message(9003, false); // please upload a file
        
        if ($size > $this->sizeLimit) 
            return $this->message(9007, false); // File is too large


        $pathinfo = pathinfo($this->file->getName());
        $filename = sanitize_file_name($pathinfo['filename']);
        $ext = $pathinfo['extension'];

        /*if($this->allowedTypes && !in_array(strtolower($ext), $this->allowedTypes)){
            $these = implode(', ', $this->allowedTypes);
            return array('error' => 'File type is invalid, it should be one of '. $these . '.');
        }*/
        
        /*if($replaceOldFile){
            /// don't overwrite previous files that were uploaded
            while (file_exists($uploadDirectory . $filename . '.' . $ext)) {
                $filename .= rand(10, 99);
            }
        }*/
        

        if ($this->status()) {
            
            if ($the_file = $this->file->save($uploadDirectory . $filename . '.' . $ext)){              
                $this->import($the_file, $filename);
                $this->delFile($uploadDirectory . $filename . '.' . $ext);

                if ( ! $this->status() )
                    $this->delFolder( $this->getZipFolder() );

                return $this->getMessage();

            } else 
                return $this->message(9008, false); // Could not save uploaded file. The upload was cancelled, or server error encountered



        } else {
            
            return $this->getMessage();

        }

        
    }


    /*
     *  Check Signature
     *
     *  @since 1.0
    **/
    function checkSignature($data){
        return $data['key'] === CLOUD_THEMEKEY;
    }
    
    /*
     *  Check Type
     *
     *  @since 1.0
    **/
    function checkType($data){
        return !empty($this->type) ? ($data['case'] == $this->type) : ($data['case'] == 'options');
    }
    

    /*
     *	Get File Content
     *
     *	@since 1.0
    **/
    private function getContent($the_file){
        if (empty($the_file) || !$the_file)
            return false;


		$fp = fopen($the_file, "r");
		while (!feof($fp))
			$the_content = fread($fp, 65536);
			 
		fclose($fp); 
		
		return $this->decodeContent($the_content);
    }

    /*
     *  Decode Contents
     *
     *  @since 1.0
    **/
    private function decodeContent($content){
        include_once(TMP_ADMIN_PATH.'/classes/JSON.php');
        $json = new Services_JSON(); 

        $decoded_options = @(base64_decode($content));
        $parse_all_options = @($json->decode($decoded_options));

       if ( $this->status() && ! $parse_all_options ) 
            $this->message(9005, false);
        

        if ($this->status()){
            if (!empty($parse_all_options))
                return objectToArray((array) $parse_all_options);
        }

        return $this->status();

    }

    /*
     *  Set FeedBack Message
     *
     *  @since 1.0
    **/
    function message($message, $status = 1){
        $this->message = $message;
        if (isset($status))
            $this->status = $status;

        return $this->message;
    }

    /*
     *  Get Message
     *
     *  @since 1.0
    **/
    function getMessage(){
        return $this->message;
    }

    /*
     *  Get Status
     *
     *  @since 1.0
    **/
    function status(){
        return $this->status;
    }


    /*
     *  Delete A File
     *
     *  @since 1.0
    **/
    private function delFile($the_file){
        return @unlink($the_file);    
    }

    /*
     *  Delete A Folder
     *
     *  @since 1.0
    **/
    private function delFolder($dir){
        if (!$dir)
            return false;

        if ($handle = @opendir($dir)) {
            $array = array();

            while (false !== ($file = @readdir($handle))) {
                if ($file != "." && $file != "..") {

                    if(@is_dir($dir.$file))
                    {
                        if(!@rmdir($dir.$file)) // Empty directory? Remove it
                        {
                        $this->delFolder($dir.$file.'/'); // Not empty? Delete the files inside it
                        }
                    }
                    else
                    {
                       @unlink($dir.$file);
                    }
                }
            }
            @closedir($handle);

            @rmdir($dir);
        }

    }

    /*
     *  Set Zip Folder
     *
     *  @since 1.0
    **/
    function getZipFolder(){
        return $this->zipFolder;
    }

    /*
     *  Get Message
     *
     *  @since 1.0
    **/
    function setZipFolder($folder){
        $this->zipFolder = $folder;
    }

    /*
     *  Extract Zip File
     *
     *  @since 1.0
    **/
    function extractZip($the_file, $to){


        $pathinfo = pathinfo($the_file);
        $filename = $pathinfo['filename'];

        $target = $to.$filename.'/';
    
        @mkdir($target);
        @chmod($target, 0777);

        if ( ! is__writable($target) === true )
             $this->message(9020, false); // the folder not writable


        if ($this->status()){

            if ( extractZip($the_file, $target) ) {
                $this->delFile($the_file);
                $this->setZipFolder($target);
                return $target;
            }
            else 
                $this->message(9019, false); // Php ZipArchive extension is not found

        }
    
        return $this->status();

    }


    /*
     *  Find Skin File In Folder
     *
     *  @since 1.0
    **/
    function findSkinFile($the_folder){

        if ($handle = @opendir($the_folder)) {
            while (false !== ($file = readdir($handle))) {
                if ($file != "." && $file != ".." && 
                    (
                     strpos($file, '.skin') !== false 
                    )
                ) {
                    $skin_files[] = $file;
                }
            }
            @closedir($handle);
        } 
        else
            $this->message(9018, false); // the folder cannot opened


        if ($this->status()){

            if ( !empty($skin_files) )
                return $skin_files; // .skin file found
            else 
                $this->message(9017, false); // no-found .skin file in the folder

        }
    
        return $this->status();

    }

    /*
     *  Find Slider File In Folder
     *
     *  @since 1.0
    **/
    function findSliderFile($the_folder){

        if ($handle = @opendir($the_folder)) {
            while (false !== ($file = readdir($handle))) {
                if ($file != "." && $file != ".." && 
                    (
                     strpos($file, '.slider') !== false 
                    )
                ) {
                    $skin_files[] = $file;
                }
            }
            @closedir($handle);
        } 
        else
            $this->message(9018, false); // the folder cannot opened


        if ($this->status()){

            if ( !empty($skin_files) )
                return $skin_files; // .skin file found
            else 
                $this->message(9022, false); // no-found .slider file in the folder

        }
    
        return $this->status();

    }



    /*
     *  Import
     *
     *  @since 1.0
    **/
    private function import($the_file, $filename){

        switch ($this->type) {
            case '':
            case 'options':

                return $this->importOptions($the_file);               

            break;
            case 'skin':


                if ($this->mode == 'zip') {
                    $zip_folder = $this->extractZip($the_file, TEMPLATEPATH.'/resources/skins/');
                    $zip_folder_relative = TMP_URL.'/resources/skins/'.sanitize_file_name($filename).'/';

                    if ($zip_folder) {
                        $the_skin_files = $this->findSkinFile($zip_folder);
                        
                        if ($the_skin_files)
                            $the_file = $zip_folder.$the_skin_files[0];

                    }                      
                    
                     $this->importSkin($the_file, $zip_folder_relative);

                } elseif ($this->mode == 'cfile'){

                     $this->importSkin($the_file);

                } else 
                    return $this->message(9004, false); // not compatible
               

            break;
            case 'slider':


                if ($this->mode == 'zip') {
                    $zip_folder = $this->extractZip($the_file, TEMPLATEPATH.'/resources/sliders/');
                    $zip_folder_relative = TMP_URL.'/resources/sliders/'.sanitize_file_name($filename).'/';

                    if ($zip_folder) {
                        $the_slider_files = $this->findSliderFile($zip_folder);
                        
                        if ($the_slider_files)
                            $the_file = $zip_folder.$the_slider_files[0];

                    }                      
                    
                     $this->importSlider($the_file, $zip_folder_relative);

                } elseif ($this->mode == 'cfile'){

                     $this->importSlider($the_file);

                } else 
                    return $this->message(9004, false); // not compatible
               

            break;

        }
    
    }


    /*
     *  Import: Theme Options
     *
     *  @since 1.0
    **/
    function importOptions($the_file){
        /*
            Check whether the file is exists
        **/

        if($the_file && file_exists($the_file))
            $data = $this->getContent($the_file);
        else{
            if ( ! $this->getMessage() )
                $this->message(9005, false); // problem in the file
        }

        /*
            Check Signature
        **/
        if ( $this->status() ){
            
            if ($this->checkSignature($data) && $this->checkType($data)){
                //true
                    $data["data"] = cloudfw_exclude_options($data["data"], $data["server"], NULL, TRUE);
                    cloudfw_update_option( (array) $data["data"]);

                    $this->message(9002, true); /*success*/

            } else {
                
                $this->message(9006, false); // not compatible
            }

        }
    
    }


    /*
     *  Import: Skin
     *
     *  @since 1.0
    **/
    function importSkin($the_file, $the_folder = ''){
        /*
            Check whether the file is exists
        **/
        if($the_file && file_exists($the_file))
            $data = $this->getContent($the_file);
        else{
            if ( ! $this->getMessage() )
                $this->message(9005, false); // problem in the file
        }

        /*
            Check Signature
        **/
        if ( $this->status() ){
            
            if ($this->checkSignature($data) && $this->checkType($data)){
                //true

                foreach( $data["data"] as $skin_id => $skin ) {
                        
                    if (!is_array($skin)) 
                        continue;

                    if ( ! $the_folder )
                        $target_folder = TMP_URL . '/resources/skins/' .$skin['data']['custom']['foldername'] . '/';
                    else
                        $target_folder = $the_folder;
                    
                    
                    $success = true;
                    $skin = cloudfw_prepare_URI_for_import($skin, $target_folder);
                    $id = cloudfw_manage_skin_ID(NULL, 'add', $skin);

                }
                
                if ($success) 
                    $this->message(9011, true); /*success*/
                else
                    $this->message(9004, false); /*an error occured*/


            } else {
                
                $this->message(9006, false); // not compatible
            }

        }
    
    }

    /*
     *	Import: Slider
     *
     *	@since 1.0
    **/
    function importSlider($the_file, $the_folder = ''){
        /*
            Check whether the file is exists
        **/
        if($the_file && file_exists($the_file))
            $data = $this->getContent($the_file);
        else{
            if ( ! $this->getMessage() )
                $this->message(9005, false); // problem in the file
        }

        /*
            Check Signature
        **/
        if ( $this->status() ){
            
            if ($this->checkSignature($data) && $this->checkType($data)){
                //true

                foreach( $data["data"] as $slider_id => $slider  ) {
                        
                    if (!is_array($slider) || !is_array($slider["main"])) 
                        continue;
                    
                    $main_id = $slider_id;



                    if ( ! $the_folder )
                        $target_folder = TMP_URL . '/resources/sliders/' .$slider["main"]["foldername"]. '/';
                    else
                        $target_folder = $the_folder;
                    
                    
                    $success = true;
                    $slider['main'] = cloudfw_prepare_URI_for_import($slider['main'], $target_folder);
                    $slider['data'] = cloudfw_prepare_URI_for_import($slider['data'], $target_folder);

                    $main_id = cloudfw_create_slider($slider["main"]);                  
                    if (!empty($main_id)) 
                        update_option($main_id, $slider["data"]);

                }
                
                if ($success) 
                    $this->message(9016, true); /*success*/
                else
                    $this->message(9004, false); /*an error occured*/


            } else {
                
                $this->message(9006, false); // not compatible
            }

        }
 	
    }
      

}