Преглед изворни кода

FileManager bugfixes + file permission module

Serghey Rodin пре 9 година
родитељ
комит
7fefa20d90

+ 8 - 0
web/css/file_manager.css

@@ -309,6 +309,7 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: -4px 0 0 -1px;  b
 .confirm-box { background-color: #333; width: 480px; font-family: arial; margin-left: 50px; border-radius: 3px; box-shadow: 0 2px 11px 0 rgba(0, 0, 0, 0.5); }
 /*.confirm-box.replace { height: 230px; }*/
 .confirm-box .message { color: #EBE697; font-size: 16px; padding: 25px; margin-bottom: 60px; display: inline-block; }
+.confirm-box .results,
 .confirm-box .warning { color: #FF9500; font-size: 16px; padding: 25px; }
 .confirm-box .warning .title, 
 .confirm-box .message .title { color: #48B1B7; }
@@ -346,6 +347,13 @@ ul.listing { list-style-type: none; padding: 18px 0 0; margin: -4px 0 0 -1px;  b
 .confirm-box.rename.warning .controls.replace { display: inline-block; }
 .confirm-box.rename.warning .message { padding-bottom: 0; }
 
+.confirm-box.chmod .message { margin-bottom: 0; }
+.confirm-box.chmod .warning { padding: 10px 25px; }
+.confirm-box.chmod ul { padding: 10px 25px; }
+.confirm-box.chmod ul:last-of-type { margin-bottom: 38px; }
+.confirm-box.chmod li { list-style-type: none; }
+
+
 /*.confirm-box.archive { height: 468px; }*/
 .confirm-box.archive .message { margin-bottom: 38px; }
 .confirm-box.archive.warning .controls,

+ 1 - 1
web/edit/file/index.php

@@ -74,7 +74,7 @@ if (($_SESSION['user'] == 'admin') && (!empty($_SESSION['look']))) {
 <input type="submit" name="save" value="Save" class="save" />
 
 
-<textarea name="contents" class="editor" id="editor" rows="4" style="display:none;width: 100%; height: 100%;"><?php echo $content ?></textarea>
+<textarea name="contents" class="editor" id="editor" rows="4" style="display:none;width: 100%; height: 100%;"><?=htmlentities($content)?></textarea>
 
 </form>
 

+ 1 - 359
web/file_manager/files.php

@@ -1,359 +1 @@
-<?php
-
-//define(MAX_FILES_TO_SORT, 5);
-//define(LISTING_TIMEOUT, 0.000001);
-define(LISTING_TIMEOUT, 5);
-
-
-
-
-//echo 'files: ';
-//$files = scandir(__DIR__);
-
-
-//echo '<pre>';
-//print_r($files);
-
-
-//$_REQUEST['sort_field'] = 'size';
-$_REQUEST['sort_field'] = 'name';
-//$_REQUEST['sort_field'] = 'atime';
-//$_REQUEST['sort_field'] = 'mtime';
-$_REQUEST['sort_desc'] = 1;
-
-
-
-/*
-+-  copy file / dir [ recursive ]
-+-  rename(move) file / dir
-+-  delete file / dir [ recursive ]
-+-  chmod file / dir
-+-  chown file / dir
-+-  create file
-+-  create dir
-*/
-
-switch($_REQUEST['action']){
-    case 'copy': fm_copy($_REQUEST['source'], $_REQUEST['dest']); break;
-    case 'rename': fm_rename($_REQUEST['source'], $_REQUEST['dest']); break;
-    case 'delete': fm_delete($_REQUEST['source']); break;
-    case 'chmod': fm_chmod($_REQUEST['source'], $_REQUEST['mode']); break;
-    case 'chown': fm_chown($_REQUEST['source'], $_REQUEST['uid'], $_REQUEST['gid']); break;
-    case 'create_file': fm_create_file($_REQUEST['source'], $_REQUEST['mode']  || FALSE); break;
-    case 'create_dir': fm_create_dir($_REQUEST['source'], $_REQUEST['mode'] || FALSE); break;
-
-    default: 
-	$pwd = $_REQUEST['path'] ? $_REQUEST['path'] : __DIR__;
-	$listing = dir_list($pwd, $_REQUEST['sort_field']); 
-	$writable = is_writable($pwd);
-
-	$pwd = array_merge(array('/'), explode('/', trim($pwd, '/'))); 
-
-	include('templates/filemanager.php'); 
-    break;
-}
-
-
-
-
-
-
-//echo $_GET['sort_field'];
-
-//    if(in_array($_GET['sort_field'], $available_sort_fields)){
-//	echo '1';
-//    }	
-
-
-
-
-
-
-
-
-/*
-  upload_file
-
-+  list_dir
-+-  copy file / dir [ recursive ]
-+-  rename(move) file / dir
-+-  delete file / dir [ recursive ]
-+-  chmod file / dir
-+-  chown file / dir
-+-  create file
-+-  create dir
-
-  view file / image
-  download file / image   
-*/
-
-
-
-function fm_create_file($filename){
-    if(is_file($filename))
-        return array('error' => 'file exists', 'code' => 1);
-
-    return !!fopen($filename, 'w');
-}
-
-
-function fm_create_dir($dirname){
-    if(is_dir($filename))
-        return array('error' => 'directory exists', 'code' => 1);
-
-    // TODO set parent directory mode
-    return mkdir($dirname);
-}
-
-
-function fm_chown($filename, $recursive = 0, $uid = FALSE, $gid = FALSE){
-    if(is_dir($filename) && $recursive){
-        $dir_handle  = opendir($dir);
-	while ($item = readdir($dir_handle)){
-    	    if (!in_array($item, array('.','..'))){
-		$new_item = $filename.'/'.$item;
-
-	        if($uid !== FALSE) chown($new_item, (int)$uid);
-		if($gid !== FALSE) chgrp($new_item, (int)$gid); 
-
-		if(is_dir($new_item)){
-		    fm_chown($new_item, $recursive, $uid, $gid);
-		}
-	    }
-	}
-    }else{
-        if($uid !== FALSE) chown($filename, (int)$uid);
-	if($gid !== FALSE) chgrp($filename, (int)$gid); 
-    }
-}
-
-
-function fm_chmod($filename, $recursive = 0, $mode){
-    if(is_dir($filename) && $recursive){
-        $dir_handle  = opendir($dir);
-	while ($item = readdir($dir_handle)){
-    	    if (!in_array($item, array('.','..'))){
-		$new_item = $filename.'/'.$item;
-	        chmod($new_item, octdec($mode));
-
-		if(is_dir($new_item)){
-		    fm_chmod($new_item, $recursive, $mode);
-		}
-	    }
-	}
-    }else{
-	chmod($filename, octdec($mode));
-    }
-}
-
-
-function fm_delete($filename){
-    if(is_dir($filename)){
-	foreach (
-	    $iterator = new RecursiveIteratorIterator(
-	    new RecursiveDirectoryIterator($filename, RecursiveDirectoryIterator::SKIP_DOTS),
-	    RecursiveIteratorIterator::SELF_FIRST) as $item
-	) {
-	  if ($item->isDir()) {
-	    rmdir($item);
-//	    mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName(), decoct(fileperms($item->getPerms())));
-	  } else {
-	    unlink($item);
-//	    copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
-	  }
-	}
-    }else{
-	return unlink($filename);
-    }
-}
-
-
-function fm_rename($source, $dest){
-    return rename($source, $dest);
-}
-
-
-function fm_copy($source, $dest){
-    if(is_dir($source)){
-	foreach (
-	    $iterator = new RecursiveIteratorIterator(
-	    new RecursiveDirectoryIterator($source, RecursiveDirectoryIterator::SKIP_DOTS),
-	    RecursiveIteratorIterator::SELF_FIRST) as $item
-	) {
-	  if ($item->isDir()) {
-	    // TODO set dir perms 
-	    mkdir($dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName(), decoct(fileperms($item->getPerms())));
-	  } else {
-	    copy($item, $dest . DIRECTORY_SEPARATOR . $iterator->getSubPathName());
-	  }
-	}
-    
-    }else{
-	return copy($source, $dest);
-    }
-}
-
-
-function list_dir(){
-    $dir_iterator = new RecursiveDirectoryIterator("/path");
-    $iterator = new RecursiveIteratorIterator($dir_iterator, RecursiveIteratorIterator::SELF_FIRST);
-    // could use CHILD_FIRST if you so wish
-
-    foreach ($iterator as $file) {
-	echo $file, "\n";
-    }
-
-    $size = 0;
-    foreach ($iterator as $file) {
-	if ($file->isFile()) {
-    	    echo substr($file->getPathname(), 27) . ": " . $file->getSize() . " B; modified " . date("Y-m-d", $file->getMTime()) . "\n";
-            $size += $file->getSize();
-	}
-    }
-
-    echo "\nTotal file size: ", $size, " bytes\n";
-}
-
-
-
-
-/// fast removing directory 
-function rmrf($dir) {
-    
-    foreach (glob($dir) as $file) {
-        if (is_dir($file)) {
-            rmrf("$file/*");
-            rmdir($file);
-        } else {
-            unlink($file);
-        }
-    }
-}
-
-
-
-
-function dir_list($dir, $sort = 0)
-{
-    $sort_order_for_filename = SORT_ASC;
-    //$available_sort_fields = array('size, type', 'mtime', 'atime', 'owner', 'group');
-    $available_sort_fields = array('name', 'size', 'type', 'mtime', 'atime', 'owner', 'group');
-    $sort_order = SORT_ASC;
-
-    if ($dir[strlen($dir)-1] != '/') $dir .= '/';
-    if (!is_dir($dir)) return array();
-
-    $start = microtime(TRUE);
-
-    $listing = array('dirs' => array(), 'files' => array(), 'dir_names' => array(), 'file_names' => array() ,'count' => 0, 'timeout_exeeded' => 0, 'time' => 0);
-    $dir_handle  = opendir($dir);
-    $dir_objects = array();
-    while ($object = readdir($dir_handle)){
-        if (!in_array($object, array('.','..'))){
-            $filename    = $dir . $object;
-	    $time = microtime(true) - $start;
-	    if($time <= LISTING_TIMEOUT){
-    		$stats = stat($filename);
-    		$mode = explain_mode($stats['mode']);
-		$perms = decoct(fileperms($filename));
-	        $item = array(
-            	    'name' => $object,
-		    'size' => $stats['size'],
-            	    'mode' => array('owner' => $mode['owner'], 'group' => $mode['owner'], 'other' => $mode['owner']),
-            	    'perms' => decoct($stats['mode']),
-            	    'type' => $mode['type'],
-            	    'mtime' => $stats['mtime'],
-            	    'atime' => $stats['atime'],
-            	    'mdate_human' => date("Y F d", $stats['mtime']),
-            	    'mtime_human' => date("H:i:s", $stats['mtime']),
-            	    'adate_human' => date("Y F d", $stats['atime']),
-            	    'atime_human' => date("H:i:s", $stats['atime']),
-	    	    'nlink' => $stats['nlink'],
-	    	    'owner' => posix_getpwuid($stats['uid'])['name'],
-	    	    'group' => posix_getgrgid($stats['gid'])['name']
-            	);
-	    }else{
-		$listing['timeout_exeeded'] = TRUE;
-		if(is_dir($filename)){   $type = 'd';
-		}else{   $type = '-'; }
-
-	        $item = array(
-            	    'name' => $object,
-		    'size' => FALSE,
-            	    'mode' => array('owner' => FALSE, 'group' => FALSE, 'other' => FALSE),
-            	    'type' => $type,
-            	    'mtime' => FALSE,
-            	    'atime' => FALSE,
-            	    'mdate_human' => FALSE,
-            	    'mtime_human' => FALSE,
-            	    'adate_human' => FALSE,
-            	    'atime_human' => FALSE,
-	    	    'nlink' => FALSE,
-	    	    'owner' => FALSE,
-	    	    'group' => FALSE
-            	);
-	    }
-
-
-	    $listing['count']++;
-
-	    if($item['type'] == 'd'){
-		$listing['dirs'][] = $item;
-		$listing['dir_names'][] = $item['name'];
-	    }else{
-		if($sort && !$listing['timeout_exeeded']){
-		    $listing[$sort][] = $item[$sort];
-		}
-		$listing['files'][] = $item;
-		$listing['file_names'][] = $item['name'];
-	    }
-        }
-    }
-    $listing['time'] = microtime(TRUE) - $start;
-
-
-    if(!$listing['timeout_exeeded']){
-	if(in_array($_REQUEST['sort_field'], $available_sort_fields)){
-	    if($_REQUEST['sort_desc']){
-		$sort_order = SORT_DESC;
-	    }
-	    array_multisort($listing[$_REQUEST['sort_field']], $sort_order, $listing['file_names'], $sort_order_for_filename, $listing['files']);
-	}
-	array_multisort($listing['dir_names'], $sort_order_for_filename, $listing['dirs']);
-    }
-
-    return $listing;
-}
-
-	
-function explain_mode($mode)
-{
-    $info = array();
-    
-    if     (($mode & 0xC000) == 0xC000) { $info['type'] = 's'; }
-    elseif (($mode & 0xA000) == 0xA000) { $info['type'] = 'l'; }
-    elseif (($mode & 0x8000) == 0x8000) { $info['type'] = '-'; }
-    elseif (($mode & 0x6000) == 0x6000) { $info['type'] = 'b'; }
-    elseif (($mode & 0x4000) == 0x4000) { $info['type'] = 'd'; }
-    elseif (($mode & 0x2000) == 0x2000) { $info['type'] = 'c'; }
-    elseif (($mode & 0x1000) == 0x1000) { $info['type'] = 'p'; }
-    else                                { $info['type'] = 'u'; }
-
-    $info['owner'] = (($mode & 0x0100) ? 'r' : '-');
-    $info['owner'] .= (($mode & 0x0080) ? 'w' : '-');
-    $info['owner'] .= (($mode & 0x0040) ? (($mode & 0x0800) ? 's' : 'x' ) : (($mode & 0x0800) ? 'S' : '-'));
-
-    // group
-    $info['group'] = (($mode & 0x0020) ? 'r' : '-');
-    $info['group'] .= (($mode & 0x0010) ? 'w' : '-');
-    $info['group'] .= (($mode & 0x0008) ? (($mode & 0x0400) ? 's' : 'x' ) : (($mode & 0x0400) ? 'S' : '-'));
-
-    // other
-    $info['other'] = (($mode & 0x0004) ? 'r' : '-');
-    $info['other'] .= (($mode & 0x0002) ? 'w' : '-');
-    $info['other'] .= (($mode & 0x0001) ? (($mode & 0x0200) ? 't' : 'x' ) : (($mode & 0x0200) ? 'T' : '-'));
-
-    return $info;
-}
-
-?>
+// absolete

+ 20 - 4
web/file_manager/fm_api.php

@@ -29,18 +29,19 @@ switch ($_REQUEST['action']) {
         $dir = $_REQUEST['dir'];
         print json_encode($fm->ls($dir));
         break;
+
     case 'check_file_type':
         $dir = $_REQUEST['dir'];
-        
         print json_encode($fm->checkFileType($dir));
         break;
+
     case 'rename_file':
         $dir = $_REQUEST['dir'];
         $item = $_REQUEST['item'];
         $target_name = $_REQUEST['target_name'];
-
         print json_encode($fm->renameFile($dir, $item, $target_name));
         break;
+
     case 'rename_directory':
         $dir = $_REQUEST['dir'];
         $item = $_REQUEST['item'];
@@ -48,27 +49,30 @@ switch ($_REQUEST['action']) {
 
         print json_encode($fm->renameDirectory($dir, $item, $target_name));
         break;
+
     case 'delete_files':
         $dir = $_REQUEST['dir'];
         $item = $_REQUEST['item'];
-
         print json_encode($fm->deleteItem($dir, $item));
         break;
+
     case 'create_file':
         $dir = $_REQUEST['dir'];
         $filename = $_REQUEST['filename'];
         print json_encode($fm->createFile($dir, $filename));
         break;
+
     case 'create_dir':
         $dir = $_REQUEST['dir'];
         $dirname = $_REQUEST['dirname'];
         print json_encode($fm->createDir($dir, $dirname));
         break;
-    
+
     case 'open_file':
         $dir = $_REQUEST['dir'];
         print json_encode($fm->open_file($dir));
         break;
+
     case 'copy_file':
         $dir = $_REQUEST['dir'];
         $target_dir = $_REQUEST['dir_target'];
@@ -76,6 +80,7 @@ switch ($_REQUEST['action']) {
         $item       = $_REQUEST['item'];
         print json_encode($fm->copyFile($item, $dir, $target_dir, $filename));
         break;
+
     case 'copy_directory':
         $dir = $_REQUEST['dir'];
         $target_dir = $_REQUEST['dir_target'];
@@ -83,6 +88,7 @@ switch ($_REQUEST['action']) {
         $item       = $_REQUEST['item'];
         print json_encode($fm->copyDirectory($item, $dir, $target_dir, $filename));
         break;
+
     case 'unpack_item':
         $dir = $_REQUEST['dir'];
         $target_dir = $_REQUEST['dir_target'];
@@ -90,6 +96,7 @@ switch ($_REQUEST['action']) {
         $item       = $_REQUEST['item'];
         print json_encode($fm->unpackItem($item, $dir, $target_dir, $filename));
         break;
+
     case 'pack_item':
         $dir = $_REQUEST['dir'];
         $target_dir = $_REQUEST['dir_target'];
@@ -97,10 +104,19 @@ switch ($_REQUEST['action']) {
         $item       = $_REQUEST['item'];
         print json_encode($fm->packItem($item, $dir, $target_dir, $filename));
         break;
+
     case 'backup':
         $path = $_REQUEST['path'];
         print json_encode($fm->backupItem($path));
         break;
+
+    case 'chmod_item':
+        $dir = $_REQUEST['dir'];
+        $item = $_REQUEST['item'];
+        $permissions = $_REQUEST['permissions'];
+        print json_encode($fm->chmodItem($dir, $item, $permissions));
+        break;
+
     default:
         //print json_encode($fm->init());
         break;

+ 64 - 77
web/file_manager/fm_core.php

@@ -1,7 +1,7 @@
 <?php
 
 class FileManager {
-    
+
     protected $delimeter = '|';
     protected $info_positions = array(
         'TYPE'          => 0,
@@ -13,38 +13,26 @@ class FileManager {
         'SIZE'          => 6,
         'NAME'          => 7
     );
-    
+
     protected $user  = null;
     public $ROOT_DIR = null;
-    
+
     public function setRootDir($root = null) {
         if (null != $root) {
-            $root = realpath($root);        
+            $root = realpath($root);
         }
         $this->ROOT_DIR = $root;
     }
-    
+
     public function __construct($user) {
         $this->user = $user;
     }
-    
-    /*public function init() {
-        $path = !empty($_REQUEST['dir']) ? $_REQUEST['dir'] : '';
-        $start_url = !empty($path) ? $this->ROOT_DIR . '/' . $path : $this->ROOT_DIR;
-        $listing = $this->getDirectoryListing($path);
-         
-        return $data = array(
-            'result'     => true,
-            'ROOT_DIR'   => $this->ROOT_DIR,
-            'TAB_A_PATH' => $start_url,
-            'TAB_B_PATH' => $this->ROOT_DIR, // second tab always loads home dir
-            'listing'    => $listing
-        );
-    }*/
-    
+
     public function checkFileType($dir) {
         $dir = $this->formatFullPath($dir);
+
         exec(VESTA_CMD . "v-get-fs-file-type {$this->user} {$dir}", $output, $return_var);
+
         $error = self::check_return_code($return_var, $output);
         if (empty($error)) {
             return array(
@@ -59,7 +47,7 @@ class FileManager {
             );
         }
     }
-    
+
     public function formatFullPath($path_part = '') {
         if (substr($path_part, 0, strlen($this->ROOT_DIR)) === $this->ROOT_DIR) {
             $path = $path_part;
@@ -71,13 +59,13 @@ class FileManager {
         //$path = str_replace(' ', '\ ', $path);
         return escapeshellarg($path);
     }
-    
+
     function deleteItem($dir, $item) {
         $dir = $this->formatFullPath($item);
         exec (VESTA_CMD . "v-delete-fs-directory {$this->user} {$dir}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -89,29 +77,16 @@ class FileManager {
                 'message'  => $error
             );
         }
-        
-        /*if (is_readable($item)) {
-            unlink($item);
-        }
-        if (is_readable($item)) {
-            return array(
-                'result'  => false,
-                'message' => 'item was not deleted'
-            );
-        }
-        return array(
-            'result' => true
-        );*/
     }
-    
+
     function copyFile($item, $dir, $target_dir, $filename) {
         $src = $this->formatFullPath($item);
         $dst = $this->formatFullPath($target_dir);
-    
+
         exec (VESTA_CMD . "v-copy-fs-file {$this->user} {$src} {$dst}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -124,17 +99,15 @@ class FileManager {
             );
         }
     }
-    
-    
+
     function copyDirectory($item, $dir, $target_dir, $filename) {
         $src = $this->formatFullPath($item);
         $dst = $this->formatFullPath($target_dir);
-    
-        exec (VESTA_CMD . "v-copy-fs-directory {$this->user} {$src} {$dst}", $output, $return_var);
 
+        exec (VESTA_CMD . "v-copy-fs-directory {$this->user} {$src} {$dst}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -147,25 +120,23 @@ class FileManager {
             );
         }
     }
-    
+
     static function check_return_code($return_var, $output) {
         if ($return_var != 0) {
             $error = implode('<br>', $output);
             return $error;
-            //if (empty($error)) $error = __('Error code:',$return_var);
-            //$_SESSION['error_msg'] = $error;
         }
-        
+
         return null;
     }
-    
+
     function createFile($dir, $filename) {
         $dir = $this->formatFullPath($dir . '/' . $filename);
 
         exec (VESTA_CMD . "v-add-fs-file {$this->user} {$dir}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -178,19 +149,17 @@ class FileManager {
             );
         }
     }
-    
+
     function packItem($item, $dir, $target_dir, $filename) {
         $item     = $this->formatFullPath($item);
         $dst_item = $this->formatFullPath($target_dir);
-        
+
         $dst_item = str_replace('.tar.gz', '', $dst_item);
-        
-        //$item = str_replace($dir . '/', '', $item);
-//var_dump(VESTA_CMD . "v-add-fs-archive {$this->user} {$dst_item} {$item}");die();
+
         exec (VESTA_CMD . "v-add-fs-archive {$this->user} {$dst_item} {$item}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -205,18 +174,16 @@ class FileManager {
     }
 
     function backupItem($item) {
-        
         $src_item     = $this->formatFullPath($item);
-        
+
         $dst_item_name = $item . '~' . date('Ymd_His');
 
         $dst_item = $this->formatFullPath($dst_item_name);
 
-//print VESTA_CMD . "v-add-fs-archive {$this->user} {$item} {$dst_item}";die();
         exec (VESTA_CMD . "v-copy-fs-file {$this->user} {$src_item} {$dst_item}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result'   => true,
@@ -231,7 +198,7 @@ class FileManager {
         }
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -244,7 +211,7 @@ class FileManager {
             );
         }
     }
-    
+
     function unpackItem($item, $dir, $target_dir, $filename) {
         $item     = $this->formatFullPath($item);
         $dst_item = $this->formatFullPath($target_dir);
@@ -252,7 +219,7 @@ class FileManager {
         exec (VESTA_CMD . "v-extract-fs-archive {$this->user} {$item} {$dst_item}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -265,17 +232,15 @@ class FileManager {
             );
         }
     }
-    
+
     function renameFile($dir, $item, $target_name) {
         $item     = $this->formatFullPath($dir . '/' . $item);
         $dst_item = $this->formatFullPath($dir . '/' . $target_name);
-        
-//        var_dump(VESTA_CMD . "v-move-fs-file {$this->user} {$item} {$dst_item}");die();
 
         exec (VESTA_CMD . "v-move-fs-file {$this->user} {$item} {$dst_item}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -288,6 +253,7 @@ class FileManager {
             );
         }
     }
+
     function renameDirectory($dir, $item, $target_name) {
         $item     = $this->formatFullPath($dir . $item);
         $dst_item = $this->formatFullPath($dir . $target_name);
@@ -298,11 +264,10 @@ class FileManager {
             );
         }
 
-
         exec (VESTA_CMD . "v-move-fs-directory {$this->user} {$item} {$dst_item}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -315,14 +280,14 @@ class FileManager {
             );
         }
     }
-    
+
     function createDir($dir, $dirname) {
         $dir = $this->formatFullPath($dir . '/' . $dirname);
 
         exec (VESTA_CMD . "v-add-fs-directory {$this->user} {$dir}", $output, $return_var);
 
         $error = self::check_return_code($return_var, $output);
-        
+
         if (empty($error)) {
             return array(
                 'result' => true
@@ -335,14 +300,36 @@ class FileManager {
             );
         }
     }
-    
+
+    function chmodItem($dir, $item, $permissions) {
+        $item       = $this->formatFullPath($dir . $item);
+        $permissions = escapeshellarg($permissions);
+
+        exec (VESTA_CMD . "v-change-fs-file-permission {$this->user} {$item} {$permissions}", $output, $return_var);
+
+        $error = self::check_return_code($return_var, $output);
+
+        if (empty($error)) {
+            return array(
+                'result' => true
+            );
+        }
+        else {
+            return array(
+                'result'   => false,
+                'message'  => $error
+            );
+        }
+    }
+
     function getDirectoryListing($dir = '') {
         $dir = $this->formatFullPath($dir);
+
         exec (VESTA_CMD . "v-list-fs-directory {$this->user} {$dir}", $output, $return_var);
 
         return $this->parseListing($output);
     }
-    
+
     public function ls($dir = '') {
         $listing = $this->getDirectoryListing($dir);
 
@@ -351,7 +338,7 @@ class FileManager {
             'listing' => $listing
         );
     }
-    
+
     public function open_file($dir = '') {
         $listing = $this->getDirectoryListing($dir);
 
@@ -360,14 +347,14 @@ class FileManager {
             'listing' => $listing
         );
     }
-    
+
     public function parseListing($raw) {
         $data = array();
         foreach ($raw as $o) {
             $info = explode($this->delimeter, $o);
             $data[] = array(
                 'type'          => $info[$this->info_positions['TYPE']],
-                'permissions'   => $info[$this->info_positions['PERMISSIONS']],
+                'permissions'   => str_pad($info[$this->info_positions['PERMISSIONS']], 3, "0", STR_PAD_LEFT),
                 'date'          => $info[$this->info_positions['DATE']],
                 'time'          => $info[$this->info_positions['TIME']],
                 'owner'         => $info[$this->info_positions['OWNER']],
@@ -376,7 +363,7 @@ class FileManager {
                 'name'          => $info[$this->info_positions['NAME']]
             );
         }
-        
+
         return $data;
     }
 

+ 245 - 23
web/js/file_manager.js

@@ -284,7 +284,7 @@ FM.openAndSync = function(dir, box, callback, forceOppositeSync) {
     if (tab == 'A') {
         opposite_tab = 'B';
     }
-    
+
     var oppositeSyncNeeded = false;
 
     if (FM.TAB_A_CURRENT_PATH == FM.TAB_B_CURRENT_PATH) {
@@ -751,19 +751,20 @@ FM.checkBulkStatus = function(bulkStatuses, acc) {
         if (msg != '') {
             status = false;
         }
-    }
 
-    if (status == true) {
-        FM.popupClose();
-    }
-    else {
-        $('#popup .results').show().html(msg);
-        $('#popup .ok').hide();
+        if (status == true) {
+            FM.popupClose();
+        }
+        else {
+            $('#popup .results').show().html(msg);
+            $('#popup .ok').hide();
+        }
+
+        var box = FM['TAB_' + tab];
+        var tab = FM.getTabLetter(FM.CURRENT_TAB);
+//        FM.openAndSync(FM['TAB_' + tab + '_CURRENT_PATH'], box, function(){}, true);
+        FM.openAndSync(FM['TAB_' + tab + '_CURRENT_PATH'], box, function(){}, false);
     }
-    
-    var box = FM['TAB_' + tab];
-    var tab = FM.getTabLetter(FM.CURRENT_TAB);
-    FM.openAndSync(FM['TAB_' + tab + '_CURRENT_PATH'], box, function(){}, true);
 }
 
 FM.bulkPopupClose = function() {
@@ -816,14 +817,13 @@ FM.bulkCopyDo = function() {
                 numberOfItems++;
             }
         });
-        
 
         var bulkStatuses = [];
         $.each(acc, function(i, o) {
             var ref = $(o);
             var src = $(ref).find('.source').val();
             src = $.parseJSON(src);
-          
+
             if (FM.isItemPseudo(src)) {
                 //cfr_html += '<div>'+src.name+'</div>';
                 return;
@@ -841,21 +841,21 @@ FM.bulkCopyDo = function() {
                 );*/
                 return;
             }
-            
+
             var dest = FM['TAB_' + opposite_tab + '_CURRENT_PATH' ];
             if (dest == '') {
                 dest = GLOBAL.ROOT_DIR;
             }
-            
+
             var action = FM.isItemFile(src) ? 'copy_file' : 'copy_directory';
-            
+
             var params = {
                 item: src.full_path,
                 filename: src.name,
                 dir:  FM['TAB_' + tab + '_CURRENT_PATH'],
                 dir_target: dest
             };
-            
+
             App.Ajax.request(action, params, function(reply) {
                 if (reply.result == true) {
                     bulkStatuses.push(true);
@@ -864,7 +864,7 @@ FM.bulkCopyDo = function() {
                     //FM.showError('copy-items', reply.message);
                     bulkStatuses.push(reply.message);
                 }
-                
+
                 FM.checkBulkStatus(bulkStatuses, acc);
             });
         });
@@ -888,7 +888,7 @@ FM.bulkCopy = function() {
                 numberOfItems++;
             }
         });
-        
+
         var tab = FM.getTabLetter(FM.CURRENT_TAB);
         var opposite_tab = 'A';
         if (tab == 'A') {
@@ -905,7 +905,6 @@ FM.bulkCopy = function() {
         //popup_bulk_copy
 
         FM.popupOpen(tpl.finalize());
-
     }
 }
 
@@ -1191,6 +1190,7 @@ FM.selectItem = function(item, box) {
     }
 
 }
+
 FM.isItemPseudo = function(item) {
     if (item.name == '.' || item.name == '..') {
         return true;
@@ -1199,7 +1199,7 @@ FM.isItemPseudo = function(item) {
 }
 
 FM.itemIsArchieve = function(item) {
-    
+
     if ($.inArray(item.filetype, FM.SUPPORTED_ARCHIEVES) != -1) {
         return true;
     }
@@ -1385,7 +1385,7 @@ FM.renameItems = function() {
 
     var src = selected.find('.source').val();
     src = $.parseJSON(src);
-    
+
     if (FM.isItemPseudo(src)) {
         return FM.displayError(
             App.Constants.FM_NO_FILE_OR_DIRECTORY_SELECTED
@@ -1398,6 +1398,228 @@ FM.renameItems = function() {
     FM.popupOpen(tpl.finalize());
 }
 
+FM.confirmChmod = function() {
+    var tab = FM.getTabLetter(FM.CURRENT_TAB);
+    var box = FM['TAB_' + tab];
+    var selected = $(FM['TAB_' + tab] ).find('.dir.active');
+    if (!selected) {
+        return FM.displayError(
+            App.Constants.FM_NO_FILE_OR_DIRECTORY_SELECTED
+        );
+    }
+
+    var src = selected.find('.source').val();
+    src = $.parseJSON(src);
+
+    var ro = $('input[name="read-by-owner"]').is(':checked') ? 4 : 0;
+    var wo = $('input[name="write-by-owner"]').is(':checked') ? 2 : 0;
+    var eo = $('input[name="execute-by-owner"]').is(':checked') ? 1 : 0;
+
+    var rg = $('input[name="read-by-group"]').is(':checked') ? 4 : 0;
+    var wg = $('input[name="write-by-group"]').is(':checked') ? 2 : 0;
+    var eg = $('input[name="execute-by-group"]').is(':checked') ? 1 : 0;
+
+    var re = $('input[name="read-by-others"]').is(':checked') ? 4 : 0;
+    var we = $('input[name="write-by-others"]').is(':checked') ? 2 : 0;
+    var ee = $('input[name="execute-by-others"]').is(':checked') ? 1 : 0;
+
+    var o = ro+wo+eo;
+    var g = rg+wg+eg;
+    var e = re+we+ee;
+
+    var permissions = o + "" + g + "" + e + "";
+
+    var action = FM.isItemFile(src) ? 'chmod_item' : 'chmod_item';
+
+    var params = {
+        dir:  FM['TAB_' + tab + '_CURRENT_PATH'] + '/',
+        item: src.name,
+        permissions: permissions
+    };
+
+    App.Ajax.request(action, params, function(reply) {
+        if (reply.result == true) {
+            FM.popupClose();
+            FM.openAndSync(FM['TAB_' + tab + '_CURRENT_PATH'], box);
+        }
+        else {
+            FM.showError('chmod-items', reply.message);
+        }
+    });
+}
+
+
+FM.confirmBulkChmod = function() {
+    var tab = FM.getTabLetter(FM.CURRENT_TAB);
+    var box = FM['TAB_' + tab];
+    var acc = $(FM.CURRENT_TAB).find('.dir.selected');
+    if (acc.length > 0) {
+        //FM.popupClose();
+
+        var cfr_html = '';
+        var numberOfItems = 0;
+        $.each(acc, function(i, o) {
+            var ref = $(o);
+            var src = $(ref).find('.source').val();
+            src = $.parseJSON(src);
+
+            if (!FM.isItemPseudo(o)) {
+                cfr_html += '<div>'+src.name+'</div>';
+                numberOfItems++;
+            }
+        });
+
+
+        var ro = $('input[name="read-by-owner"]').is(':checked') ? 4 : 0;
+        var wo = $('input[name="write-by-owner"]').is(':checked') ? 2 : 0;
+        var eo = $('input[name="execute-by-owner"]').is(':checked') ? 1 : 0;
+
+        var rg = $('input[name="read-by-group"]').is(':checked') ? 4 : 0;
+        var wg = $('input[name="write-by-group"]').is(':checked') ? 2 : 0;
+        var eg = $('input[name="execute-by-group"]').is(':checked') ? 1 : 0;
+
+        var re = $('input[name="read-by-others"]').is(':checked') ? 4 : 0;
+        var we = $('input[name="write-by-others"]').is(':checked') ? 2 : 0;
+        var ee = $('input[name="execute-by-others"]').is(':checked') ? 1 : 0;
+
+        var o = ro+wo+eo;
+        var g = rg+wg+eg;
+        var e = re+we+ee;
+
+        var permissions = o + "" + g + "" + e + "";
+
+        var action = 'chmod_item';
+        var tab = FM.getTabLetter(FM.CURRENT_TAB);
+
+
+        var bulkStatuses = [];
+        $.each(acc, function(i, o) {
+
+            var ref = $(o);
+            var src = $(ref).find('.source').val();
+            src = $.parseJSON(src);
+
+            if (FM.isItemPseudo(src)) {
+                return;
+            }
+
+            var params = {
+                dir:  FM['TAB_' + tab + '_CURRENT_PATH'] + '/',
+                item: src.name,
+                permissions: permissions
+            };
+
+            App.Ajax.request(action, params, function(reply) {
+                if (reply.result == true) {
+                    bulkStatuses.push(true);
+                }
+                else {
+                    bulkStatuses.push(reply.message);
+                }
+            });
+        });
+
+
+    var status = true;
+    var msg    = '';
+    $.each(bulkStatuses, function(i, o) {
+        if (o != true) {
+            msg += '<p>'+o+'</p>';
+        }
+    });
+
+    if (msg != '') {
+       status = false;
+    }
+
+    if (status == true) {
+        FM.popupClose();
+        FM.openAndSync(FM['TAB_' + tab + '_CURRENT_PATH'], box);
+    }
+    else {
+        $('#popup .message').show().html(msg);
+        $('#popup .ok').hide();
+    }
+
+//    FM.popupClose();
+//    FM.openAndSync(FM['TAB_' + tab + '_CURRENT_PATH'], box);
+    }
+}
+
+
+FM.chmodItems = function() {
+    var tab = FM.getTabLetter(FM.CURRENT_TAB);
+    var selected = $(FM['TAB_' + tab] ).find('.dir.selected');
+    if (selected.length == 0) {
+        return FM.displayError(
+            App.Constants.FM_NO_FILE_OR_DIRECTORY_SELECTED
+        );
+    }
+
+    if (selected.length > 1) { // multi operation
+        return FM.bulkChmod();
+    }
+
+
+    var src = selected.find('.source').val();
+    src = $.parseJSON(src);
+
+    var mode = selected.find('.mode').text();
+
+    var tpl = Tpl.get('popup_chmod', 'FM');
+    tpl.set(':FILENAME', src.name);
+
+    tpl.set(':READ_BY_OWNER', mode[0] & 4 ? "checked" : "");
+    tpl.set(':WRITE_BY_OWNER', mode[0] & 2 ? "checked" : "");
+    tpl.set(':EXECUTE_BY_OWNER', mode[0] & 1 ? "checked" : "");
+
+    tpl.set(':READ_BY_GROUP', mode[1] & 4 ? "checked" : "");
+    tpl.set(':WRITE_BY_GROUP', mode[1] & 2 ? "checked" : "");
+    tpl.set(':EXECUTE_BY_GROUP', mode[1] & 1 ? "checked" : "");
+
+    tpl.set(':READ_BY_OTHERS', mode[2] & 4 ? "checked" : "");
+    tpl.set(':WRITE_BY_OTHERS', mode[2] & 2 ? "checked" : "");
+    tpl.set(':EXECUTE_BY_OTHERS', mode[2] & 1 ? "checked" : "");
+
+    FM.popupOpen(tpl.finalize());
+}
+
+FM.bulkChmod = function() {
+    var acc = $(FM.CURRENT_TAB).find('.dir.selected');
+    if (acc.length > 0) {
+        FM.popupClose();
+
+        var cfr_html = '';
+        var numberOfItems = 0;
+        $.each(acc, function(i, o) {
+            var ref = $(o);
+            var src = $(ref).find('.source').val();
+            src = $.parseJSON(src);
+
+            if (!FM.isItemPseudo(src)) {
+                cfr_html += '<div>'+src.name+'</div>';
+                numberOfItems++;
+            }
+        });
+
+        var tab = FM.getTabLetter(FM.CURRENT_TAB);
+        var opposite_tab = 'A';
+        if (tab == 'A') {
+            opposite_tab = 'B';
+        }
+        var dest = FM['TAB_' + opposite_tab + '_CURRENT_PATH' ];
+        if (dest == '') {
+            dest = GLOBAL.ROOT_DIR;
+        }
+
+        var tpl = Tpl.get('popup_bulk_chmod', 'FM');
+        tpl.set(':NUMBER_OF_ITEMS', numberOfItems);
+        //popup_bulk_copy
+
+        FM.popupOpen(tpl.finalize());
+    }
+}
+
 FM.isPopupOpened = function() {
     return $('#popup').length > 0 ? true : false;
 }