1
0
mirror of https://github.com/misterunknown/ifm.git synced 2025-08-16 21:13:59 +02:00
This commit is contained in:
Jannis Rondorf
2017-07-28 14:29:31 +02:00
8 changed files with 345 additions and 39 deletions

View File

@@ -51,8 +51,10 @@ RUN set -xe; \
php5-zlib \ php5-zlib \
php5-posix \ php5-posix \
php5-soap \ php5-soap \
php5-openssl \
php5-pcntl \ php5-pcntl \
php5-xml \ php5-xml \
php5-phar \
php5-zip php5-zip
RUN mkdir -p /run/apache2 \ RUN mkdir -p /run/apache2 \

View File

@@ -13,20 +13,34 @@ The IFM uses the following resources:
* create/edit files and directories * create/edit files and directories
* copy/move files and directories * copy/move files and directories
* download files and directories * download files and directories
* upload files directly or via URL * upload files directly, via URL or per drag & drop
* extract zip archives * extract archives (tar, tgz, tar.gz, tar.bz2, zip)
* change permissions * change permissions
* image preview * image preview
## requirements ## requirements
| Client | Server | * Client
|:--------------------------------- |:------------------------------------------------------------ | * HTML5 and CSS3 compatible browser
| HTML5 and CSS3 compatible browser | PHP >= 5.5 (only if using auth; if not PHP 5.4 works either) | * activated javascript
| activated JavaScript | optional: cURL extention (for remote upload) | * Server
* PHP >= 5.5
* extensions
* bz2
* curl (for remote upload)
* json
* openssl (for remote uploads from https sources)
* phar (for tar support)
* zip
* zlib
## installation ## installation
Just copy the ifm.php to your webspace - thats all :) Just copy the ifm.php to your webspace - thats all :)
## security information
The IFM is usually locked to it's own directory, so you are not able to go above. You can change that by setting the `root_dir` in the scripts [configuration](https://github.com/misterunknown/ifm/wiki/Configuration).
By default, it is not allowed to show or edit the `.htaccess` file. This is because you can configure the IFM via environment variables. Thus if anyone has the ability to edit the `.htaccess` file, he could overwrite the active configuration. [See also](https://github.com/misterunknown/ifm/wiki/Configuration).
## key bindings ## key bindings
* <kbd>e</kbd> - edit / extract current file * <kbd>e</kbd> - edit / extract current file
* <kbd>h</kbd><kbd>j</kbd><kbd>k</kbd><kbd>l</kbd> - vim-style navigation (alternative to arrow keys) * <kbd>h</kbd><kbd>j</kbd><kbd>k</kbd><kbd>l</kbd> - vim-style navigation (alternative to arrow keys)
@@ -37,6 +51,7 @@ Just copy the ifm.php to your webspace - thats all :)
* <kbd>a</kbd> - show ajax request dialog * <kbd>a</kbd> - show ajax request dialog
* <kbd>F</kbd> - new file * <kbd>F</kbd> - new file
* <kbd>D</kbd> - new directory * <kbd>D</kbd> - new directory
* <kbd>c</kbd><kbd>m</kbd> - show copy/move dialog
* <kbd>space</kbd> - select a highlighted item * <kbd>space</kbd> - select a highlighted item
* <kbd>del</kbd> - delete selected files * <kbd>del</kbd> - delete selected files
* <kbd>Enter</kbd> - open a file or change to the directory * <kbd>Enter</kbd> - open a file or change to the directory
@@ -117,6 +132,3 @@ listed below:
## issues ## issues
Currently there are no known issues. If you find any flaws please let me know. Currently there are no known issues. If you find any flaws please let me know.
## security information
By default, the IFM is locked to it's own directory, so you are not able to go above. You can change that by setting the $root_dir in the scripts configuration.

File diff suppressed because one or more lines are too long

117
ifm.php

File diff suppressed because one or more lines are too long

View File

@@ -486,12 +486,30 @@ function IFM( params ) {
url: self.api, url: self.api,
type: "POST", type: "POST",
data: ({ data: ({
api: "getFolderTree", api: "getFolders"
dir: self.currentDir
}), }),
dataType: "json", dataType: "json",
success: function( data ) { success: function( data ) {
$( '#copyMoveTree' ).treeview( { data: data, levels: 0, expandIcon: "icon icon-folder-empty", collapseIcon: "icon icon-folder-open-empty" } ); $( '#copyMoveTree' ).treeview({
data: data,
levels: 1,
expandIcon: "icon icon-folder-empty",
emptyIcon: "icon icon-folder-empty",
collapseIcon: "icon icon-folder-open-empty",
loadingIcon: "icon icon-spin5",
lazyLoad: function( n, cb ) {
$.ajax({
url: self.api,
type: "POST",
data: {
api: "getFolders",
dir: n.dataAttr.path
},
dataType: "json",
success: cb
});
}
});
}, },
error: function() { self.hideModal(); self.showMessage( "Error while fetching the folder tree.", "e" ) } error: function() { self.hideModal(); self.showMessage( "Error while fetching the folder tree.", "e" ) }
}); });

View File

@@ -1 +1 @@
.treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed} .treeview .list-group-item{cursor:pointer}.treeview span.indent{margin-left:10px;margin-right:10px}.treeview span.icon,.treeview span.image{width:12px;margin-right:5px}.treeview .node-disabled{color:silver;cursor:not-allowed}.treeview .node-hidden{display:none}.treeview span.image{display:inline-block;height:1.19em;vertical-align:middle;background-size:contain;background-repeat:no-repeat;line-height:1em}

File diff suppressed because one or more lines are too long

View File

@@ -47,7 +47,7 @@ class IFM {
"showowner" => 1, "showowner" => 1,
"showgroup" => 1, "showgroup" => 1,
"showpermissions" => 2, "showpermissions" => 2,
"showhtdocs" => 1, "showhtdocs" => 0,
"showhiddenfiles" => 1, "showhiddenfiles" => 1,
"showpath" => 0, "showpath" => 0,
); );
@@ -61,7 +61,40 @@ class IFM {
if( session_status() !== PHP_SESSION_ACTIVE ) if( session_status() !== PHP_SESSION_ACTIVE )
session_start(); session_start();
$this->config = array_merge( $this->defaultconfig, $config ); // load the default config
$this->config = $this->defaultconfig;
// load config from environment variables
$this->config['auth'] = getenv('IFM_AUTH') !== false ? getenv('IFM_AUTH') : $this->config['auth'] ;
$this->config['auth_source'] = getenv('IFM_AUTH_SOURCE') !== false ? getenv('IFM_AUTH_SOURCE') : $this->config['auth_source'] ;
$this->config['root_dir'] = getenv('IFM_ROOT_DIR') !== false ? getenv('IFM_ROOT_DIR') : $this->config['root_dir'] ;
$this->config['tmp_dir'] = getenv('IFM_TMP_DIR') !== false ? getenv('IFM_TMP_DIR') : $this->config['tmp_dir'] ;
$this->config['defaulttimezone'] = getenv('IFM_DEFAULTTIMEZONE') !== false ? getenv('IFM_DEFAULTTIMEZONE') : $this->config['defaulttimezone'] ;
$this->config['forbiddenChars'] = getenv('IFM_FORBIDDENCHARS') !== false ? str_split( getenv('IFM_FORBIDDENCHARS') ) : $this->config['forbiddenChars'] ;
$this->config['ajaxrequest'] = getenv('IFM_API_AJAXREQUEST') !== false ? getenv('IFM_API_AJAXREQUEST') : $this->config['ajaxrequest'] ;
$this->config['chmod'] = getenv('IFM_API_CHMOD') !== false ? getenv('IFM_API_CHMOD') : $this->config['chmod'] ;
$this->config['copymove'] = getenv('IFM_API_COPYMOVE') !== false ? getenv('IFM_API_COPYMOVE') : $this->config['copymove'] ;
$this->config['createdir'] = getenv('IFM_API_CREATEDIR') !== false ? getenv('IFM_API_CREATEDIR') : $this->config['createdir'] ;
$this->config['createfile'] = getenv('IFM_API_CREATEFILE') !== false ? getenv('IFM_API_CREATEFILE') : $this->config['createfile'] ;
$this->config['edit'] = getenv('IFM_API_EDIT') !== false ? getenv('IFM_API_EDIT') : $this->config['edit'] ;
$this->config['delete'] = getenv('IFM_API_DELETE') !== false ? getenv('IFM_API_DELETE') : $this->config['delete'] ;
$this->config['download'] = getenv('IFM_API_DOWNLOAD') !== false ? getenv('IFM_API_DOWNLOAD') : $this->config['download'] ;
$this->config['extract'] = getenv('IFM_API_EXTRACT') !== false ? getenv('IFM_API_EXTRACT') : $this->config['extract'] ;
$this->config['upload'] = getenv('IFM_API_UPLOAD') !== false ? getenv('IFM_API_UPLOAD') : $this->config['upload'] ;
$this->config['remoteupload'] = getenv('IFM_API_REMOTEUPLOAD') !== false ? getenv('IFM_API_REMOTEUPLOAD') : $this->config['remoteupload'] ;
$this->config['rename'] = getenv('IFM_API_RENAME') !== false ? getenv('IFM_API_RENAME') : $this->config['rename'] ;
$this->config['zipnload'] = getenv('IFM_API_ZIPNLOAD') !== false ? getenv('IFM_API_ZIPNLOAD') : $this->config['zipnload'] ;
$this->config['showlastmodified'] = getenv('IFM_GUI_SHOWLASTMODIFIED') !== false ? getenv('IFM_GUI_SHOWLASTMODIFIED') : $this->config['showlastmodified'] ;
$this->config['showfilesize'] = getenv('IFM_GUI_SHOWFILESIZE') !== false ? getenv('IFM_GUI_SHOWFILESIZE') : $this->config['showfilesize'] ;
$this->config['showowner'] = getenv('IFM_GUI_SHOWOWNER') !== false ? getenv('IFM_GUI_SHOWOWNER') : $this->config['showowner'] ;
$this->config['showgroup'] = getenv('IFM_GUI_SHOWGROUP') !== false ? getenv('IFM_GUI_SHOWGROUP') : $this->config['showgroup'] ;
$this->config['showpermissions'] = getenv('IFM_GUI_SHOWPERMISSIONS') !== false ? getenv('IFM_GUI_SHOWPERMISSIONS') : $this->config['showpermissions'] ;
$this->config['showhtdocs'] = getenv('IFM_GUI_SHOWHTDOCS') !== false ? getenv('IFM_GUI_SHOWHTDOCS') : $this->config['showhtdocs'] ;
$this->config['showhiddenfiles'] = getenv('IFM_GUI_SHOWHIDDENFILES') !== false ? getenv('IFM_GUI_SHOWHIDDENFILES') : $this->config['showhiddenfiles'] ;
$this->config['showpath'] = getenv('IFM_GUI_SHOWPATH') !== false ? getenv('IFM_GUI_SHOWPATH') : $this->config['showpath'] ;
// load config from passed array
$this->config = array_merge( $this->config, $config );
$templates = array(); $templates = array();
$templates['app'] = <<<'f00bar' $templates['app'] = <<<'f00bar'
@@ -143,6 +176,7 @@ f00bar;
public function getCSS() { public function getCSS() {
print ' print '
<style type="text/css">';?> @@@src/includes/bootstrap.min.css@@@ <?php print '</style> <style type="text/css">';?> @@@src/includes/bootstrap.min.css@@@ <?php print '</style>
<style type="text/css">';?> @@@src/includes/bootstrap-treeview.min.css@@@ <?php print '</style>
<style type="text/css">';?> @@@src/includes/fontello-embedded.css@@@ <?php print '</style> <style type="text/css">';?> @@@src/includes/fontello-embedded.css@@@ <?php print '</style>
<style type="text/css">';?> @@@src/includes/animation.css@@@ <?php print '</style> <style type="text/css">';?> @@@src/includes/animation.css@@@ <?php print '</style>
<style type="text/css">';?> @@@src/style.css@@@ <?php print '</style> <style type="text/css">';?> @@@src/style.css@@@ <?php print '</style>
@@ -196,6 +230,9 @@ f00bar;
} }
elseif( $_REQUEST["api"] == "getConfig" ) { elseif( $_REQUEST["api"] == "getConfig" ) {
$this->getConfig(); $this->getConfig();
}
elseif( $_REQUEST["api"] == "getFolders" ) {
$this->getFolders( $_REQUEST );
} elseif( $_REQUEST["api"] == "getTemplates" ) { } elseif( $_REQUEST["api"] == "getTemplates" ) {
echo json_encode( $this->templates ); echo json_encode( $this->templates );
} elseif( $_REQUEST["api"] == "getI18N" ) { } elseif( $_REQUEST["api"] == "getI18N" ) {
@@ -221,9 +258,7 @@ f00bar;
case "zipnload": $this->zipnload( $_REQUEST); break; case "zipnload": $this->zipnload( $_REQUEST); break;
case "remoteUpload": $this->remoteUpload( $_REQUEST ); break; case "remoteUpload": $this->remoteUpload( $_REQUEST ); break;
case "multidelete": $this->deleteMultipleFiles( $_REQUEST ); break; case "multidelete": $this->deleteMultipleFiles( $_REQUEST ); break;
case "getFolderTree": case "getFolderTree": $this->getFolderTree( $_REQUEST ); break;
echo json_encode( array_merge( array( 0 => array( "text" => "/ [root]", "nodes" => array(), "dataAttributes" => array( "path" => $this->getRootDir() ) ) ), $this->getFolderTreeRecursive( $this->getRootDir() ) ) );
break;
default: default:
echo json_encode( array( "status" => "ERROR", "message" => "Invalid api action given" ) ); echo json_encode( array( "status" => "ERROR", "message" => "Invalid api action given" ) );
break; break;
@@ -333,6 +368,50 @@ f00bar;
echo json_encode( $ret ); echo json_encode( $ret );
} }
private function getFolders( $d ) {
if( ! isset( $d['dir'] ) )
$d['dir'] = $this->getRootDir();
if( ! $this->isPathValid( $d['dir'] ) )
echo "[]";
else {
$ret = array();
foreach( glob( $this->pathCombine( $d['dir'], "*" ), GLOB_ONLYDIR ) as $dir ) {
array_push( $ret, array(
"text" => htmlspecialchars( basename( $dir ) ),
"lazyLoad" => true,
"dataAttr" => array( "path" => $dir )
));
}
sort( $ret );
if( $this->getScriptRoot() == realpath( $d['dir'] ) )
$ret = array_merge(
array(
0 => array(
"text" => "/ [root]",
"dataAttributes" => array( "path" => $this->getRootDir() )
)
),
$ret
);
echo json_encode( $ret );
}
}
private function getFolderTree( $d ) {
echo json_encode(
array_merge(
array(
0 => array(
"text" => "/ [root]",
"nodes" => array(),
"dataAttributes" => array( "path" => $this->getRootDir() )
)
),
$this->getFolderTreeRecursive( $d['dir'] )
)
);
}
private function getFolderTreeRecursive( $start_dir ) { private function getFolderTreeRecursive( $start_dir ) {
$ret = array(); $ret = array();
$start_dir = realpath( $start_dir ); $start_dir = realpath( $start_dir );
@@ -882,6 +961,7 @@ f00bar;
$tmp_i = pathinfo( $tmp_d ); $tmp_i = pathinfo( $tmp_d );
array_push( $tmp_missing_parts, $tmp_i['filename'] ); array_push( $tmp_missing_parts, $tmp_i['filename'] );
$tmp_d = dirname( $tmp_d ); $tmp_d = dirname( $tmp_d );
if( $tmp_d == dirname( $tmp_d ) ) break;
} }
$rpDir = $this->pathCombine( realpath( $tmp_d ), implode( "/", array_reverse( $tmp_missing_parts ) ) ); $rpDir = $this->pathCombine( realpath( $tmp_d ), implode( "/", array_reverse( $tmp_missing_parts ) ) );
$rpConfig = $this->getRootDir(); $rpConfig = $this->getRootDir();