rel_path = Filemanager::cleanPath($get['path']); if ($this->rel_path!="/") { $this->rel_path .= "/"; } if (!empty($get['query'])) { $this->query = $get['query']; } if (!empty($get['options'])) { $this->foptions = $get['options']; } $this->root = $get['root']; if ($this->isAbsPath($get['path'])) { $this->path = Filemanager::cleanPath($get['path']); } else { $this->root .= '/'; $this->path = $this->root . Filemanager::cleanPath($get['path']); } // Search if (!empty($post['search_string'])) { $this->search_string = ($post['search_string']); } if (!empty($post['search_file_type'])) { $this->search_file_type = ($post['search_file_type']); } // Create if (!empty($get['type'])) { $this->type = $get['type']; } // Modify\Create if (!empty($get['new_name'])) { $this->new_name = $get['new_name']; } foreach (array('content', 'mtime', 'patch') as $key) { if (!empty($post[$key])) { if (get_magic_quotes_gpc()) { $this->$key = stripslashes($post[$key]); } else { $this->$key = $post[$key]; } } } // Duplicate if (!empty($get['destination'])) { $get['destination'] = Filemanager::cleanPath($get['destination']); if ($this->isAbsPath($get['path'])) { $this->destination = $get['destination']; } else { $this->destination = $this->root . $get['destination']; } } } ////////////////////////////////////////////////////////////////// // INDEX (Returns list of files and directories) ////////////////////////////////////////////////////////////////// public function index() { if (file_exists($this->path)) { $index = array(); if (is_dir($this->path) && $handle = opendir($this->path)) { while (false !== ($object = readdir($handle))) { if ($object != "." && $object != ".." && $object != $this->controller) { if (is_dir($this->path.'/'.$object)) { $type = "directory"; $size=count(glob($this->path.'/'.$object.'/*')); } else { $type = "file"; $size=@filesize($this->path.'/'.$object); } $index[] = array( "name"=>$this->rel_path . $object, "type"=>$type, "size"=>$size ); } } $folders = array(); $files = array(); foreach ($index as $item => $data) { if ($data['type']=='directory') { $folders[] = array("name"=>$data['name'],"type"=>$data['type'],"size"=>$data['size']); } if ($data['type']=='file') { $files[] = array("name"=>$data['name'],"type"=>$data['type'],"size"=>$data['size']); } } function sorter($a, $b, $key = 'name') { return strnatcmp($a[$key], $b[$key]); } usort($folders, "sorter"); usort($files, "sorter"); $output = array_merge($folders, $files); $this->status = "success"; $this->data = '"index":' . json_encode($output); } else { $this->status = "error"; $this->message = "Not A Directory"; } } else { $this->status = "error"; $this->message = "Path Does Not Exist"; } $this->respond(); } public function find() { if (!function_exists('shell_exec')) { $this->status = "error"; $this->message = "Shell_exec() Command Not Enabled."; } else { chdir($this->path); $input = str_replace('"', '', $this->query); $cmd = 'find -L '; $strategy = ''; if ($this->foptions && $this->foptions['strategy']) { $strategy = $this->foptions['strategy']; } switch ($strategy) { case 'substring': $cmd = "$cmd -iname ".escapeshellarg('*'.$input.'*'); break; case 'regexp': $cmd = "$cmd -regex ".escapeshellarg($input); break; case 'left_prefix': default: $cmd = "$cmd -iname ".escapeshellarg($input.'*'); break; } $cmd = "$cmd -printf \"%h/%f %y\n\""; $output = shell_exec($cmd); $file_arr = explode("\n", $output); $output_arr = array(); error_reporting(0); foreach ($file_arr as $i => $fentry) { $farr = explode(" ", $fentry); $fname = trim($farr[0]); if ($farr[1] == 'f') { $ftype = 'file'; } else { $ftype = 'directory'; } if (strlen($fname) != 0) { $fname = $this->rel_path . substr($fname, 2); $f = array('path' => $fname, 'type' => $ftype ); array_push($output_arr, $f); } } if (count($output_arr)==0) { $this->status = "error"; $this->message = "No Results Returned"; } else { $this->status = "success"; $this->data = '"index":' . json_encode($output_arr); } } $this->respond(); } ////////////////////////////////////////////////////////////////// // SEARCH ////////////////////////////////////////////////////////////////// public function search() { if (!function_exists('shell_exec')) { $this->status = "error"; $this->message = "Shell_exec() Command Not Enabled."; } else { if ($_GET['type'] == 1) { $this->path = WORKSPACE; } $return = array(); $input = str_replace('"', '', $this->search_string); $cmd = 'find -L ' . escapeshellarg($this->path) . ' -iregex '.escapeshellarg('.*' . $this->search_file_type ).' -type f | xargs grep -i -I -n -R -H ' . escapeshellarg($input) . ''; $output = shell_exec($cmd); $output_arr = explode("\n", $output); foreach ($output_arr as $line) { $data = explode(":", $line); $da = array(); if (count($data) > 2) { $da['line'] = $data[1]; $da['file'] = str_replace($this->path, '', $data[0]); $da['result'] = str_replace($this->root, '', $data[0]); $da['string'] = str_replace($data[0] . ":" . $data[1] . ':', '', $line); $return[] = $da; } } if (count($return)==0) { $this->status = "error"; $this->message = "No Results Returned"; } else { $this->status = "success"; $this->data = '"index":' . json_encode($return); } } $this->respond(); } ////////////////////////////////////////////////////////////////// // OPEN (Returns the contents of a file) ////////////////////////////////////////////////////////////////// public function open() { if (is_file($this->path)) { $output = file_get_contents($this->path); if (extension_loaded('mbstring')) { if (!mb_check_encoding($output, 'UTF-8')) { if (mb_check_encoding($output, 'ISO-8859-1')) { $output = utf8_encode($output); } else { $output = mb_convert_encoding($content, 'UTF-8'); } } } $this->status = "success"; $this->data = '"content":' . json_encode($output); $mtime = filemtime($this->path); $this->data .= ', "mtime":'.$mtime; } else { $this->status = "error"; $this->message = "Not A File :".$this->path; } $this->respond(); } ////////////////////////////////////////////////////////////////// // OPEN IN BROWSER (Return URL) ////////////////////////////////////////////////////////////////// public function openinbrowser() { $protocol = ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://"; $domainName = $_SERVER['HTTP_HOST']; $url = $protocol.WSURL.'/'.$this->rel_path; $this->status = "success"; $this->data = '"url":' . json_encode(rtrim($url, "/")); $this->respond(); } ////////////////////////////////////////////////////////////////// // CREATE (Creates a new file or directory) ////////////////////////////////////////////////////////////////// public function create() { // Create file if ($this->type=="file") { if (!file_exists($this->path)) { if ($file = fopen($this->path, 'w')) { // Write content if ($this->content) { fwrite($file, $this->content); } $this->data = '"mtime":'.filemtime($this->path); fclose($file); $this->status = "success"; } else { $this->status = "error"; $this->message = "Cannot Create File"; } } else { $this->status = "error"; $this->message = "File Already Exists"; } } // Create directory if ($this->type=="directory") { if (!is_dir($this->path)) { mkdir($this->path); $this->status = "success"; } else { $this->status = "error"; $this->message = "Directory Already Exists"; } } $this->respond(); } ////////////////////////////////////////////////////////////////// // DELETE (Deletes a file or directory (+contents)) ////////////////////////////////////////////////////////////////// public function delete() { function rrmdir($path, $follow) { if (is_file($path)) { unlink($path); } else { $files = array_diff(scandir($path), array('.','..')); foreach ($files as $file) { if (is_link("$path/$file")) { if ($follow) { rrmdir("$path/$file", $follow); } unlink("$path/$file"); } elseif (is_dir("$path/$file")) { rrmdir("$path/$file", $follow); } else { unlink("$path/$file"); } } return rmdir($path); } } if (file_exists($this->path)) { if (isset($_GET['follow'])) { rrmdir($this->path, true); } else { rrmdir($this->path, false); } $this->status = "success"; } else { $this->status = "error"; $this->message = "Path Does Not Exist "; } $this->respond(); } ////////////////////////////////////////////////////////////////// // MODIFY (Modifies a file name/contents or directory name) ////////////////////////////////////////////////////////////////// public function modify() { // Change name if ($this->new_name) { $explode = explode('/', $this->path); array_pop($explode); $new_path = implode("/", $explode) . "/" . $this->new_name; if (!file_exists($new_path)) { if (rename($this->path, $new_path)) { //unlink($this->path); $this->status = "success"; } else { $this->status = "error"; $this->message = "Could Not Rename"; } } else { $this->status = "error"; $this->message = "Path Already Exists"; } } else { // Change content if ($this->content || $this->patch) { if ($this->content==' ') { $this->content=''; // Blank out file } if ($this->patch && ! $this->mtime) { $this->status = "error"; $this->message = "mtime parameter not found"; $this->respond(); return; } if (is_file($this->path)) { $serverMTime = filemtime($this->path); $fileContents = file_get_contents($this->path); if ($this->patch && $this->mtime != $serverMTime) { $this->status = "error"; $this->message = "Client is out of sync"; //DEBUG : file_put_contents($this->path.".conflict", "SERVER MTIME :".$serverMTime.", CLIENT MTIME :".$this->mtime); $this->respond(); return; } elseif (strlen(trim($this->patch)) == 0 && ! $this->content) { // Do nothing if the patch is empty and there is no content $this->status = "success"; $this->data = '"mtime":'.$serverMTime; $this->respond(); return; } if ($file = fopen($this->path, 'w')) { if ($this->patch) { $dmp = new diff_match_patch(); $p = $dmp->patch_apply($dmp->patch_fromText($this->patch), $fileContents); $this->content = $p[0]; //DEBUG : file_put_contents($this->path.".orig",$fileContents ); //DEBUG : file_put_contents($this->path.".patch", $this->patch); } if (fwrite($file, $this->content) === false) { $this->status = "error"; $this->message = "could not write to file"; } else { // Unless stat cache is cleared the pre-cached mtime will be // returned instead of new modification time after editing // the file. clearstatcache(); $this->data = '"mtime":'.filemtime($this->path); $this->status = "success"; } fclose($file); } else { $this->status = "error"; $this->message = "Cannot Write to File"; } } else { $this->status = "error"; $this->message = "Not A File"; } } else { $file = fopen($this->path, 'w'); fclose($file); $this->data = '"mtime":'.filemtime($this->path); $this->status = "success"; } } $this->respond(); } ////////////////////////////////////////////////////////////////// // DUPLICATE (Creates a duplicate of the object - (cut/copy/paste) ////////////////////////////////////////////////////////////////// public function duplicate() { if (!file_exists($this->path)) { $this->status = "error"; $this->message = "Invalid Source"; } function recurse_copy($src, $dst) { $dir = opendir($src); @mkdir($dst); while (false !== ( $file = readdir($dir))) { if (( $file != '.' ) && ( $file != '..' )) { if (is_dir($src . '/' . $file)) { recurse_copy($src . '/' . $file, $dst . '/' . $file); } else { copy($src . '/' . $file, $dst . '/' . $file); } } } closedir($dir); } if ($this->status!="error") { if (is_file($this->path)) { copy($this->path, $this->destination); $this->status = "success"; } else { recurse_copy($this->path, $this->destination); if (!$this->response) { $this->status = "success"; } } } $this->respond(); } ////////////////////////////////////////////////////////////////// // UPLOAD (Handles uploads to the specified directory) ////////////////////////////////////////////////////////////////// public function upload() { // Check that the path is a directory if (is_file($this->path)) { $this->status = "error"; $this->message = "Path Not A Directory"; } else { // Handle upload $info = array(); foreach( $_FILES['upload']['name'] as $key=>$value) { if (!empty($value)) { $filename = $value; $add = $this->path."/$filename"; if (@move_uploaded_file($_FILES['upload']['tmp_name'][$key], $add)) { $info[] = array( "name"=>$value, "size"=>filesize($add), "url"=>$add, "thumbnail_url"=>$add, "delete_url"=>$add, "delete_type"=>"DELETE" ); } } } $this->upload_json = json_encode($info); } $this->respond(); } ////////////////////////////////////////////////////////////////// // RESPOND (Outputs data in JSON [JSEND] format) ////////////////////////////////////////////////////////////////// public function respond() { // Success /////////////////////////////////////////////// if ($this->status=="success") { if ($this->data) { $json = '{"status":"success","data":{'.$this->data.'}}'; } else { $json = '{"status":"success","data":null}'; } // Upload JSON /////////////////////////////////////////// } elseif ($this->upload_json!='') { $json = $this->upload_json; // Error ///////////////////////////////////////////////// } else { $json = '{"status":"error","message":"'.$this->message.'"}'; } // Output //////////////////////////////////////////////// echo($json); } ////////////////////////////////////////////////////////////////// // Clean a path ////////////////////////////////////////////////////////////////// public static function cleanPath($path) { // replace backslash with slash $path = str_replace('\\', '/', $path); // allow only valid chars in paths$ $path = preg_replace('/[^A-Za-z0-9\-\._\/\ ]/', '', $path); // maybe this is not needed anymore // prevent Poison Null Byte injections $path = str_replace(chr(0), '', $path); // prevent go out of the workspace while (strpos($path, '../') !== false) { $path = str_replace('../', '', $path); } return $path; } }