mirror of
https://github.com/misterunknown/ifm.git
synced 2025-08-10 18:14:00 +02:00
Merge pull request #39 from misterunknown/js-templates
Js templates closes #39
This commit is contained in:
2
.gitattributes
vendored
Normal file
2
.gitattributes
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
ifm.php -diff
|
||||
build/* -diff
|
1240
build/ifm.js
Normal file
1240
build/ifm.js
Normal file
File diff suppressed because it is too large
Load Diff
2824
build/ifmlib.php
Normal file
2824
build/ifmlib.php
Normal file
File diff suppressed because one or more lines are too long
70
compiler.php
70
compiler.php
@@ -1,32 +1,56 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
/**
|
||||
* IFM compiler
|
||||
*
|
||||
* This script compiles all sources into one single file.
|
||||
*/
|
||||
|
||||
// This compiles the source files into one file
|
||||
chdir( realpath( dirname( __FILE__ ) ) );
|
||||
|
||||
$IFM_CONFIG = "src/config.php";
|
||||
$IFM_MAIN = "src/main.php";
|
||||
$IFM_OTHER_PHPFILES = array("src/ifmzip.php");
|
||||
$IFM_SRC_MAIN = "src/main.php";
|
||||
$IFM_SRC_PHPFILES = array( "src/ifmzip.php" );
|
||||
$IFM_SRC_JS = "src/ifm.js";
|
||||
|
||||
$filename = "ifm.php";
|
||||
$IFM_BUILD_STANDALONE = "ifm.php";
|
||||
$IFM_BUILD_LIB_PHP = "build/ifmlib.php";
|
||||
|
||||
// config
|
||||
file_put_contents($filename, file_get_contents($IFM_CONFIG));
|
||||
|
||||
// other php classes
|
||||
foreach ( $IFM_OTHER_PHPFILES as $file) {
|
||||
$content_file = file($file);
|
||||
unset($content_file[0]); // remove <?php line
|
||||
file_put_contents($filename, $content_file, FILE_APPEND);
|
||||
/**
|
||||
* Prepare main script
|
||||
*/
|
||||
$main = file_get_contents( $IFM_SRC_MAIN );
|
||||
$includes = NULL;
|
||||
preg_match_all( "/\@\@\@([^\@]+)\@\@\@/", $main, $includes, PREG_SET_ORDER );
|
||||
foreach( $includes as $file ) {
|
||||
$main = str_replace( $file[0], file_get_contents( $file[1] ), $main );
|
||||
}
|
||||
|
||||
// main
|
||||
$content_main = file($IFM_MAIN);
|
||||
unset($content_main[0]);
|
||||
$content_main = implode($content_main);
|
||||
$include_files = NULL;
|
||||
preg_match_all( "/\@\@\@([^\@]+)\@\@\@/", $content_main, $include_files, PREG_SET_ORDER );
|
||||
foreach( $include_files as $file ) {
|
||||
//echo $file[0]. " " .$file[1]."\n";
|
||||
$content_main = str_replace( $file[0], file_get_contents( $file[1] ), $content_main );
|
||||
/**
|
||||
* Add PHP files
|
||||
*/
|
||||
$phpincludes = array();
|
||||
foreach( $IFM_SRC_PHPFILES as $file ) {
|
||||
$content = file( $file );
|
||||
unset( $content[0] ); // remove <?php line
|
||||
$phpincludes = array_merge( $phpincludes, $content );
|
||||
}
|
||||
file_put_contents($filename, $content_main, FILE_APPEND);
|
||||
|
||||
/**
|
||||
* Build standalone script
|
||||
*/
|
||||
file_put_contents( $IFM_BUILD_STANDALONE, $main );
|
||||
file_put_contents( $IFM_BUILD_STANDALONE, $phpincludes, FILE_APPEND );
|
||||
file_put_contents( $IFM_BUILD_STANDALONE, array(
|
||||
'',
|
||||
'/**',
|
||||
' * start IFM',
|
||||
' */',
|
||||
'$ifm = new IFM();',
|
||||
'$ifm->run();'
|
||||
), FILE_APPEND );
|
||||
|
||||
/**
|
||||
* Build library
|
||||
*/
|
||||
file_put_contents( $IFM_BUILD_LIB_PHP, $main );
|
||||
file_put_contents( $IFM_BUILD_LIB_PHP, $phpincludes, FILE_APPEND );
|
||||
|
@@ -1,96 +0,0 @@
|
||||
<?php
|
||||
|
||||
/* =======================================================================
|
||||
* Improved File Manager
|
||||
* ---------------------
|
||||
* License: This project is provided under the terms of the MIT LICENSE
|
||||
* http://github.com/misterunknown/ifm/blob/master/LICENSE
|
||||
* =======================================================================
|
||||
*
|
||||
* config
|
||||
*/
|
||||
|
||||
class IFMConfig {
|
||||
|
||||
// 0 = no/not allowed;; 1 = yes/allowed;; default: no/forbidden;
|
||||
|
||||
// action controls
|
||||
const upload = 1; // allow uploads
|
||||
const remoteupload = 1; // allow remote uploads using cURL
|
||||
const delete = 1; // allow deletions
|
||||
const rename = 1; // allow renamings
|
||||
const edit = 1; // allow editing
|
||||
const chmod = 1; // allow to change rights
|
||||
const extract = 1; // allow extracting zip archives
|
||||
const download = 1; // allow to download files and skripts (even php scripts!)
|
||||
const selfdownload = 1; // allow to download this skript itself
|
||||
const createdir = 1; // allow to create directorys
|
||||
const createfile = 1; // allow to create files
|
||||
const zipnload = 1; // allow to zip and download directorys
|
||||
const copymove = 1; // allow to copy and move files and directories
|
||||
|
||||
// view controls
|
||||
const multiselect = 1; // implement multiselect of files and directories
|
||||
const showlastmodified = 0; // show the last modified date?
|
||||
const showfilesize = 1; // show filesize?
|
||||
const showowner = 1; // show file owner?
|
||||
const showgroup = 1; // show file group?
|
||||
const showpermissions = 2; // show permissions 0 -> not; 1 -> octal, 2 -> human readable
|
||||
const showhtdocs = 1; // show .htaccess and .htpasswd
|
||||
const showhiddenfiles = 1; // show files beginning with a dot (e.g. ".bashrc")
|
||||
const showpath = 0; // show absolute path
|
||||
|
||||
/*
|
||||
authentication
|
||||
|
||||
This provides a super simple authentication functionality. At the moment only one user can be
|
||||
configured. The credential information can be either set inline or read from a file. The
|
||||
password has to be a hash generated by PHPs password_hash function. The default credentials are
|
||||
admin:admin.
|
||||
|
||||
If you specify a file it should only contain one line, with the credentials in the following
|
||||
format:
|
||||
<username>:<passwordhash>
|
||||
|
||||
LDAP auth syntax
|
||||
|
||||
const auth_source = 'ldap;<ldap_sever_host>;<rootdn>';
|
||||
|
||||
The script will add "uid=<username>," to the rootdn for binding. If your ldap server
|
||||
does not use uid for usernames you can change it in the function checkCredentials.
|
||||
|
||||
examples:
|
||||
const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC';
|
||||
const auth_source = 'file;/path/to/file';
|
||||
const auth_source = 'ldap;<ldap_sever_host>:<rootdn>';
|
||||
*/
|
||||
const auth = 0;
|
||||
const auth_source = 'inline;admin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC';
|
||||
|
||||
/*
|
||||
root_dir - set a custom root directory instead of the script location
|
||||
|
||||
This option is highly experimental and should only be set if you definitely know what you do.
|
||||
Settings this option may cause black holes or other unwanted things. Use with special care.
|
||||
|
||||
default setting:
|
||||
const root_dir = "";
|
||||
*/
|
||||
const root_dir = "";
|
||||
const defaulttimezone = "Europe/Berlin"; // set default timezone
|
||||
|
||||
/**
|
||||
* Temp directory for zip files
|
||||
*
|
||||
* Default is the upload_tmp_dir which is set in the php.ini, but you may also set an different path
|
||||
*/
|
||||
const tmp_dir = "";
|
||||
|
||||
// development tools
|
||||
const ajaxrequest = 1; // formular to perform an ajax request
|
||||
|
||||
static function getConstants() {
|
||||
$oClass = new ReflectionClass(__CLASS__);
|
||||
return $oClass->getConstants();
|
||||
}
|
||||
}
|
1211
src/ifm.js
1211
src/ifm.js
File diff suppressed because it is too large
Load Diff
@@ -62,7 +62,7 @@ class IFMZip {
|
||||
/**
|
||||
* Unzip a zip file
|
||||
*/
|
||||
public function extract( $file, $destination="./" ) {
|
||||
public static function extract( $file, $destination="./" ) {
|
||||
$zip = new ZipArchive;
|
||||
$res = $zip->open( $file );
|
||||
if( $res === true ) {
|
||||
|
2
src/includes/ekko-lightbox.min.css
vendored
2
src/includes/ekko-lightbox.min.css
vendored
@@ -1,2 +0,0 @@
|
||||
.ekko-lightbox-nav-overlay a:focus,.ekko-lightbox-nav-overlay a>:focus{outline:0}.ekko-lightbox-container{position:relative}.ekko-lightbox-container>div.ekko-lightbox-item{position:absolute;top:0;left:0;width:100%;transition:opacity .5s ease-in-out;opacity:1}.ekko-lightbox-nav-overlay{z-index:1;position:absolute;top:0;left:0;width:100%;height:100%;display:-ms-flexbox;display:flex}.ekko-lightbox-nav-overlay a{-ms-flex:1;flex:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;opacity:0;transition:opacity .5s;color:#fff;font-size:30px;z-index:1}.ekko-lightbox-nav-overlay a>*{-ms-flex-positive:1;flex-grow:1}.ekko-lightbox-nav-overlay a span{padding:0 30px}.ekko-lightbox-nav-overlay a:last-child span{text-align:right}.ekko-lightbox-nav-overlay a:hover{text-decoration:none}.ekko-lightbox a:hover{opacity:1;text-decoration:none}.ekko-lightbox .modal-footer{text-align:left}.ekko-lightbox-loader{position:absolute;top:0;left:0;bottom:0;right:0;width:100%;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.ekko-lightbox-loader>div{width:40px;height:40px;position:relative;text-align:center}.ekko-lightbox-loader>div>div{width:100%;height:100%;border-radius:50%;background-color:#fff;opacity:.6;position:absolute;top:0;left:0;animation:a 2s infinite ease-in-out}.ekko-lightbox-loader>div>div:last-child{animation-delay:-1s}@keyframes a{0%,to{transform:scale(0);-webkit-transform:scale(0)}50%{transform:scale(1);-webkit-transform:scale(1)}}
|
||||
/*# sourceMappingURL=ekko-lightbox.min.css.map */
|
2
src/includes/ekko-lightbox.min.js
vendored
2
src/includes/ekko-lightbox.min.js
vendored
File diff suppressed because one or more lines are too long
1
src/includes/mustache.min.js
vendored
Normal file
1
src/includes/mustache.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
373
src/main.php
373
src/main.php
@@ -13,17 +13,55 @@
|
||||
error_reporting( E_ALL );
|
||||
ini_set( 'display_errors', 'OFF' );
|
||||
|
||||
|
||||
class IFM {
|
||||
const VERSION = '2.4.0';
|
||||
|
||||
public function __construct() {
|
||||
private $defaultconfig = array(
|
||||
// general config
|
||||
"auth" => 0,
|
||||
"auth_source" => 'inlineadmin:$2y$10$0Bnm5L4wKFHRxJgNq.oZv.v7yXhkJZQvinJYR2p6X1zPvzyDRUVRC',
|
||||
"root_dir" => "",
|
||||
"tmp_dir" => "",
|
||||
"defaulttimezone" => "Europe/Berlin",
|
||||
|
||||
// api controls
|
||||
"ajaxrequest" => 1,
|
||||
"chmod" => 1,
|
||||
"copymove" => 1,
|
||||
"createdir" => 1,
|
||||
"createfile" => 1,
|
||||
"edit" => 1,
|
||||
"delete" => 1,
|
||||
"download" => 1,
|
||||
"extract" => 1,
|
||||
"upload" => 1,
|
||||
"remoteupload" => 1,
|
||||
"rename" => 1,
|
||||
"zipnload" => 1,
|
||||
|
||||
// gui controls
|
||||
"showlastmodified" => 0,
|
||||
"showfilesize" => 1,
|
||||
"showowner" => 1,
|
||||
"showgroup" => 1,
|
||||
"showpermissions" => 2,
|
||||
"showhtdocs" => 1,
|
||||
"showhiddenfiles" => 1,
|
||||
"showpath" => 0,
|
||||
);
|
||||
|
||||
private $config = array();
|
||||
public $mode = "";
|
||||
|
||||
public function __construct( $config=array() ) {
|
||||
session_start();
|
||||
$this->config = array_merge( $this->defaultconfig, $config );
|
||||
}
|
||||
|
||||
/*
|
||||
this function contains the client-side application
|
||||
/**
|
||||
* This function contains the client-side application
|
||||
*/
|
||||
|
||||
public function getApplication() {
|
||||
print '<!DOCTYPE HTML>
|
||||
<html>
|
||||
@@ -31,93 +69,43 @@ class IFM {
|
||||
<title>IFM - improved file manager</title>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<style type="text/css">';?> @@@src/includes/bootstrap.min.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/includes/ekko-lightbox.min.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/includes/fontello-embedded.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/includes/bootstrap-treeview.min.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/style.css@@@ <?php print '</style>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">';
|
||||
$this->getCSS();
|
||||
print '
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">IFM</a>
|
||||
<button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" id="navbar">
|
||||
<form class="navbar-form navbar-left">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="currentDirLabel">Content of <span id="docroot">';
|
||||
print ( IFMConfig::showpath == 1 ) ? realpath( IFMConfig::root_dir ) : "/";
|
||||
print '</span></span><input class="form-control" id="currentDir" aria-describedby="currentDirLabel" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a id="refresh"><span title="refresh" class="icon icon-arrows-cw"></span> <span class="visible-xs">refresh</span></a></li>';
|
||||
if( IFMConfig::upload == 1 ) {
|
||||
print '<li><a id="upload"><span title="upload" class="icon icon-upload"></span> <span class="visible-xs">upload</span></a></li>';
|
||||
}
|
||||
if( IFMConfig::createfile == 1 ) {
|
||||
print '<li><a id="createFile"><span title="new file" class="icon icon-doc-inv"></span> <span class="visible-xs">new file</span></a></li>';
|
||||
}
|
||||
if( IFMConfig::createdir == 1 ) {
|
||||
print '<li><a id="createDir"><span title="new folder" class="icon icon-folder"></span> <span class="visible-xs">new folder</span></a></li>';
|
||||
}
|
||||
print '<li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="icon icon-down-open"></span></a><ul class="dropdown-menu" role="menu">';
|
||||
$options = false;
|
||||
if( IFMConfig::remoteupload == 1 ) {
|
||||
print '<li><a onclick="ifm.remoteUploadDialog();return false;"><span class="icon icon-upload-cloud"></span> remote upload</a></li>';
|
||||
$options = true;
|
||||
}
|
||||
if( IFMConfig::ajaxrequest == 1 ) {
|
||||
print '<li><a onclick="ifm.ajaxRequestDialog();return false;"><span class="icon icon-link-ext"></span> ajax request</a></li>';
|
||||
$options = true;
|
||||
}
|
||||
if( !$options ) print '<li>No options available</li>';
|
||||
print '</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<table id="filetable" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Filename</th>';
|
||||
if( IFMConfig::download == 1 ) print '<th><!-- column for download link --></th>';
|
||||
if( IFMConfig::showlastmodified == 1 ) print '<th>last modified</th>';
|
||||
if( IFMConfig::showfilesize == 1 ) print '<th>size</th>';
|
||||
if( IFMConfig::showpermissions > 0 ) print '<th class="hidden-xs">permissions</th>';
|
||||
if( IFMConfig::showowner == 1 && function_exists( "posix_getpwuid" ) ) print '<th class="hidden-xs hidden-sm">owner</th>';
|
||||
if( IFMConfig::showgroup == 1 && function_exists( "posix_getgrgid" ) ) print '<th class="hidden-xs hidden-sm hidden-md">group</th>';
|
||||
if( in_array( 1, array( IFMConfig::edit, IFMConfig::rename, IFMConfig::delete, IFMConfig::zipnload, IFMConfig::extract ) ) ) print '<th class="buttons"><!-- column for buttons --></th>';
|
||||
print '</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="panel panel-default footer"><div class="panel-body">IFM - improved file manager | ifm.php hidden | <a href="http://github.com/misterunknown/ifm">Visit the project on GitHub</a></div></div>
|
||||
</div>
|
||||
<div id="ifm"></div>';
|
||||
$this->getJS();
|
||||
print '
|
||||
<script>var ifm = new IFM(); ifm.init( "ifm" );</script>
|
||||
</body>
|
||||
</html>
|
||||
';
|
||||
}
|
||||
|
||||
public function getInlineApplication() {
|
||||
$this->getCSS();
|
||||
print '<div id="ifm"></div>';
|
||||
$this->getJS();
|
||||
}
|
||||
|
||||
public function getCSS() {
|
||||
print '
|
||||
<style type="text/css">';?> @@@src/includes/bootstrap.min.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/includes/fontello-embedded.css@@@ <?php print '</style>
|
||||
<style type="text/css">';?> @@@src/style.css@@@ <?php print '</style>
|
||||
';
|
||||
}
|
||||
|
||||
public function getJS() {
|
||||
print '
|
||||
<script>';?> @@@src/includes/ace.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/jquery.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/bootstrap.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/bootstrap-notify.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/ekko-lightbox.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/bootstrap-treeview.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/includes/mustache.min.js@@@ <?php print '</script>
|
||||
<script>';?> @@@src/ifm.js@@@ <?php print '</script>
|
||||
</body>
|
||||
</html>
|
||||
';
|
||||
}
|
||||
|
||||
@@ -137,24 +125,29 @@ class IFM {
|
||||
$this->getFiles( $_REQUEST["dir"] );
|
||||
else
|
||||
$this->getFiles( "" );
|
||||
} else {
|
||||
}
|
||||
elseif( $_REQUEST["api"] == "getConfig" ) {
|
||||
$this->getConfig();
|
||||
} elseif( $_REQUEST["api"] == "getTemplates" ) {
|
||||
echo json_encode( $this->getTemplates() );
|
||||
} else {
|
||||
if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) ) {
|
||||
switch( $_REQUEST["api"] ) {
|
||||
case "createDir": $this->createDir( $_REQUEST["dir"], $_REQUEST["dirname"] ); break;
|
||||
case "saveFile": $this->saveFile( $_REQUEST ); break;
|
||||
case "getContent": $this->getContent( $_REQUEST ); break;
|
||||
case "deleteFile": $this->deleteFile( $_REQUEST ); break;
|
||||
case "renameFile": $this->renameFile( $_REQUEST ); break;
|
||||
case "downloadFile": $this->downloadFile( $_REQUEST ); break;
|
||||
case "extractFile": $this->extractFile( $_REQUEST ); break;
|
||||
case "uploadFile": $this->uploadFile( $_REQUEST ); break;
|
||||
case "delete": $this->deleteFile( $_REQUEST ); break;
|
||||
case "rename": $this->renameFile( $_REQUEST ); break;
|
||||
case "download": $this->downloadFile( $_REQUEST ); break;
|
||||
case "extract": $this->extractFile( $_REQUEST ); break;
|
||||
case "upload": $this->uploadFile( $_REQUEST ); break;
|
||||
case "copyMove": $this->copyMove( $_REQUEST ); break;
|
||||
case "changePermissions": $this->changePermissions( $_REQUEST ); break;
|
||||
case "zipnload": $this->zipnload( $_REQUEST); break;
|
||||
case "remoteUpload": $this->remoteUpload( $_REQUEST ); break;
|
||||
case "deleteMultipleFiles": $this->deleteMultipleFiles( $_REQUEST ); break;
|
||||
case "multidelete": $this->deleteMultipleFiles( $_REQUEST ); break;
|
||||
case "getFolderTree":
|
||||
echo json_encode( array_merge( array( 0 => array( "text" => "/ [root]", "nodes" => array(), "dataAttributes" => array( "path" => realpath( IFMConfig::root_dir ) ) ) ), $this->getFolderTreeRecursive( IFMConfig::root_dir ) ) );
|
||||
echo json_encode( array_merge( array( 0 => array( "text" => "/ [root]", "nodes" => array(), "dataAttributes" => array( "path" => realpath( $this->config['root_dir'] ) ) ) ), $this->getFolderTreeRecursive( $this->config['root_dir'] ) ) );
|
||||
break;
|
||||
default:
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No valid api action given" ) );
|
||||
@@ -164,19 +157,23 @@ class IFM {
|
||||
print json_encode(array("status"=>"ERROR", "message"=>"No valid working directory"));
|
||||
}
|
||||
}
|
||||
exit( 0 );
|
||||
}
|
||||
|
||||
public function run() {
|
||||
public function run( $mode="standalone" ) {
|
||||
if ( $this->checkAuth() ) {
|
||||
// go to our root_dir
|
||||
if( ! is_dir( realpath( IFMConfig::root_dir ) ) || ! is_readable( realpath( IFMConfig::root_dir ) ) )
|
||||
if( ! is_dir( realpath( $this->config['root_dir'] ) ) || ! is_readable( realpath( $this->config['root_dir'] ) ) )
|
||||
die( "Cannot access root_dir.");
|
||||
else
|
||||
chdir( realpath( IFMConfig::root_dir ) );
|
||||
if ( ! isset($_REQUEST['api']) ) {
|
||||
$this->getApplication();
|
||||
} else {
|
||||
chdir( realpath( $this->config['root_dir'] ) );
|
||||
$this->mode = $mode;
|
||||
if ( isset( $_REQUEST['api'] ) || $mode == "api" ) {
|
||||
$this->handleRequest();
|
||||
} elseif( $mode == "standalone" ) {
|
||||
$this->getApplication();
|
||||
} else {
|
||||
$this->getInlineApplication();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -185,61 +182,53 @@ class IFM {
|
||||
api functions
|
||||
*/
|
||||
|
||||
private function getFiles($dir) {
|
||||
// SECURITY FUNCTION (check that we don't operate on a higher level that the script itself)
|
||||
$dir=$this->getValidDir($dir);
|
||||
// now we change in our target directory
|
||||
$this->chDirIfNecessary($dir);
|
||||
// unset our file and directory arrays
|
||||
unset($files); unset($dirs); $files = array(); $dirs = array();
|
||||
// so lets loop over our directory
|
||||
if ($handle = opendir(".")) {
|
||||
while (false !== ($result = readdir($handle))) { // this awesome statement is the correct way to loop over a directory :)
|
||||
if( $result == basename( $_SERVER['SCRIPT_NAME'] ) && $this->getScriptRoot() == getcwd() ) { } // we don't want to see the script itself
|
||||
elseif( ( $result == ".htaccess" || $result==".htpasswd" ) && IFMConfig::showhtdocs != 1 ) {} // check if we are granted to see .ht-docs
|
||||
elseif( $result == "." ) {} // the folder itself will also be invisible
|
||||
elseif( $result != ".." && substr( $result, 0, 1 ) == "." && IFMConfig::showhiddenfiles != 1 ) {} // eventually hide hidden files, if we should not see them
|
||||
elseif( ! @is_readable( $result ) ) {}
|
||||
else { // thats are the files we should see
|
||||
private function getFiles( $dir ) {
|
||||
$dir = $this->getValidDir( $dir );
|
||||
$this->chDirIfNecessary( $dir );
|
||||
|
||||
unset( $files ); unset( $dirs ); $files = array(); $dirs = array();
|
||||
|
||||
if( $handle = opendir( "." ) ) {
|
||||
while( false !== ( $result = readdir( $handle ) ) ) {
|
||||
if( $result == basename( $_SERVER['SCRIPT_NAME'] ) && $this->getScriptRoot() == getcwd() ) { }
|
||||
elseif( ( $result == ".htaccess" || $result==".htpasswd" ) && $this->config['showhtdocs'] != 1 ) {}
|
||||
elseif( $result == "." ) {}
|
||||
elseif( $result != ".." && substr( $result, 0, 1 ) == "." && $this->config['showhiddenfiles'] != 1 ) {}
|
||||
else {
|
||||
$item = array();
|
||||
$i = 0;
|
||||
$item["name"] = $result;
|
||||
$i++;
|
||||
if( is_dir($result) ) {
|
||||
$item["type"] = "dir";
|
||||
} else {
|
||||
$item["type"] = "file";
|
||||
}
|
||||
if( is_dir( $result ) ) {
|
||||
if( $result == ".." )
|
||||
$item["icon"] = "icon icon-up-open";
|
||||
else
|
||||
$item["icon"] = "icon icon-folder-empty";
|
||||
} else {
|
||||
$item["type"] = "file";
|
||||
$type = substr( strrchr( $result, "." ), 1 );
|
||||
$item["icon"] = $this->getTypeIcon( $type );
|
||||
}
|
||||
if( IFMConfig::showlastmodified == 1 ) { $item["lastmodified"] = date( "d.m.Y, G:i e", filemtime( $result ) ); }
|
||||
if( IFMConfig::showfilesize == 1 ) {
|
||||
$item["filesize"] = filesize( $result );
|
||||
if( $item["filesize"] > 1073741824 ) $item["filesize"] = round( ( $item["filesize"]/1073741824 ), 2 ) . " GB";
|
||||
elseif($item["filesize"]>1048576)$item["filesize"] = round( ( $item["filesize"]/1048576 ), 2 ) . " MB";
|
||||
elseif($item["filesize"]>1024)$item["filesize"] = round( ( $item["filesize"]/1024 ), 2 ) . " KB";
|
||||
else $item["filesize"] = $item["filesize"] . " Byte";
|
||||
if( $this->config['showlastmodified'] == 1 ) { $item["lastmodified"] = date( "d.m.Y, G:i e", filemtime( $result ) ); }
|
||||
if( $this->config['showfilesize'] == 1 ) {
|
||||
$item["size"] = filesize( $result );
|
||||
if( $item["size"] > 1073741824 ) $item["size"] = round( ( $item["size"]/1073741824 ), 2 ) . " GB";
|
||||
elseif($item["size"]>1048576)$item["size"] = round( ( $item["size"]/1048576 ), 2 ) . " MB";
|
||||
elseif($item["size"]>1024)$item["size"] = round( ( $item["size"]/1024 ), 2 ) . " KB";
|
||||
else $item["size"] = $item["size"] . " Byte";
|
||||
}
|
||||
if( IFMConfig::showpermissions > 0 ) {
|
||||
if( IFMConfig::showpermissions == 1 ) $item["fileperms"] = substr( decoct( fileperms( $result ) ), -3 );
|
||||
elseif( IFMConfig::showpermissions == 2 ) $item["fileperms"] = $this->filePermsDecode( fileperms( $result ) );
|
||||
if( $this->config['showpermissions'] > 0 ) {
|
||||
if( $this->config['showpermissions'] == 1 ) $item["fileperms"] = substr( decoct( fileperms( $result ) ), -3 );
|
||||
elseif( $this->config['showpermissions'] == 2 ) $item["fileperms"] = $this->filePermsDecode( fileperms( $result ) );
|
||||
if( $item["fileperms"] == "" ) $item["fileperms"] = " ";
|
||||
$item["filepermmode"] = ( IFMConfig::showpermissions == 1 ) ? "short" : "long";
|
||||
$item["filepermmode"] = ( $this->config['showpermissions'] == 1 ) ? "short" : "long";
|
||||
}
|
||||
if( IFMConfig::showowner == 1 ) {
|
||||
if( $this->config['showowner'] == 1 ) {
|
||||
if ( function_exists( "posix_getpwuid" ) && fileowner($result) !== false ) {
|
||||
$ownerarr = posix_getpwuid( fileowner( $result ) );
|
||||
$item["owner"] = $ownerarr['name'];
|
||||
} else $item["owner"] = false;
|
||||
}
|
||||
if( IFMConfig::showgroup == 1 ) {
|
||||
if( $this->config['showgroup'] == 1 ) {
|
||||
if( function_exists( "posix_getgrgid" ) && filegroup( $result ) !== false ) {
|
||||
$grouparr = posix_getgrgid( filegroup( $result ) );
|
||||
$item["group"] = $grouparr['name'];
|
||||
@@ -256,6 +245,13 @@ class IFM {
|
||||
echo json_encode( array_merge( $dirs, $files ) );
|
||||
}
|
||||
|
||||
private function getConfig() {
|
||||
$ret = $this->config;
|
||||
$ret['inline'] = ( $this->mode == "inline" ) ? true : false;
|
||||
$ret['isDocroot'] = ( realpath( $this->config['root_dir'] ) == dirname( __FILE__ ) ) ? "true" : "false";
|
||||
echo json_encode( $ret );
|
||||
}
|
||||
|
||||
private function getFolderTreeRecursive( $start_dir ) {
|
||||
$ret = array();
|
||||
$start_dir = realpath( $start_dir );
|
||||
@@ -271,7 +267,7 @@ class IFM {
|
||||
}
|
||||
|
||||
private function copyMove( $d ) {
|
||||
if( IFMConfig::copymove != 1 ) {
|
||||
if( $this->config['copymove'] != 1 ) {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No permission to copy or move files." ) );
|
||||
exit( 1 );
|
||||
}
|
||||
@@ -327,11 +323,11 @@ class IFM {
|
||||
private function saveFile(array $d) {
|
||||
if( isset( $d['filename'] ) && $d['filename'] != "" ) {
|
||||
// if you are not allowed to see .ht-docs you can't save one
|
||||
if( IFMConfig::showhtdocs != 1 && substr( $d['filename'], 0, 3 ) == ".ht" ) {
|
||||
if( $this->config['showhtdocs'] != 1 && substr( $d['filename'], 0, 3 ) == ".ht" ) {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "You are not allowed to edit or create htdocs" ) );
|
||||
}
|
||||
// same with hidden files
|
||||
elseif( IFMConfig::showhiddenfiles != 1 && substr( $d['filename'], 0, 1 ) == "." ) {
|
||||
elseif( $this->config['showhiddenfiles'] != 1 && substr( $d['filename'], 0, 1 ) == "." ) {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "You are not allowed to edit or create hidden files" ) );
|
||||
}
|
||||
elseif(strpos($d['filename'],'/')!==false) {
|
||||
@@ -358,7 +354,7 @@ class IFM {
|
||||
// gets the content of a file
|
||||
// notice: if the content is not JSON encodable it returns an error
|
||||
private function getContent( array $d ) {
|
||||
if( IFMConfig::edit != 1 ) echo json_encode( array( "status" => "ERROR", "message" => "No permission to edit files" ) );
|
||||
if( $this->config['edit'] != 1 ) echo json_encode( array( "status" => "ERROR", "message" => "No permission to edit files" ) );
|
||||
else {
|
||||
$this->chDirIfNecessary( $d['dir'] );
|
||||
if( file_exists( $d['filename'] ) ) {
|
||||
@@ -371,7 +367,7 @@ class IFM {
|
||||
|
||||
// deletes a file or a directory (recursive!)
|
||||
private function deleteFile( array $d ) {
|
||||
if( IFMConfig::delete != 1 ) {
|
||||
if( $this->config['delete'] != 1 ) {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No permission to delete files" ) );
|
||||
}
|
||||
else {
|
||||
@@ -396,7 +392,7 @@ class IFM {
|
||||
|
||||
// deletes a bunch of files or directories
|
||||
private function deleteMultipleFiles( array $d ) {
|
||||
if( IFMConfig::delete != 1 || IFMConfig::multiselect != 1 ) echo json_encode( array( "status" => "ERROR", "message" => "No permission to delete multiple files" ) );
|
||||
if( $this->config['delete'] != 1 ) echo json_encode( array( "status" => "ERROR", "message" => "No permission to delete multiple files" ) );
|
||||
else {
|
||||
$this->chDirIfNecessary( $d['dir'] );
|
||||
$err = array(); $errFLAG = -1; // -1 -> no files deleted; 0 -> at least some files deleted; 1 -> all files deleted
|
||||
@@ -429,15 +425,15 @@ class IFM {
|
||||
|
||||
// renames a file
|
||||
private function renameFile( array $d ) {
|
||||
if( IFMConfig::rename != 1 ) {
|
||||
if( $this->config['rename'] != 1 ) {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No permission to rename files" ) );
|
||||
} else {
|
||||
$this->chDirIfNecessary( $d['dir'] );
|
||||
if( strpos( $d['newname'], '/' ) !== false )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No slashes allowed in filenames" ) );
|
||||
elseif( IFMConfig::showhtdocs != 1 && ( substr( $d['newname'], 0, 3) == ".ht" || substr( $d['filename'], 0, 3 ) == ".ht" ) )
|
||||
elseif( $this->config['showhtdocs'] != 1 && ( substr( $d['newname'], 0, 3) == ".ht" || substr( $d['filename'], 0, 3 ) == ".ht" ) )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to rename this file" ) );
|
||||
elseif( IFMConfig::showhiddenfiles != 1 && ( substr( $d['newname'], 0, 1) == "." || substr( $d['filename'], 0, 1 ) == "." ) )
|
||||
elseif( $this->config['showhiddenfiles'] != 1 && ( substr( $d['newname'], 0, 1) == "." || substr( $d['filename'], 0, 1 ) == "." ) )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to rename file" ) );
|
||||
else {
|
||||
if( @rename( $d['filename'], $d['newname'] ) )
|
||||
@@ -450,21 +446,21 @@ class IFM {
|
||||
|
||||
// provides a file for downloading
|
||||
private function downloadFile( array $d ) {
|
||||
if( IFMConfig::download != 1 )
|
||||
if( $this->config['download'] != 1 )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to download files" ) );
|
||||
elseif( IFMConfig::showhtdocs != 1 && ( substr( $d['filename'], 0, 3 ) == ".ht" || substr( $d['filename'],0,3 ) == ".ht" ) )
|
||||
elseif( $this->config['showhtdocs'] != 1 && ( substr( $d['filename'], 0, 3 ) == ".ht" || substr( $d['filename'],0,3 ) == ".ht" ) )
|
||||
echo json_encode( array( "status" => "ERROR", "message"=>"Not allowed to download htdocs" ) );
|
||||
elseif( IFMConfig::showhiddenfiles != 1 && ( substr( $d['filename'], 0, 1 ) == "." || substr( $d['filename'],0,1 ) == "." ) )
|
||||
elseif( $this->config['showhiddenfiles'] != 1 && ( substr( $d['filename'], 0, 1 ) == "." || substr( $d['filename'],0,1 ) == "." ) )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to download hidden files" ) );
|
||||
else {
|
||||
$this->chDirIfNecessary( $d["dir"] );
|
||||
$this->file_download( $d['filename'] );
|
||||
$this->fileDownload( $d['filename'] );
|
||||
}
|
||||
}
|
||||
|
||||
// extracts a zip-archive
|
||||
private function extractFile( array $d ) {
|
||||
if( IFMConfig::extract != 1 )
|
||||
if( $this->config['extract'] != 1 )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No permission to extract files" ) );
|
||||
else {
|
||||
$this->chDirIfNecessary( $d['dir'] );
|
||||
@@ -492,16 +488,16 @@ class IFM {
|
||||
|
||||
// uploads a file
|
||||
private function uploadFile( array $d ) {
|
||||
if( IFMConfig::upload != 1 )
|
||||
if( $this->config['upload'] != 1 )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No permission to upload files" ) );
|
||||
elseif( !isset( $_FILES['file'] ) )
|
||||
echo json_encode( array( "file" => $_FILE,"files" => $_FILES ) );
|
||||
else {
|
||||
$this->chDirIfNecessary( $d['dir'] );
|
||||
$newfilename = ( isset( $d["newfilename"] ) && $d["newfilename"]!="" ) ? $d["newfilename"] : $_FILES['file']['name'];
|
||||
if( IFMConfig::showhtdocs != 1 && ( substr( $newfilename, 0, 3 ) == ".ht" || substr( $newfilename,0,3 ) == ".ht" ) )
|
||||
if( $this->config['showhtdocs'] != 1 && ( substr( $newfilename, 0, 3 ) == ".ht" || substr( $newfilename,0,3 ) == ".ht" ) )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to upload htdoc file" ) );
|
||||
elseif( IFMConfig::showhiddenfiles != 1 && ( substr( $newfilename, 0, 1 ) == "." || substr( $newfilename,0,1 ) == "." ) )
|
||||
elseif( $this->config['showhiddenfiles'] != 1 && ( substr( $newfilename, 0, 1 ) == "." || substr( $newfilename,0,1 ) == "." ) )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to upload hidden file" ) );
|
||||
else {
|
||||
if( $_FILES['file']['tmp_name'] ) {
|
||||
@@ -523,7 +519,7 @@ class IFM {
|
||||
|
||||
// change permissions of a file
|
||||
private function changePermissions( array $d ) {
|
||||
if( IFMConfig::chmod != 1 ) echo json_encode( array( "status" => "ERROR", "message" => "No rights to change permissions" ) );
|
||||
if( $this->config['chmod'] != 1 ) echo json_encode( array( "status" => "ERROR", "message" => "No rights to change permissions" ) );
|
||||
elseif( ! isset( $d["chmod"] )||$d['chmod']=="" ) echo json_encode( array( "status" => "ERROR", "message" => "Could not identify new permissions" ) );
|
||||
elseif( ! $this->isPathValid( $this->pathCombine( $d['dir'],$d['filename'] ) ) ) { echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to change the permissions" ) ); }
|
||||
else {
|
||||
@@ -562,7 +558,7 @@ class IFM {
|
||||
// zips a directory and provides it for downloading
|
||||
// it creates a temporary zip file in the current directory, so it has to be as much space free as the file size is
|
||||
private function zipnload( array $d ) {
|
||||
if( IFMConfig::zipnload != 1 )
|
||||
if( $this->config['zipnload'] != 1 )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No permission to download directories" ) );
|
||||
else {
|
||||
$this->chDirIfNecessary( $d['dir'] );
|
||||
@@ -572,7 +568,7 @@ class IFM {
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "Filename not allowed" ) );
|
||||
else {
|
||||
unset( $zip );
|
||||
$dfile = $this->pathCombine( IFMConfig::tmp_dir, uniqid( "ifm-tmp-" ) . ".zip" ); // temporary filename
|
||||
$dfile = $this->pathCombine( $this->config['tmp_dir'], uniqid( "ifm-tmp-" ) . ".zip" ); // temporary filename
|
||||
try {
|
||||
IFMZip::create( realpath( $d['filename'] ), $dfile, ( $d['filename'] == "." ) );
|
||||
if( $d['filename'] == "." ) {
|
||||
@@ -581,7 +577,7 @@ class IFM {
|
||||
else
|
||||
$d['filename'] = basename( getcwd() );
|
||||
}
|
||||
$this->file_download( $dfile, $d['filename'] . ".zip" );
|
||||
$this->fileDownload( $dfile, $d['filename'] . ".zip" );
|
||||
} catch ( Exception $e ) {
|
||||
echo "An error occured: " . $e->getMessage();
|
||||
} finally {
|
||||
@@ -593,7 +589,7 @@ class IFM {
|
||||
|
||||
// uploads a file from an other server using the curl extention
|
||||
private function remoteUpload( array $d ) {
|
||||
if( IFMConfig::remoteupload != 1 )
|
||||
if( $this->config['remoteupload'] != 1 )
|
||||
echo json_encode( array( "status" => "ERROR", "message" => "No permission to remote upload files" ) );
|
||||
elseif( !isset( $d['method'] ) || !in_array( $d['method'], array( "curl", "file" ) ) )
|
||||
echo json_encode( array( "status" => "error", "message" => "No valid method given. Valid methods: ['curl', 'file']" ) );
|
||||
@@ -646,7 +642,7 @@ class IFM {
|
||||
*/
|
||||
|
||||
public function checkAuth() {
|
||||
if( IFMConfig::auth == 1 && ( ! isset( $_SESSION['auth'] ) || $_SESSION['auth'] !== true ) ) {
|
||||
if( $this->config['auth'] == 1 && ( ! isset( $_SESSION['auth'] ) || $_SESSION['auth'] !== true ) ) {
|
||||
$login_failed = false;
|
||||
if( isset( $_POST["user"] ) && isset( $_POST["pass"] ) ) {
|
||||
if( $this->checkCredentials( $_POST["user"], $_POST["pass"] ) ) {
|
||||
@@ -677,7 +673,7 @@ class IFM {
|
||||
}
|
||||
|
||||
private function checkCredentials( $user, $pass ) {
|
||||
list( $src, $srcopt ) = explode( ";", IFMConfig::auth_source, 2 );
|
||||
list( $src, $srcopt ) = explode( ";", $this->config['auth_source'], 2 );
|
||||
switch( $src ) {
|
||||
case "inline":
|
||||
list( $uname, $hash ) = explode( ":", $srcopt );
|
||||
@@ -762,7 +758,7 @@ class IFM {
|
||||
return "";
|
||||
} else {
|
||||
$rpDir = realpath( $dir );
|
||||
$rpConfig = realpath( IFMConfig::root_dir );
|
||||
$rpConfig = realpath( $this->config['root_dir'] );
|
||||
if( $rpConfig == "/" )
|
||||
return $rpDir;
|
||||
elseif( $rpDir == $rpConfig )
|
||||
@@ -785,7 +781,7 @@ class IFM {
|
||||
$tmp_d = dirname( $tmp_d );
|
||||
}
|
||||
$rpDir = $this->pathCombine( realpath( $tmp_d ), implode( "/", array_reverse( $tmp_missing_parts ) ) );
|
||||
$rpConfig = ( IFMConfig::root_dir == "" ) ? realpath( dirname( __FILE__ ) ) : realpath( IFMConfig::root_dir );
|
||||
$rpConfig = ( $this->config['root_dir'] == "" ) ? realpath( dirname( __FILE__ ) ) : realpath( $this->config['root_dir'] );
|
||||
if( ! is_string( $rpDir ) || ! is_string( $rpConfig ) ) // can happen if open_basedir is in effect
|
||||
return false;
|
||||
elseif( $rpDir == $rpConfig )
|
||||
@@ -907,9 +903,9 @@ class IFM {
|
||||
|
||||
// check if filename is allowed
|
||||
private function allowedFileName( $f ) {
|
||||
if( IFMConfig::showhtdocs != 1 && substr( $f, 0, 3 ) == ".ht" )
|
||||
if( $this->config['showhtdocs'] != 1 && substr( $f, 0, 3 ) == ".ht" )
|
||||
return false;
|
||||
elseif( IFMConfig::showhiddenfiles != 1 && substr( $f, 0, 1 ) == "." )
|
||||
elseif( $this->config['showhiddenfiles'] != 1 && substr( $f, 0, 1 ) == "." )
|
||||
return false;
|
||||
elseif( ! $this->isPathValid( $f ) )
|
||||
return false;
|
||||
@@ -931,7 +927,7 @@ class IFM {
|
||||
else return true;
|
||||
}
|
||||
|
||||
private function file_download( $file, $name="" ) {
|
||||
private function fileDownload( $file, $name="" ) {
|
||||
header( 'Content-Description: File Transfer' );
|
||||
header( 'Content-Type: application/octet-stream' );
|
||||
header( 'Content-Disposition: attachment; filename="' . ( trim( $name ) == "" ? basename( $file ) : $name ) . '"' );
|
||||
@@ -949,12 +945,51 @@ class IFM {
|
||||
fclose($stdout_stream);
|
||||
}
|
||||
|
||||
///helper
|
||||
private function getTemplates() {
|
||||
$templates = array();
|
||||
$templates['app'] = <<<'f00bar'
|
||||
@@@src/templates/app.html@@@
|
||||
f00bar;
|
||||
$templates['filetable'] = <<<'f00bar'
|
||||
@@@src/templates/filetable.html@@@
|
||||
f00bar;
|
||||
$templates['file'] = <<<'f00bar'
|
||||
@@@src/templates/modal.file.html@@@
|
||||
f00bar;
|
||||
$templates['createdir'] = <<<'f00bar'
|
||||
@@@src/templates/modal.createdir.html@@@
|
||||
f00bar;
|
||||
$templates['ajaxrequest'] = <<<'f00bar'
|
||||
@@@src/templates/modal.ajaxrequest.html@@@
|
||||
f00bar;
|
||||
$templates['copymove'] = <<<'f00bar'
|
||||
@@@src/templates/modal.copymove.html@@@
|
||||
f00bar;
|
||||
$templates['createdir'] = <<<'f00bar'
|
||||
@@@src/templates/modal.createdir.html@@@
|
||||
f00bar;
|
||||
$templates['deletefile'] = <<<'f00bar'
|
||||
@@@src/templates/modal.deletefile.html@@@
|
||||
f00bar;
|
||||
$templates['extractfile'] = <<<'f00bar'
|
||||
@@@src/templates/modal.extractfile.html@@@
|
||||
f00bar;
|
||||
$templates['file'] = <<<'f00bar'
|
||||
@@@src/templates/modal.file.html@@@
|
||||
f00bar;
|
||||
$templates['multidelete'] = <<<'f00bar'
|
||||
@@@src/templates/modal.multidelete.html@@@
|
||||
f00bar;
|
||||
$templates['remoteupload'] = <<<'f00bar'
|
||||
@@@src/templates/modal.remoteupload.html@@@
|
||||
f00bar;
|
||||
$templates['renamefile'] = <<<'f00bar'
|
||||
@@@src/templates/modal.renamefile.html@@@
|
||||
f00bar;
|
||||
$templates['uploadfile'] = <<<'f00bar'
|
||||
@@@src/templates/modal.uploadfile.html@@@
|
||||
f00bar;
|
||||
|
||||
return $templates;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
start program
|
||||
*/
|
||||
|
||||
$ifm = new IFM();
|
||||
$ifm->run();
|
||||
|
@@ -7,15 +7,18 @@ body {
|
||||
font-size: 14pt;
|
||||
}
|
||||
|
||||
#filetable tr td:nth-child(5) {
|
||||
#filetable td:nth-child(5), #filetable th:nth-child(5) {
|
||||
text-align: center;
|
||||
}
|
||||
#filetable tr td:nth-child(6) {
|
||||
#filetable td:nth-child(6), #filetable th:nth-child(6) {
|
||||
text-align: center;
|
||||
}
|
||||
#filetable tr td:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
#filetable td:last-child a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
a { cursor: pointer !important; }
|
||||
|
||||
|
82
src/templates/app.html
Normal file
82
src/templates/app.html
Normal file
@@ -0,0 +1,82 @@
|
||||
<nav class="navbar navbar-inverse
|
||||
{{^config.inline}}
|
||||
navbar-fixed-top
|
||||
{{/config.inline}}
|
||||
">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<a class="navbar-brand">IFM</a>
|
||||
<button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse" id="navbar">
|
||||
<form class="navbar-form navbar-left">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="currentDirLabel">Content of <span id="docroot">{{showpath}}</span></span>
|
||||
<input class="form-control" id="currentDir" aria-describedby="currentDirLabel" type="text">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a id="refresh"><span title="refresh" class="icon icon-arrows-cw"></span> <span class="visible-xs">refresh</span></a></li>
|
||||
{{#config.upload}}
|
||||
<li><a id="upload"><span title="upload" class="icon icon-upload"></span> <span class="visible-xs">upload</span></a></li>
|
||||
{{/config.upload}}
|
||||
{{#config.createfile}}
|
||||
<li><a id="createFile"><span title="new file" class="icon icon-doc-inv"></span> <span class="visible-xs">new file</span></a></li>
|
||||
{{/config.createfile}}
|
||||
{{#config.createdir}}
|
||||
<li><a id="createDir"><span title="new folder" class="icon icon-folder"></span> <span class="visible-xs">new folder</span></a></li>
|
||||
{{/config.createdir}}
|
||||
<li class="dropdown"><a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"><span class="icon icon-down-open"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
{{#config.remoteupload}}
|
||||
<li><a id="buttonRemoteUpload"><span class="icon icon-upload-cloud"></span> remote upload</a></li>
|
||||
{{/config.remoteupload}}
|
||||
{{#config.ajaxrequest}}
|
||||
<li><a id="buttonAjaxRequest"><span class="icon icon-link-ext"></span> ajax request</a></li>
|
||||
{{/config.ajaxrequest}}
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="container">
|
||||
<table id="filetable" class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Filename</th>
|
||||
{{#config.download}}
|
||||
<th><!-- column for download link --></th>
|
||||
{{/config.download}}
|
||||
{{#config.showlastmodified}}
|
||||
<th>last modified</th>
|
||||
{{/config.showlastmodified}}
|
||||
{{#config.showfilesize}}
|
||||
<th>size</th>
|
||||
{{/config.showfilesize}}
|
||||
{{#config.showpermissions}}
|
||||
<th class="hidden-xs">permissions</th>
|
||||
{{/config.showpermissions}}
|
||||
{{#config.showowner}}
|
||||
<th class="hidden-xs hidden-sm">owner</th>
|
||||
{{/config.showowner}}
|
||||
{{#config.showgroup}}
|
||||
<th class="hidden-xs hidden-sm hidden-md">group</th>
|
||||
{{/config.showgroup}}
|
||||
<th class="buttons"><!-- column for buttons --></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="panel panel-default footer"><div class="panel-body">IFM - improved file manager | ifm.php hidden | <a href="http://github.com/misterunknown/ifm">Visit the project on GitHub</a></div></div>
|
||||
</div>
|
52
src/templates/filetable.html
Normal file
52
src/templates/filetable.html
Normal file
@@ -0,0 +1,52 @@
|
||||
<tbody>
|
||||
{{#items}}
|
||||
<tr class="clickable-row {{rowclasses}}" data-filename="{{name}}" data-eaction="{{eaction}}">
|
||||
<td>
|
||||
<a tabindex="0" id="{{guid}}" class="ifmitem" {{{tooltip}}} data-type="{{type}}">
|
||||
<span class="{{icon}}"></span>
|
||||
{{linkname}}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
{{#download.allowed}}
|
||||
<form id="d_{{guid}}">
|
||||
<input type="hidden" name="dir" value="{{download.currentDir}}">
|
||||
<input type="hidden" name="filename" value="{{download.name}}">
|
||||
<input type="hidden" name="api" value="{{download.action}}">
|
||||
</form>
|
||||
<a tabindex="0" name="start_download" data-guid="{{guid}}">
|
||||
<span class="{{download.icon}}"></span>
|
||||
</a>
|
||||
{{/download.allowed}}
|
||||
</td>
|
||||
{{#config.showlastmodified}}
|
||||
<td>{{lastmodified}}</td>
|
||||
{{/config.showlastmodified}}
|
||||
{{#config.showfilesize}}
|
||||
<td>{{size}}</td>
|
||||
{{/config.showfilesize}}
|
||||
{{#config.showpermissions}}
|
||||
<td class="hidden-xs">
|
||||
<input type="text" name="newpermissions" class="form-control {{filepermmode}}" value="{{fileperms}}" data-filename="{{name}}" {{readonly}}>
|
||||
</td>
|
||||
{{/config.showpermissions}}
|
||||
{{#config.showowner}}
|
||||
<td class="hidden-xs hidden-sm">
|
||||
{{owner}}
|
||||
</td>
|
||||
{{/config.showowner}}
|
||||
{{#config.showgroup}}
|
||||
<td class="hidden-xs hidden-sm hidden-md">
|
||||
{{group}}
|
||||
</td>
|
||||
{{/config.showgroup}}
|
||||
<td>
|
||||
{{#button}}
|
||||
<a tabindex="0" name="do-{{action}}" data-name="{{name}}">
|
||||
<span class="{{icon}}" title="{{title}}"</span>
|
||||
</a>
|
||||
{{/button}}
|
||||
</td>
|
||||
</tr>
|
||||
{{/items}}
|
||||
</tbody>
|
5
src/templates/misc.savequestion.html
Normal file
5
src/templates/misc.savequestion.html
Normal file
@@ -0,0 +1,5 @@
|
||||
<div id="savequestion">
|
||||
<label>Do you want to save this file?</label><br>
|
||||
<button id="buttonSave">Save</button>
|
||||
<button id="buttonDismiss">Dismiss</button>
|
||||
</div>
|
16
src/templates/modal.ajaxrequest.html
Normal file
16
src/templates/modal.ajaxrequest.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<form id="formAjaxRequest">
|
||||
<div class="modal-body">
|
||||
<fieldset>
|
||||
<label>URL</label><br>
|
||||
<input class="form-control" type="text" id="ajaxurl" required><br>
|
||||
<label>Data</label><br>
|
||||
<textarea class="form-control" id="ajaxdata"></textarea><br>
|
||||
<label>Method</label><br>
|
||||
<input type="radio" name="arMethod" value="GET">GET</input><input type="radio" name="arMethod" value="POST" checked="checked">POST</input><br>
|
||||
<button type="button" class="btn btn-success" id="buttonRequest">Request</button>
|
||||
<button type="button" class="btn btn-default" id="buttonClose">Close</button><br>
|
||||
<label>Response</label><br>
|
||||
<textarea class="form-control" id="ajaxresponse"></textarea>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
13
src/templates/modal.copymove.html
Normal file
13
src/templates/modal.copymove.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<form id="formCopyMove">
|
||||
<fieldset>
|
||||
<div class="modal-body">
|
||||
<label>Select destination:</label>
|
||||
<div id="copyMoveTree"><span class="icon icon-spin5"></span></div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" id="copyButton">copy</button>
|
||||
<button type="button" class="btn btn-default" id="moveButton">move</button>
|
||||
<button type="button" class="btn btn-default" id="cancelButton">cancel</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
12
src/templates/modal.createdir.html
Normal file
12
src/templates/modal.createdir.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<form id="formCreateDir">
|
||||
<div class="modal-body">
|
||||
<fieldset>
|
||||
<label>Directoy name:</label>
|
||||
<input class="form-control" type="text" name="dirname" value="" />
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" id="buttonSave">Save</button>
|
||||
<button type="button" class="btn btn-default" id="buttonCancel">Cancel</button>
|
||||
</div>
|
||||
</form>
|
9
src/templates/modal.deletefile.html
Normal file
9
src/templates/modal.deletefile.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<form id="formDeleteFile">
|
||||
<div class="modal-body">
|
||||
<label>Do you really want to delete the file {{filename}}?
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" id="buttonYes">Yes</button>
|
||||
<button type="button" class="btn btn-default" id="buttonNo">No</button>
|
||||
</div>
|
||||
</form>
|
23
src/templates/modal.extractfile.html
Normal file
23
src/templates/modal.extractfile.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<form id="formExtractFile">
|
||||
<fieldset>
|
||||
<div class="modal-body">
|
||||
<label>Extract {{filename}} to:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><input type="radio" name="extractTargetLocation" value="./" checked="checked"></span>
|
||||
<span class="form-control">./</span>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><input type="radio" name="extractTargetLocation" value="./{{destination}}"></span>
|
||||
<span class="form-control">./{{destination}}</span>
|
||||
</div>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><input type="radio" name="extractTargetLocation" value="custom"></span>
|
||||
<input id="extractCustomLocation" type="text" class="form-control" placeholder="custom location" value="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" id="buttonExtract">extract</button>
|
||||
<button type="button" class="btn btn-default" id="buttonCancel">cancel</button>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
21
src/templates/modal.file.html
Normal file
21
src/templates/modal.file.html
Normal file
@@ -0,0 +1,21 @@
|
||||
<form id="formFile">
|
||||
<div class="modal-body">
|
||||
<fieldset>
|
||||
<label>Filename:</label>
|
||||
<input type="text" class="form-control" name="filename" value="{{filename}}"><br>
|
||||
<div id="content" name="content"></div><br>
|
||||
<button type="button" class="btn btn-default" id="editoroptions">editor options</button>
|
||||
<div class="hide" id="editoroptions-head">options</div>
|
||||
<div class="hide" id="editoroptions-content">
|
||||
<input type="checkbox" id="editor-wordwrap"> word wrap</input><br>
|
||||
<input type="checkbox" id="editor-softtabs"> use soft tabs</input>
|
||||
<div class="input-group"><span class="input-group-addon">tabsize</span><input class="form-control" type="text" size="2" id="editor-tabsize"title="tabsize"></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" id="buttonSave" class="btn btn-default">Save</button>
|
||||
<button type="button" id="buttonSaveNotClose" class="btn btn-default">Save without closing</button>
|
||||
<button type="button" id="buttonClose" class="btn btn-default">Close</button>
|
||||
</div>
|
||||
</form>
|
9
src/templates/modal.multidelete.html
Normal file
9
src/templates/modal.multidelete.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<form id="formDeleteFiles">
|
||||
<div class="modal-body">
|
||||
<label>Do you really want to delete these {{count}} files?</label>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" id="buttonYes">Yes</button>
|
||||
<button type="button" class="btn btn-default" id="buttonNo">No</button>
|
||||
</div>
|
||||
</form>
|
16
src/templates/modal.remoteupload.html
Normal file
16
src/templates/modal.remoteupload.html
Normal file
@@ -0,0 +1,16 @@
|
||||
<form id="formRemoteUpload">
|
||||
<div class="modal-body">
|
||||
<fieldset>
|
||||
<label>Remote upload URL</label><br>
|
||||
<input class="form-control" type="text" id="url" name="url" required><br>
|
||||
<label>Filename (required)</label>
|
||||
<input class="form-control" type="text" id="filename" name="filename" required><br>
|
||||
<label>Method</label>
|
||||
<input type="radio" name="method" value="curl" checked="checked">cURL<input type="radio" name="method" value="file">file</input><br>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" id="buttonUpload">Upload</button>
|
||||
<button type="button" class="btn btn-default" id="buttonCancel">Cancel</button>
|
||||
</div>
|
||||
</form>
|
10
src/templates/modal.renamefile.html
Normal file
10
src/templates/modal.renamefile.html
Normal file
@@ -0,0 +1,10 @@
|
||||
<div class="modal-body">
|
||||
<form id="formRenameFile">
|
||||
<fieldset>
|
||||
<label>Rename {{filename}} to:</label>
|
||||
<input class="form-control" type="text" name="newname" /><br>
|
||||
<button class="btn btn-default" id="buttonRename">Rename</button>
|
||||
<button class="btn btn-default" id="buttonCancel">Cancel</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
14
src/templates/modal.uploadfile.html
Normal file
14
src/templates/modal.uploadfile.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<form id="formUploadFile">
|
||||
<div class="modal-body">
|
||||
<fieldset>
|
||||
<label>Upload file</label><br>
|
||||
<input class="file" type="file" name="ufile" id="ufile"><br>
|
||||
<label>new filename</label>
|
||||
<input class="form-control" type="text" name="newfilename"><br>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-default" id="buttonUpload">Upload</button>
|
||||
<button class="btn btn-default" id="buttonCancel">Cancel</button>
|
||||
</div>
|
||||
</form>
|
Reference in New Issue
Block a user