<?php

class File extends UD {
	
	function __construct(){
		parent::__construct();
	
		// initialize Error Message
		$this->_initErrorMsg();
	}

	function saveRawPostData($a){
	 
	 		
		$pathItemObj = $this->checkPathAndGetPathElements($a[0]);
		
		parent::saveFileContent($pathItemObj->realPath, $GLOBALS['HTTP_RAW_POST_DATA']);
		
		Response::sendOKResponse((object) array("success"=>true));
		
	}
	
	function saveFileContent($d){
	 
		$pathItemObj = $this->checkPathAndGetPathElements($d->path);
		
		parent::saveFileContent($pathItemObj->realPath, $d->content);
		
		Response::sendOKResponse((object) array("success"=>true));
		
	}
	function getFileContent($d){
	 
		$pathItemObj = $this->checkPathAndGetPathElements($d->path);
	//	print_r($pathItemObj);
		
	/*	$fp = fopen($pathToFile,"r", true);
		$fileContent = fread($fp, filesize($pathItemObj->realPath));
		fclose($fp);*/
		
		$content = parent::getFileContent($pathItemObj->realPath);
		
	//	print_r(	$fileContent);
		Response::sendOKResponse($content);
		
	}

	function getFlashAsset($a){

		$fileObj = $this->checkPathAndGetPathElements($a[0]);
		$extension = $this->getExtension($fileObj->path);
		 
		$mimeArr = array(
							"gif" => "image/gif",
							"bmp" => "image/bmp",
							"png" => "image/png",
							"jpg" => "image/jpeg",
							"jpeg" => "image/jpeg",
							"swf" => "application/x-shockwave-flash",
							"mp3" => "audio/mpeg",
							"wav" => "audio/x-wav"
						);
	
		
		// >> added
		header("Pragma: public");
		header("Expires: 0");
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Cache-Control: public");
		header("Content-Description: File Transfer");
		header("Content-Transfer-Encoding: binary");
		// << added
	
		//	header('Content-Type: ' . $this->mime);
		header("Content-type: ".$mimeArr[$extension]);
		header("Content-Disposition: filename=".$this->getFileName($fileObj->realPath));


		header("Content-Length: ".filesize($fileObj->realPath));


		 
		 readfile($fileObj->realPath);
		 
		 flush();
		 
		 exit;
		 


		
	} 
	function getImage($a){
	 

		$fileObj = $this->checkPathAndGetPathElements($a[0]);
		 
		// >> added
		header("Pragma: public");
		header("Expires: 0");
		header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
		header("Cache-Control: public");
		header("Content-Description: File Transfer");
		header("Content-Transfer-Encoding: binary");
		// << added
	
		//	header('Content-Type: ' . $this->mime);
		header('Content-Disposition: attachment; filename="' . $this->getFileName($fileObj->realPath) . '"');
		//	header('Last-Modified: ' . date('D, d M Y H:i:s \G\M\T' , $this->data_mod));

		header("Content-Length: ".filesize($fileObj->realPath));

	
	
		 
		 readfile($fileObj->realPath);
		 
		 flush();
		 
		 exit;
	}
	
	function undoUpload($d){
	
		$retObj = (object) array();
		
		for($i=0;$i<count($d->files);$i++){
			$fileObj = $this->checkPathAndGetPathElements($d->files[$i]->path);
		 
		 	$itemObj = (object) array();	
		 	$itemObj->path = $d->files[$i]->path;
			$itemObj->recycleBinFileName2 = RecycleBin::getInstance()->add($d->files[$i]->path, "" , (RecycleBin::$OVERWRITE), Request::getApplicationName());
			if(empty($d->files[$i]->recycleBinFileName)){
				$itemObj->fileItem = $this->getFileInfo($fileObj->realPath, "m/d/Y H:i");
		 		$itemObj->success = $this->deleteFile($fileObj->realPath);
		 		$itemObj->removed = true;
		 	}
		 	else{
		 	 	$itemObj->recycleBinFileName = $d->files[$i]->recycleBinFileName;
		 	 	$itemObj->success = RecycleBin::getInstance()->restore($d->files[$i]->recycleBinFileName, $d->files[$i]->path, true);
				$itemObj->fileItem = $this->getFileInfo($fileObj->realPath, "m/d/Y H:i");
				$itemObj->removed = false;
		 	}
			$retObj->files[$i] = $itemObj;
		}
		
		Response::sendOKResponse($retObj);	
		
	}
	function redoUpload($d){
	
		$retObj = (object) array();
		
		for($i=0;$i<count($d->files);$i++){
			$fileObj = $this->checkPathAndGetPathElements($d->files[$i]->path);
		 
		 	$itemObj = (object) array();	
		 	$itemObj->path = $d->files[$i]->path;
			if(!empty($d->files[$i]->recycleBinFileName)){
			 	$itemObj->recycleBinFileName = RecycleBin::getInstance()->add($d->files[$i]->path, $d->files[$i]->recycleBinFileName , RecycleBin::$OVERWRITE, Request::getApplicationName());
		 		$itemObj->exist = true;
		 	}else{
		 		$itemObj->exist = false;
		 	}

		 	$itemObj->recycleBinFileName2 = $d->files[$i]->recycleBinFileName2;
		 	$itemObj->success = RecycleBin::getInstance()->restore($d->files[$i]->recycleBinFileName2, $d->files[$i]->path, true);
			$itemObj->fileItem = $this->getFileInfo($fileObj->realPath, "m/d/Y H:i");
		 	
			$retObj->files[$i] = $itemObj;
		}
		
		Response::sendOKResponse($retObj);	
		
	}
	function retriveFilesInfo($d){
		
		$filesPaths = $d->filesPaths;
	 
	 	$retObj = array();
		$items = Array();
		if(is_array($filesPaths)){
			for($i=0; $i<count($filesPaths); $i++){
			 	$itemObj = $this->checkPathAndGetPathElements($filesPaths[$i]);
			 	$item = (object) array();
			 	$item->path = $filesPaths[$i];
			 	$item->fileItem = $this->getFileInfo($itemObj->realPath, "m/d/Y H:i");
			 	$retObj[$i] = $item; 	
			}
		}
		
		Response::sendOKResponse($retObj);
			
	}
	function upload($a){
		
		$path = $a[0];
		$recycleBinFileName = $a[1];
		
		$itemObj = $this->checkPathAndGetPathElements($path);

		if(!empty($recycleBinFileName))
			RecycleBin::getInstance()->add($path, $recycleBinFileName , RecycleBin::$OVERWRITE, Request::getApplicationName());
			 
		if(isset($_FILES['Filedata']['tmp_name'])){
			move_uploaded_file($_FILES['Filedata']['tmp_name'], $itemObj->realPath);
  		}
  		
	}
	function uploadCheck($d){
	 	
		$items = $d->items;
	 
	 	$retObj = (object) array();
	 	$retObj->existAny = false;
		$itemsResponses = Array();
		for($i=0; $i<count($items); $i++){
		 	$itemObj = $this->checkPathAndGetPathElements($items[$i]->path);
		 	
			$itemResponse = (object) array();
			$itemResponse->exist = file_exists($itemObj->realPath);
			if($itemResponse->exist){
			 	$retObj->existAny  = true;
			  	if($d->useRecycleBin==true){
					$itemResponse->recycleBinFileName = RecycleBin::getInstance()->getRecycleBinFileName($itemObj->realPath);
				}
			}
			$itemsResponses[$i] = $itemResponse;
		}
	
		//if($retObj->existAny==true)
			$retObj->itemsResponses = $itemsResponses;
		
	 	Response::sendOKResponse($retObj);
	}
	
	function fileProperties($d, $output=true){
	 
		$fileObj = $this->checkPathAndGetPathElements($d->path);
	 	
	 	$dateFormat="l, F j, Y, g:m:i a";
	 	
	 	$F = $this->getFileInfo($fileObj->realPath, $dateFormat);
	 	
	 	if($F===false){
		 	$retObj = (object) array();
		 	$retObj->success = false;
		 	Response::sendOKResponse($retObj);
	 	}
	 		
	 		
	 	$_stats = stat($fileObj->realPath);
	 	$F->atime = date($dateFormat, $_stats['atime']);
		$F->mtime = date($dateFormat, $_stats['mtime']);
		$F->ctime = date($dateFormat, $_stats['ctime']);
		
		$F->path=$d->path;
		
		if($output==true)
			Response::sendOKResponse($F);
		else
			return $F;
	}
			
	function compressRedo($d){
		$this->compress($d);
	}
	function compressUndo($d){
		
		$retObj = (object) array();
		$retObj->pathTo = $d->toPath;
		$archiveItemObj = $this->checkPathAndGetPathElements($d->archivePath);
		if(!empty($d->recycleBinFileName)){
		 	$retObj->success = RecycleBin::getInstance()->restore($d->recycleBinFileName, $d->archivePath, true);
			$retObj->fileItem = $this->getFileInfo($archiveItemObj->realPath, "m/d/Y H:i");
			$retObj->exist=true;	
		}else{
		 	$retObj->fileItem = $this->getFileInfo($archiveItemObj->realPath, "m/d/Y H:i");
		 	$retObj->success = $itemObj->success = $this->deleteFile($archiveItemObj->realPath);
		 	$retObj->exist=false;
		}
		
		Response::sendOKResponse($retObj);
	}
	 
	function compress($d){
		
		$retObj = (object) array();
		
		if($d->download==true){
			$archivePathObj = UserFileSystem::getInstance()->getNewTmpFilenameInTmpDir("archive_", ".".strtolower($d->compressType));
			$retObj->archivePath = $archivePathObj->fullPath;
		}else{
			$retObj->archivePath = $d->archivePath;
			$archivePathObj = $this->checkPathAndGetPathElements($d->archivePath);
			if(file_exists($archivePathObj->realPath)){
				if($d->forceOverwrite!=true){
					$retObj->success = false;
					$retObj->exist = true;
					Response::sendOKResponse($retObj);
				}else{
				 	if($d->useRecycleBin==true){
						$recBinFileName = RecycleBin::getInstance()->add($archivePathObj->fullPath, $d->recycleBinFileName, RecycleBin::$OVERWRITE, Request::getApplicationName());
					 	if($recBinFileName){
					 	 	$retObj->recycleBinSuccess = true;
					 	 	$retObj->recycleBinFileName = $recBinFileName;
					 	}
					}
				}
			}
			
		}
		
		$pathFromObj = $this->checkPathAndGetPathElements($d->fromPath);
		
		// make zip file
		if($d->compressType=="ZIP"){
			$retObj->success = $this->makeZIPCompressedFile($d->items, $pathFromObj->realPath, $archivePathObj->realPath);
		}else if($d->compressType=="GZ"){
			$retObj->success = $this->makeGZCompressedFile($d->items[0], $pathFromObj->realPath, $archivePathObj->realPath);
		}else if($d->compressType=="TAR" || $d->compressType=="TGZ" || $d->compressType=="TBZ"){
			$retObj->success = $this->makeTARCompressedFile($d->items, $pathFromObj->realPath, $archivePathObj->realPath, $d->compressType);
		}
		
		$retObj->archiveFileItem = $this->getFileInfo($archivePathObj->realPath, "m/d/Y H:i");
		
	 	Response::sendOKResponse($retObj);
	}
	function makeTARCompressedFile($items, $baseItemsRealPath, $archiveRealPath, $compressType){
	
		require_once("archive/archive.php");
		
		if($compressType=="TAR")
			$archiver = new tar_file($archiveRealPath);
		else if($compressType=="TGZ")
			$archiver = new gzip_file($archiveRealPath);
		else //if($compressType=="TBZ")
			$archiver = new bzip_file($archiveRealPath);
	
		$archiver->set_options(array('basedir' => $baseItemsRealPath, 'overwrite' => 1));
		
		for($i=0; $i<count($items); $i++){
		 	$pathItemObj = $this->checkPathAndGetPathElements($items[$i]->path);
		 	$archiver->add_files(array(substr($pathItemObj->realPath,strlen($baseItemsRealPath)+1)));
		}
		
		$archiver->create_archive();
		
		return true;
	}
	function makeGZCompressedFile($item, $baseItemsRealPath, $archiveRealPath){

		$pathItemObj = $this->checkPathAndGetPathElements($item->path);
		
		$content=$this->getFileContent($pathItemObj->realPath);
		
		if(is_int($content) && $content<0){
			return $content;
		}
		
		if(!$gzfp=gzopen($archiveRealPath,"wb")){
		 	return -70;
		}
		
		gzwrite($gzfp,$content);
		gzclose($gzfp);
		
		return true;
	}
	function makeZIPCompressedFile($items, $baseItemsRealPath, $archiveRealPath){
	 	require_once("zipfile/zip.class.php");
		$archiver = new zipfile();
		
		$archiver->basedir = $baseItemsRealPath;
		
		for($i=0; $i<count($items); $i++){
		 	$pathItemObj = $this->checkPathAndGetPathElements($items[$i]->path);
			$archiver->add_file(substr($pathItemObj->realPath,strlen($baseItemsRealPath)+1));
		}
		
		Util::writeFile($archiveRealPath, $archiver->zipped_file());
		
		return true;
	}
	function compressReturn(&$itemResponse, $success){
		$itemResponse->success = $success;
		return $itemResponse;
	}

	function download($d){
	
		$pathToObj = $this->checkPathAndGetPathElements($d[0]);
		
		require_once("httpdownload/class.httpdownload.php");
		$dl = new httpdownload();
		 
 		$dl->set_byfile($pathToObj->realPath); //Download from a file
 		$dl->use_resume = true; //Enable Resume Mode
 		if(!empty($d[1])){ 
		  $dl->filename = $d[1];
 		}else{
 		  $dl->filename = Util::getFileNameFromPath($d[0]);
		}
 		//$dl->delete_on_completion = true;
 		$dl->download(); //Download File
 		
		exit;
		
	}
	function copyMove($d){
	 
		$items = $d->items;
		
		$itemsResponses = Array();
		for($i=0; $i<count($items); $i++){
		 	$itemsResponses[$i] = $this->copyMoveItem($d->fromPath, $d->toPath, $items[$i], $d->useRecycleBin, $d->operation, $d->forceOverwrite);
		}
		
		$recItems = array();
		if(isset($d->directoriesForDeletion)){
			foreach($d->directoriesForDeletion as $key=>$_path)  {
			 	$drive = Util::getDriveFromPath($_path);
				$path = Util::getRelativePathFromPath($_path);
				$driveRealPath = UserFileSystem::getInstance()->getDriveRootDir($drive);
				$realPath =  UD::getRealPath($driveRealPath."/".$path);
				$this->recursiveFolderDeletion($realPath, false, $recItems, $drive, false);
			}
		}
		
	 	Response::sendOKResponse($itemsResponses);
	}

	function checkPathAndGetPathElements($path){
	 	
	 	$pathObj = (object) array();

		$pathObj->drive = Util::getDriveFromPath($path);
		$pathObj->path = Util::getRelativePathFromPath($path);
		$pathObj->realDrivePath = UserFileSystem::getInstance()->getDriveRootDir($pathObj->drive);
	 	$pathObj->fullPath = $path;
		
		if($pathObj->realDrivePath==false){
			return -52;
		}

		//return full path to directory
		$pathObj->realPath =  UD::getRealPath($pathObj->realDrivePath."/".$pathObj->path);

		//check can user access to this directory
		if(!UserFileSystem::getInstance()->securityPathCheck($pathObj->realPath , $pathObj->drive)){
			return -50;
		}
		
		return 	$pathObj;
		
	}
	function replaceNameToPath($path, $newName){
		return substr($path, 0,	strrpos($path, "/")+1).$newName;
	}
	function getPathTo($baseFromPath, $baseToPath, $path, $newName){
	 	if($newName) 
			$path = $this->replaceNameToPath($path, $newName);
	 	return $baseToPath.substr($path, strlen($baseFromPath));
	}
	function moveCopyFile($fromRealPath, $toRealPath, $force, $operation){
		if($operation=="MOVE")
			return $this->move($fromRealPath, $toRealPath, $force);
		else
			return $this->copy($fromRealPath, $toRealPath, $force);
	}

	function cmReturn(&$itemResponse, $success, $assignSubItems, &$recItems){
		$itemResponse->success = $success;
		if($assignSubItems!=true && $recItems!==null){
			$recItems[] = $itemResponse;
			return $itemResponse->success;
		}else{
			return $itemResponse;
		}
	}
	function copyMoveItem($baseFromPath, $baseToPath, $item, $useRecycleBin=true, $operation="COPY", $forceOverwrite=false, &$recItems=null){
	
		$itemResponse = (object) Array();
		
		$pathFromObj = $this->checkPathAndGetPathElements($item->path);
		$pathToObj = $this->checkPathAndGetPathElements($this->getPathTo($baseFromPath, $baseToPath, $item->path, $item->newName));
		
		// if copy to itself
		if($pathFromObj->realPath==$pathToObj->realPath){
		 	return $this->cmReturn($itemResponse, -60, $assignSubItems, $recItems);
		}
		// if copy dir to it's subdir
		//print_R($pathFromObj->realPath);
		//print_R("sssssssss");
		//print_R(substr($pathToObj->realPath, 0, strlen($pathFromObj->realPath)));
		if($item->type=="dir" && substr($pathToObj->realPath, 0, strlen($pathFromObj->realPath)) == $pathFromObj->realPath){
		 	return $this->cmReturn($itemResponse, -61, $assignSubItems, $recItems);
		}
		
		//if check failed return error id
		if($pathFromObj<0){
			return $this->cmReturn($itemResponse, $pathFromObj, $assignSubItems, $recItems);
		}
		
		
		// proccess dir		
		if($item->type=="dir"){

			//create directory
			$itemResponse->exist = is_dir($pathToObj->realPath);
			
		/*	if($itemResponse->exist){
				$itemResponse->success = -62;
			}
			else{*/
				$itemResponse->success = Util::createDirectoryIfNotExist($pathToObj->realPath);
			//}
				
 			$itemResponse->type = "dir";
 			$itemResponse->pathFrom = self::getPathFromRealPath($pathFromObj->drive, $pathFromObj->realPath);
 			$itemResponse->pathTo = self::getPathFromRealPath($pathToObj->drive, $pathToObj->realPath);
			
			if($itemResponse->success<0){
			 	return $this->cmReturn($itemResponse, false, $assignSubItems, $recItems);
			} 
		 		
		 	if($recItems===null) {
				$itemResponse->fileToItem = $this->getFileInfo($pathToObj->realPath, "m/d/Y H:i");
				$itemResponse->fileFromItem = $this->getFileInfo($pathFromObj->realPath, "m/d/Y H:i");
				$recItems = array();
				$assignSubItems = true;
			}
		 	
			$handle = opendir($pathFromObj->realPath);
			while (FALSE !== ($item = readdir($handle))){
				if($item != '.' && $item != '..'){
					$path = $pathFromObj->realPath.'/'.$item;
					//print_r(self::createFileItemFromRealPath($path));
					$success=$this->copyMoveItem($baseFromPath, $baseToPath, self::createFileItemFromRealPath($path), $useRecycleBin, $operation, $forceOverwrite, $recItems);
					$itemResponse->success = ($success==true && $itemResponse->success==true);
					//print_r($recItems);
					if($assignSubItems==true) $itemResponse->subDirectoriesFiles = $recItems;
				}
			}
			closedir($handle);
		 	
		 	if($operation=="MOVE") 
				$itemResponse->successRemoved = $this->deleteFolder($pathFromObj->realPath);
 	
	 	}
 		// proccess file
	 	else if ($item->type=="file"){
	 		
	 		
	 	  	$itemResponse->pathFrom = self::getPathFromRealPath($pathFromObj->drive, $pathFromObj->realPath);
 			$itemResponse->pathTo = self::getPathFromRealPath($pathToObj->drive, $pathToObj->realPath);
 			$itemResponse->type = "file";
 						
	 		$fileToExist = is_file($pathToObj->realPath);

			if($useRecycleBin==true && $fileToExist==true && $forceOverwrite==true){
			 	$recBinFileName = RecycleBin::getInstance()->add($pathToObj->fullPath, "", RecycleBin::$OVERWRITE, Request::getApplicationName());
			 	if($recBinFileName){
			 	 	$itemResponse->recycleBinSuccess = true;
			 	 	$itemResponse->recycleBinFileName = $recBinFileName;
			 	}
			}elseif($fileToExist==true && $forceOverwrite!=true){
				return $this->cmReturn($itemResponse, -62, $assignSubItems, $recItems);
			}

			// copy/move
			if($recItems===null && !($itemResponse->success<0)) {
				$itemResponse->fileFromItem = $this->getFileInfo($pathFromObj->realPath, "m/d/Y H:i");
			}
			
			$itemResponse->success = $this->moveCopyFile($pathFromObj->realPath, $pathToObj->realPath, $forceOverwrite, $operation);


			if($recItems===null && !($itemResponse->success<0)) {
				$itemResponse->fileToItem = $this->getFileInfo($pathToObj->realPath, "m/d/Y H:i");

			}

 		}
 	
 		if($operation=="MOVE"){
 			
 		}
 	
		return $this->cmReturn($itemResponse, $itemResponse->success, $assignSubItems, $recItems);
		

	}
/*	function recursiveFolderMoveCopy($baseFromPath, $baseToPath, $pathFromObj, $pathToObj, $useRecycleBin, $operation, &$recItems){
		
		//check can user access to this directory
		if(!UserFileSystem::getInstance()->securityPathCheck($directory, $drive)){
			Response::sendResponse(false, null, "file", "no_permission");
		}
		
		if(!is_dir($directory))
			return -1;
		
		if(!is_readable($directory))
			return -2;
		
		$handle = opendir($directory);
		while (FALSE !== ($item = readdir($handle))){
			if($item != '.' && $item != '..'){
				$path = $directory.'/'.$item;
				if(is_dir($path)) {
					$this->recursiveFolderMoveCopy($path, $useRecycleBin, $recItems, $drive, $operation);
				}
				else{
				 	if($useRecycleBin==true){
					 	$recBinFileName = RecycleBin::getInstance()->add(self::getPathFromRealPath($drive, $path), "", RecycleBin::$DELETE, Request::getApplicationName());
					 	if($recBinFileName){
					 	 	$itemResponse  = (object) array();
					 	 	$itemResponse->recycleBinSuccess = true;
					 	 	$itemResponse->recycleBinFileName = $recBinFileName;
					 	 	$itemResponse->path = self::getPathFromRealPath($drive, $path);
					 	 	$itemResponse->type = "file";
					 	}
					}
					$itemResponse->success = $this->moveCopyFile($fromRealPath, $toRealPath, $force, $operation);
					$recItems[] = $itemResponse;
				}
			}
		}
		closedir($handle);
		
		if(@rmdir($directory)===false){
			return -3;
		}else{
		 	$itemResponse  = (object) array();
			$itemResponse->success = true;
			$itemResponse->path = self::getPathFromRealPath($drive, $directory);
			$itemResponse->type = "dir";	
			$recDelItems[] = $itemResponse;
		}
		
		return true;
	}*/
	function createFile($d){
	 	
	 	$fileObj = $this->checkPathAndGetPathElements($d->filePath);
	 
		$success = parent::createFileAP($fileObj->realPath, $d->fileContent, Config::get("chmod_file"));
		if($success<0){
	 		Response::sendErrorResponse($this->getErrorID($success), $this->getErrorMsg($success));
		}else{
		 	$retObj = (object) array();
			$retObj->success = $success;
			$retObj->fileItem = $this->getFileInfo($fileObj->realPath, "m/d/Y H:i");
			Response::sendOKResponse($retObj);
		}
	}
	
	function createDirectory($d){
	 	
	 	$drive = Util::getDriveFromPath($d->dirPath);
		$path = Util::getRelativePathFromPath($d->dirPath);
		$driveRealPath = UserFileSystem::getInstance()->getDriveRootDir($drive);
		$realPath =  UD::getRealPath($driveRealPath."/".$path);
		

		$success = parent::addFolder($realPath, Config::get("chmod_dir"));
		if($success<0){
	 		Response::sendErrorResponse($this->getErrorID($success), $this->getErrorMsg($success));
		}else{
		 	$retObj = (object) array();
			$retObj->success = $success;
			$retObj->fileItem = $this->getFileInfo($realPath, "m/d/Y H:i");
			Response::sendOKResponse($retObj);
		}
	}

	function getDirectory($d){
	 

		$drive = Util::getDriveFromPath($d->dirPath);
		$path = Util::getRelativePathFromPath($d->dirPath);
		$driveRealPath = UserFileSystem::getInstance()->getDriveRootDir($drive);
		if($driveRealPath==false){
			Response::sendResponse(false, null, "file", "unknown_drive");
		}
		
		//return full path to directory
		$realPath =  UD::getRealPath($driveRealPath."/".$path);

		//check can user access to this directory
		if(!UserFileSystem::getInstance()->securityPathCheck($realPath, $drive)){
			Response::sendResponse(false, null, "file", "no_permission");
		}
		
	 	$FaF = $this->getFoldersAndFiles($realPath, false, "m/d/Y H:i");
	 	if($FaF<0){
	 		Response::sendErrorResponse($this->getErrorID($FaF), $this->getErrorMsg($FaF));
		}
		
		usort($FaF, array(&$this, "sortFilesFunction"));
	//	usort(, "sortFilesFunction");
	
		Response::sendOKResponse($FaF);
	 
	}
	
	
	function rename($d) {
	
		$driveFrom = Util::getDriveFromPath($d->renameFrom);
		$pathFrom = Util::getRelativePathFromPath($d->renameFrom);
		$driveRealPathFrom = UserFileSystem::getInstance()->getDriveRootDir($driveFrom);
		
		if($driveRealPathFrom==false){
			Response::sendResponse(false, null, "file", "unknown_drive");
		}
		
		$driveTo = Util::getDriveFromPath($d->renameTo);
		$pathTo= Util::getRelativePathFromPath($d->renameTo);
		$driveRealPathTo = UserFileSystem::getInstance()->getDriveRootDir($driveTo);
		
		if($driveRealPathTo==false){
			Response::sendResponse(false, null, "file", "unknown_drive");
		}
		
	
	
		//return full path to directory
		$realPathRenameFrom =  UD::getRealPath($driveRealPathFrom."/".$pathFrom);
		$realPathRenameTo =  UD::getRealPath($driveRealPathTo."/".$pathTo);
		
		//check can user access to this directory
		if(!UserFileSystem::getInstance()->securityPathCheck($realPathRenameFrom, $driveFrom) || !UserFileSystem::getInstance()->securityPathCheck($realPathRenameTo, $driveTo)){
			Response::sendResponse(false, null, "file", "no_permission");
		}

		// rename		
		if($d->renameType=="dir")
 			$success = $this->renameFolder($realPathRenameFrom, $realPathRenameTo);
 		else if ($d->renameType=="file")
 			$success = $this->renameFile($realPathRenameFrom, $realPathRenameTo);
 		else
 			Response::sendResponse(false, $d, "file", "unknown_file_type");
 		
 		if($success<0){
	 		Response::sendErrorResponse($this->getErrorID($success), $this->getErrorMsg($success), $d);
		}

		$d->fileItem = $this->getFileInfo($realPathRenameTo, "m/d/Y H:i");
		Response::sendOKResponse($d);
		
 	}


	function restoreCopyedOrMovedDirsAndFiles($d){
	 	
	 	$dirsArr =  array();
	 	if(is_array($d->dirs))
	 		$dirsArr = array_merge($dirsArr, $d->dirs);
	 /*	if(is_array($d->delDirs))
	 		$dirsArr = array_merge($dirsArr, $d->delDirs);*/
	 		

	 	$retObj = (object) array();
	
		// ------------------------------
		// only for move 
		// ------------------------------
	 	if($d->operation=="MOVE"){
	 	 
		 	// proccess dirs on from side
			for($i=0;$i<count($dirsArr);$i++){
			 	$itemObj = (object) array();
			 	$realPath = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($dirsArr[$i]->pathFrom))."/".Util::getRelativePathFromPath($dirsArr[$i]->pathFrom));
			 	$itemObj->exist = is_dir($realPath);
				$itemObj->success = $this->createPath($dirsArr[$i]->pathFrom);
				$itemObj->path = $dirsArr[$i]->pathFrom;
				$itemObj->fileItem = $this->getFileInfo($realPath, "m/d/Y H:i");
				$retObj->dirsFrom[$i] = $itemObj;
			}
			
			
			// proccess files on from side
			if(is_array($d->files)){
				for($i=0;$i<count($d->files);$i++){
				 	$itemObj = (object) array();	
				 	// realPathFrom
					$realPathFrom = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($d->files[$i]->pathFrom))."/".Util::getRelativePathFromPath($d->files[$i]->pathFrom));
				 	// realPathTo
				 	$realPathTo = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($d->files[$i]->pathTo))."/".Util::getRelativePathFromPath($d->files[$i]->pathTo));
				 	$itemObj->exist = is_file($realPathFrom);
					$itemObj->success = $this->copy($realPathTo, $realPathFrom, true);
					$itemObj->path = $d->files[$i]->pathFrom;
					$itemObj->fileItem = $this->getFileInfo($realPathFrom, "m/d/Y H:i");
					$retObj->filesFrom[$i] = $itemObj;
				}
			}
		
		}
		
		// ------------------------------
		// for both move and copy
		// ------------------------------
		
		// delete or restore from rec bin on to side
		if(is_array($d->files)){
			for($i=0;$i<count($d->files);$i++){
			 	$itemObj = (object) array();	
			 	$itemObj->path = $d->files[$i]->pathTo;
				 // realPathTo
			 	$driveTo = Util::getDriveFromPath($d->files[$i]->pathTo);
			 	$realPathTo = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir($driveTo)."/".Util::getRelativePathFromPath($d->files[$i]->pathTo));	
			 	if($d->files[$i]->recycleBinFileName){
			 	 	$itemObj->success = RecycleBin::getInstance()->restore($d->files[$i]->recycleBinFileName, $d->files[$i]->pathTo);
					$itemObj->fileItem = $this->getFileInfo($realPathTo, "m/d/Y H:i");
					$itemObj->removed = false;
			 	}
			 	else{
			 		$itemObj->fileItem = $this->getFileInfo($realPathTo, "m/d/Y H:i");
			 	 	$itemObj->success = $this->deleteFile($realPathTo);
			 	 	$itemObj->removed = true;
			 	}
				$retObj->filesTo[$i] = $itemObj;
			}
		}
		
	 	// proccess dirs on to side
	 	$retObj->dirsTo = array();
		for($i=0;$i<count($dirsArr);$i++){
		 	if($dirsArr[$i]->exist==false){
			 	$itemObj = (object) array();
			 	$driveTo = Util::getDriveFromPath($dirsArr[$i]->pathTo);
			 	$realPathTo = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir($driveTo)."/".Util::getRelativePathFromPath($dirsArr[$i]->pathTo));
			 	$itemObj->path = $dirsArr[$i]->pathTo;
			 	$itemObj->fileItem = $this->getFileInfo($realPathTo, "m/d/Y H:i");
			 	$recItems = array();
			 	$this->recursiveFolderDeletion($realPathTo, false, $recItems, $driveTo, true);
				$itemObj->success = true; //$this->deleteFile($realPathTo);
			 	$itemObj->removed = true;

				$retObj->dirsTo[] = $itemObj;
			}
		}
		
	 	//print_r($retObj);
	 	
	 //print_r($d->files);

		Response::sendOKResponse($retObj);
	}
	
	function performCopyedOrMovedDirsAndFiles($d){
	 
	 	$dirsArr =  array();
	 	if(is_array($d->dirs))
	 		$dirsArr = array_merge($dirsArr, $d->dirs);
	 /*	if(is_array($d->delDirs))
	 		$dirsArr = array_merge($dirsArr, $d->delDirs);*/
	 		

	 	$retObj = (object) array();
	
		// ------------------------------
		// for both move and copy
		// ------------------------------

	 	 
	 	// proccess dirs on to side
		for($i=0;$i<count($dirsArr);$i++){
		 	$itemObj = (object) array();
		 	$realPath = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($dirsArr[$i]->pathTo))."/".Util::getRelativePathFromPath($dirsArr[$i]->pathTo));
		 	$itemObj->exist = is_dir($realPath);
			$itemObj->success = $this->createPath($dirsArr[$i]->pathTo);
			$itemObj->path = $dirsArr[$i]->pathTo;
			$itemObj->fileItem = $this->getFileInfo($realPath, "m/d/Y H:i");
			$retObj->dirsTo[$i] = $itemObj;
		}
		
		
		// proccess files on to side
		if(is_array($d->files)){
			for($i=0;$i<count($d->files);$i++){
			 	$itemObj = (object) array();	
			 	// realPathFrom
				$realPathFrom = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($d->files[$i]->pathFrom))."/".Util::getRelativePathFromPath($d->files[$i]->pathFrom));
			 	// realPathTo
			 	$realPathTo = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($d->files[$i]->pathTo))."/".Util::getRelativePathFromPath($d->files[$i]->pathTo));
			 	$itemObj->exist = is_file($realPathTo);
				$itemObj->success = $this->copy($realPathFrom, $realPathTo, true);
				$itemObj->path = $d->files[$i]->pathTo;
				$itemObj->fileItem = $this->getFileInfo($realPathTo, "m/d/Y H:i");
				$retObj->filesTo[$i] = $itemObj;
			}
		}
	

		if($d->operation=="MOVE"){
	 	 
		// ------------------------------
		// only for move  
		// ------------------------------
			
			// delete on from side
			if(is_array($d->files)){
				for($i=0;$i<count($d->files);$i++){
				 	$itemObj = (object) array();	
				 	$itemObj->path = $d->files[$i]->pathFrom;
					 // realPathTo
				 	$driveFrom = Util::getDriveFromPath($d->files[$i]->pathFrom);
				 	$realPathFrom = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir($driveFrom)."/".Util::getRelativePathFromPath($d->files[$i]->pathFrom));	
				 	$itemObj->fileItem = $this->getFileInfo($realPathFrom, "m/d/Y H:i");
				 	
					if($d->files[$i]->recycleBinFileName)
				 		RecycleBin::getInstance()->add($d->files[$i]->pathFrom, $d->files[$i]->recycleBinFileName, RecycleBin::$DELETE, Request::getApplicationName());
				 	
				 	$itemObj->success = $this->deleteFile($realPathFrom);
				 	$itemObj->removed = true;
					$retObj->filesFrom[$i] = $itemObj;
				}
			}
			
		 	// proccess (delete) dirs on from side
		 	$retObj->dirsFrom = array();
			for($i=0;$i<count($dirsArr);$i++){
			 	//if($dirsArr[$i]->exist==false){
				 	$itemObj = (object) array();
				 	$driveFrom = Util::getDriveFromPath($dirsArr[$i]->pathFrom);
				 	$realPathFrom = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir($driveFrom)."/".Util::getRelativePathFromPath($dirsArr[$i]->pathFrom));
				 	$itemObj->path = $dirsArr[$i]->pathFrom;
				 	$itemObj->fileItem = $this->getFileInfo($realPathFrom, "m/d/Y H:i");
				 	$recItems = array();
				 	$this->recursiveFolderDeletion($realPathFrom, false, $recItems, $driveFrom, true);
					$itemObj->success = true; //$this->deleteFile($realPathTo);
				 	$itemObj->removed = true;
					$retObj->dirsFrom[] = $itemObj;
				//}
			}
			
		}
	 	//print_r($retObj);
	 	
	 //print_r($d->files);

		Response::sendOKResponse($retObj);
	}
	//////////////////////////////
	function restoreDirsAndFiles($d){
		
		$retObj = (object) array();
		//restore directories
		if(is_array($d->dirs)){
			for($i=0;$i<count($d->dirs);$i++){
			 	$itemObj = (object) array();
				$itemObj->success = $this->createPath($d->dirs[$i]->path);
				$itemObj->path = $d->dirs[$i]->path;
				$realPath = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($d->dirs[$i]->path))."/".Util::getRelativePathFromPath($d->dirs[$i]->path));
				$itemObj->fileItem = $this->getFileInfo($realPath, "m/d/Y H:i");
				$retObj->dirs[$i] = $itemObj;
			}
		}
		
		//restore files
		if(is_array($d->files)){
			for($i=0;$i<count($d->files);$i++){
			 	$itemObj = (object) array();
				$itemObj->success = RecycleBin::getInstance()->restore($d->files[$i]->recycleBinFileName, $d->files[$i]->path);
				$itemObj->path = $d->files[$i]->path;
				$realPath = UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($d->files[$i]->path))."/".Util::getRelativePathFromPath($d->files[$i]->path));
				$itemObj->fileItem = $this->getFileInfo($realPath, "m/d/Y H:i");
				$retObj->files[$i] = $itemObj;
			}
		}

		Response::sendOKResponse($retObj);
	}
	function createAbsolutePath($base, $_path){
	 	
		$pathArr = explode("/", $_path);
		$pathToCreate = $base;
		for($i=0; $i<count($pathArr); $i++){
		 	if($pathArr[$i]=="") continue;
			$pathToCreate .= "/". $pathArr[$i];
			if(!Util::createDirectoryIfNotExist($pathToCreate))
				return false;
		}
		
		return true;	
	}
	function createRelativePath($_path){
	 	
		$pathArr = explode("/", $_path);
		$pathToCreate = "";
		for($i=0; $i<count($pathArr); $i++){
		 	if($pathArr[$i]=="") continue;
			$pathToCreate .= $pathArr[$i];
			if(!Util::createDirectoryIfNotExist($pathToCreate))
				return false;
			
			$pathToCreate .= "/";
		}
		
		return true;	
	}
	function createPath($_path){
	 	
		$path = Util::getRelativePathFromPath($_path);
		$driveRealPath = UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($_path));
		
		$pathArr = explode("/", $path);
		$pathToCreate = $driveRealPath;
		for($i=0; $i<count($pathArr); $i++){
		 	if($pathArr[$i]=="") continue;
			$pathToCreate .= "/". $pathArr[$i];
			if(!Util::createDirectoryIfNotExist($pathToCreate))
				return false;
		}
		
		return true;	
	}

	function deleteDirsAndFiles($d){
	

		$retObj = (object) array();
		//delete files
		if(is_array($d->files)){
			for($i=0;$i<count($d->files);$i++){
			 	$itemObj = (object) array();
				RecycleBin::getInstance()->add($d->files[$i]->path, $d->files[$i]->recycleBinFileName, RecycleBin::$DELETE, Request::getApplicationName());
				$itemObj->path = $d->files[$i]->path;
				$delRealPath =  UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($d->files[$i]->path))."/".Util::getRelativePathFromPath($d->files[$i]->path));
				$itemObj->fileItem = $this->getFileInfo($delRealPath, "m/d/Y H:i");
				$itemObj->success = $this->deleteFile($delRealPath);
				$retObj->files[$i] = $itemObj;
			}
		}
		
		//delete dirs
		if(is_array($d->dirs)){
			for($i=0;$i<count($d->dirs);$i++){
			 	$itemObj = (object) array();
				$itemObj->path = $d->dirs[$i]->path;
				$delRealPath =  UD::getRealPath(UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($d->dirs[$i]->path))."/".Util::getRelativePathFromPath($d->dirs[$i]->path));
				$itemObj->fileItem = $this->getFileInfo($delRealPath, "m/d/Y H:i");
				$itemObj->success = $this->deletePath($d->dirs[$i]->path);
				$retObj->dirs[$i] = $itemObj;
			}
		}
		
		
		Response::sendOKResponse($retObj);
	}

	function deletePath($_path){
	 	
		$path = Util::getRelativePathFromPath($_path);
		$driveRealPath = UserFileSystem::getInstance()->getDriveRootDir(Util::getDriveFromPath($_path));
		
		for($i=0;i<100;$i++){
			$this->deleteFolder($driveRealPath.$path);
			$pos = strrpos($path, "/");
			if($pos===false) return;
			$path = substr($pos, 0, $pos);
			if($path=="") return;
		}
	
	}
	//////////////////////////////////
	
	function delete($d){
	 
	 	$delItems = $d->deleteItems;
		
		$itemsResponses = Array();
		for($i=0; $i<count($delItems); $i++){
		 	$itemsResponses[$i] = $this->deleteItem($delItems[$i], $d->useRecycleBin, $d->forceDeleting);
		}
	 
	 	Response::sendOKResponse($itemsResponses);
	}
	
	function deleteItem($item, $useRecycleBin=true, $forceDeleting=false){
	
		$itemResponse = (object) Array();
		
		$drive = Util::getDriveFromPath($item->path);
		$path = Util::getRelativePathFromPath($item->path);
		$driveRealPath = UserFileSystem::getInstance()->getDriveRootDir($drive);
	
		if($driveRealPath==false){
			$itemResponse->success = -52;
			return $itemResponse;
		}
		
		//return full path to directory
		$realDelPath =  UD::getRealPath($driveRealPath."/".$path);
		
		//check can user access to this directory
		if(!UserFileSystem::getInstance()->securityPathCheck($realDelPath, $drive)){
			$itemResponse->success = -50;
			return $itemResponse;
		}
		
		// delete		
		if($item->type=="dir"){
		 	if($forceDeleting==true){
		 	 	$recDelItems = Array();
		 		$success = $this->recursiveFolderDeletion($realDelPath, $useRecycleBin, $recDelItems, $drive);
		 		$itemResponse->subDirectoriesFiles = $recDelItems;
		 		
		 	}else{
 				$success = $this->deleteFolder($realDelPath);
 			}
 			$itemResponse->type = "dir";
 			$itemResponse->name = $item->name;
 			$itemResponse->path = self::getPathFromRealPath($drive, $realDelPath);
 		}
 		else if ($item->type=="file"){
	 		
			if($useRecycleBin==true){
			 	$recBinFileName = RecycleBin::getInstance()->add($item->path, "", RecycleBin::$DELETE, Request::getApplicationName());
			 	if($recBinFileName){
			 	 	$itemResponse->recycleBinSuccess = true;
			 	 	$itemResponse->recycleBinFileName = $recBinFileName;
			 	 	$itemResponse->path = $item->path;
			 	 	$itemResponse->name = $item->name;
			 	 	$itemResponse->type = "file";
			 	}
			}
 		 
 			$success = $this->deleteFile($realDelPath);
 			
 		}

		$itemResponse->success = $success;
		
		if($success<0){
 			//Ovde treba da dodje > removeFromRecycleBin($fileName)  ili >> $recBinFileName)
 		}
		
		return $itemResponse;
	}
	
	function recursiveFolderDeletion($directory, $useRecycleBin=true, &$recDelItems, $drive, $onlyDirs=false){
		
		//check can user access to this directory
		if(!UserFileSystem::getInstance()->securityPathCheck($directory, $drive)){
			Response::sendResponse(false, null, "file", "no_permission");
		}
		
		if(!is_dir($directory))
			return -1;
		
		if(!is_readable($directory))
			return -2;
		
		$handle = opendir($directory);
		while (FALSE !== ($item = readdir($handle))){
			if($item != '.' && $item != '..'){
				$path = $directory.'/'.$item;
				if(is_dir($path)) {
					$this->recursiveFolderDeletion($path, $useRecycleBin, $recDelItems, $drive, $onlyDirs);
				}
				else if($onlyDirs==false){
				 	if($useRecycleBin==true){
					 	$recBinFileName = RecycleBin::getInstance()->add(self::getPathFromRealPath($drive, $path), "", RecycleBin::$DELETE, Request::getApplicationName());
					 	if($recBinFileName){
					 	 	$itemResponse  = (object) array();
					 	 	$itemResponse->recycleBinSuccess = true;
					 	 	$itemResponse->recycleBinFileName = $recBinFileName;
					 	 	$itemResponse->path = self::getPathFromRealPath($drive, $path);
					 	 	$itemResponse->type = "file";
					 	}
					}
					$itemResponse->success = $this->deleteFile($path);
					$recDelItems[] = $itemResponse;
				}
			}
		}
		closedir($handle);
		
		if (count(glob("$directory/*")) !== 0)
		 	return -3;
	
		if( @rmdir($directory)===false)
			return -3;

		$itemResponse  = (object) array();
		$itemResponse->success = true;
		$itemResponse->path = self::getPathFromRealPath($drive, $directory);
		$itemResponse->type = "dir";	
		$recDelItems[] = $itemResponse;
		
		
		return true;
	}
	
	function _initErrorMsg(){
		
		//$this->_err = array();
		$this->_err = parent::_initErrorMsg();
		$this->_err["050"] = "You have not permission to access this directory";
		$this->_err["051"] = "Unknown file type";
		$this->_err["052"] = "Unknown virtual drive";

		$this->_err["060"] = "Can not copy file or directory to itself";
		$this->_err["061"] = "Can not copy directories to its subdirectory";
		$this->_err["062"] = "File exists";
		
		$this->_err["070"] = "Can not create new archive (gzopen failed)";
		
	} // _initErrorMsg function end
	
	// STATIC
	static function getPathFromRealPath($drive, $path){
		return $drive.":".substr($path, strlen(UserFileSystem::getInstance()->getDriveRootDir($drive)));
	}
	static function createFileItemFromRealPath($path){
	
		$item = self::getFileInfo($path, "m/d/Y H:i");
		//print_R($item);
		$item->path = self::getPathFromRealPath( UserFileSystem::getInstance()->getDriveFromRealPath($path), $path);
		//print_R($item);
		return $item;
		
	}
	                                                    
	                                                                                     
	static private function sortFilesFunction($a, $b){
	 	if($a["type"]=="dir" && $b["type"]!="file" ) return -1;
	 	elseif($a["type"]!="file" && $b["type"]=="dir" ) return 1;
	 	else return strcmp($a["name"], $b["name"]);
	}       
	
}
                             
                                                            
                                                            