1
0
mirror of https://github.com/misterunknown/ifm.git synced 2025-08-13 11:34:00 +02:00

Merge pull request #39 from misterunknown/js-templates

Js templates

closes #39
This commit is contained in:
Marco Dickert
2017-07-06 17:26:30 +02:00
committed by GitHub
26 changed files with 6720 additions and 1543 deletions

2
.gitattributes vendored Normal file
View File

@@ -0,0 +1,2 @@
ifm.php -diff
build/* -diff

1240
build/ifm.js Normal file

File diff suppressed because it is too large Load Diff

2824
build/ifmlib.php Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,32 +1,56 @@
#!/usr/bin/env php #!/usr/bin/env php
<?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_SRC_MAIN = "src/main.php";
$IFM_MAIN = "src/main.php"; $IFM_SRC_PHPFILES = array( "src/ifmzip.php" );
$IFM_OTHER_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)); * Prepare main script
*/
// other php classes $main = file_get_contents( $IFM_SRC_MAIN );
foreach ( $IFM_OTHER_PHPFILES as $file) { $includes = NULL;
$content_file = file($file); preg_match_all( "/\@\@\@([^\@]+)\@\@\@/", $main, $includes, PREG_SET_ORDER );
unset($content_file[0]); // remove <?php line foreach( $includes as $file ) {
file_put_contents($filename, $content_file, FILE_APPEND); $main = str_replace( $file[0], file_get_contents( $file[1] ), $main );
} }
// main /**
$content_main = file($IFM_MAIN); * Add PHP files
unset($content_main[0]); */
$content_main = implode($content_main); $phpincludes = array();
$include_files = NULL; foreach( $IFM_SRC_PHPFILES as $file ) {
preg_match_all( "/\@\@\@([^\@]+)\@\@\@/", $content_main, $include_files, PREG_SET_ORDER ); $content = file( $file );
foreach( $include_files as $file ) { unset( $content[0] ); // remove <?php line
//echo $file[0]. " " .$file[1]."\n"; $phpincludes = array_merge( $phpincludes, $content );
$content_main = str_replace( $file[0], file_get_contents( $file[1] ), $content_main );
} }
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 );

2151
ifm.php

File diff suppressed because one or more lines are too long

View File

@@ -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

File diff suppressed because it is too large Load Diff

View File

@@ -62,7 +62,7 @@ class IFMZip {
/** /**
* Unzip a zip file * Unzip a zip file
*/ */
public function extract( $file, $destination="./" ) { public static function extract( $file, $destination="./" ) {
$zip = new ZipArchive; $zip = new ZipArchive;
$res = $zip->open( $file ); $res = $zip->open( $file );
if( $res === true ) { if( $res === true ) {

View File

@@ -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 */

File diff suppressed because one or more lines are too long

1
src/includes/mustache.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -13,17 +13,55 @@
error_reporting( E_ALL ); error_reporting( E_ALL );
ini_set( 'display_errors', 'OFF' ); ini_set( 'display_errors', 'OFF' );
class IFM { class IFM {
const VERSION = '2.4.0'; 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(); 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() { public function getApplication() {
print '<!DOCTYPE HTML> print '<!DOCTYPE HTML>
<html> <html>
@@ -31,93 +69,43 @@ class IFM {
<title>IFM - improved file manager</title> <title>IFM - improved file manager</title>
<meta charset="utf-8"> <meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">';
<style type="text/css">';?> @@@src/includes/bootstrap.min.css@@@ <?php print '</style> $this->getCSS();
<style type="text/css">';?> @@@src/includes/ekko-lightbox.min.css@@@ <?php print '</style> print '
<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>
</head> </head>
<body> <body>
<nav class="navbar navbar-inverse navbar-fixed-top"> <div id="ifm"></div>';
<div class="container"> $this->getJS();
<div class="navbar-header"> print '
<a class="navbar-brand">IFM</a> <script>var ifm = new IFM(); ifm.init( "ifm" );</script>
<button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar"> </body>
<span class="sr-only">Toggle navigation</span> </html>
<span class="icon-bar"></span> ';
<span class="icon-bar"></span> }
<span class="icon-bar"></span>
</button> public function getInlineApplication() {
</div> $this->getCSS();
<div class="navbar-collapse collapse" id="navbar"> print '<div id="ifm"></div>';
<form class="navbar-form navbar-left"> $this->getJS();
<div class="form-group"> }
<div class="input-group">
<span class="input-group-addon" id="currentDirLabel">Content of <span id="docroot">'; public function getCSS() {
print ( IFMConfig::showpath == 1 ) ? realpath( IFMConfig::root_dir ) : "/"; print '
print '</span></span><input class="form-control" id="currentDir" aria-describedby="currentDirLabel" type="text"> <style type="text/css">';?> @@@src/includes/bootstrap.min.css@@@ <?php print '</style>
</div> <style type="text/css">';?> @@@src/includes/fontello-embedded.css@@@ <?php print '</style>
</div> <style type="text/css">';?> @@@src/style.css@@@ <?php print '</style>
</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 ) { public function getJS() {
print '<li><a id="upload"><span title="upload" class="icon icon-upload"></span> <span class="visible-xs">upload</span></a></li>'; print '
}
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>
<script>';?> @@@src/includes/ace.js@@@ <?php print '</script> <script>';?> @@@src/includes/ace.js@@@ <?php print '</script>
<script>';?> @@@src/includes/jquery.min.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.min.js@@@ <?php print '</script>
<script>';?> @@@src/includes/bootstrap-notify.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/bootstrap-treeview.min.js@@@ <?php print '</script>
<script>';?> @@@src/includes/mustache.min.js@@@ <?php print '</script>
<script>';?> @@@src/ifm.js@@@ <?php print '</script> <script>';?> @@@src/ifm.js@@@ <?php print '</script>
</body>
</html>
'; ';
} }
@@ -137,24 +125,29 @@ class IFM {
$this->getFiles( $_REQUEST["dir"] ); $this->getFiles( $_REQUEST["dir"] );
else else
$this->getFiles( "" ); $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"] ) ) { if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) ) {
switch( $_REQUEST["api"] ) { switch( $_REQUEST["api"] ) {
case "createDir": $this->createDir( $_REQUEST["dir"], $_REQUEST["dirname"] ); break; case "createDir": $this->createDir( $_REQUEST["dir"], $_REQUEST["dirname"] ); break;
case "saveFile": $this->saveFile( $_REQUEST ); break; case "saveFile": $this->saveFile( $_REQUEST ); break;
case "getContent": $this->getContent( $_REQUEST ); break; case "getContent": $this->getContent( $_REQUEST ); break;
case "deleteFile": $this->deleteFile( $_REQUEST ); break; case "delete": $this->deleteFile( $_REQUEST ); break;
case "renameFile": $this->renameFile( $_REQUEST ); break; case "rename": $this->renameFile( $_REQUEST ); break;
case "downloadFile": $this->downloadFile( $_REQUEST ); break; case "download": $this->downloadFile( $_REQUEST ); break;
case "extractFile": $this->extractFile( $_REQUEST ); break; case "extract": $this->extractFile( $_REQUEST ); break;
case "uploadFile": $this->uploadFile( $_REQUEST ); break; case "upload": $this->uploadFile( $_REQUEST ); break;
case "copyMove": $this->copyMove( $_REQUEST ); break; case "copyMove": $this->copyMove( $_REQUEST ); break;
case "changePermissions": $this->changePermissions( $_REQUEST ); break; case "changePermissions": $this->changePermissions( $_REQUEST ); break;
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 "deleteMultipleFiles": $this->deleteMultipleFiles( $_REQUEST ); break; case "multidelete": $this->deleteMultipleFiles( $_REQUEST ); break;
case "getFolderTree": 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; break;
default: default:
echo json_encode( array( "status" => "ERROR", "message" => "No valid api action given" ) ); 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")); print json_encode(array("status"=>"ERROR", "message"=>"No valid working directory"));
} }
} }
exit( 0 );
} }
public function run() { public function run( $mode="standalone" ) {
if ( $this->checkAuth() ) { if ( $this->checkAuth() ) {
// go to our root_dir // 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."); die( "Cannot access root_dir.");
else else
chdir( realpath( IFMConfig::root_dir ) ); chdir( realpath( $this->config['root_dir'] ) );
if ( ! isset($_REQUEST['api']) ) { $this->mode = $mode;
$this->getApplication(); if ( isset( $_REQUEST['api'] ) || $mode == "api" ) {
} else {
$this->handleRequest(); $this->handleRequest();
} elseif( $mode == "standalone" ) {
$this->getApplication();
} else {
$this->getInlineApplication();
} }
} }
} }
@@ -185,61 +182,53 @@ class IFM {
api functions api functions
*/ */
private function getFiles($dir) { private function getFiles( $dir ) {
// SECURITY FUNCTION (check that we don't operate on a higher level that the script itself) $dir = $this->getValidDir( $dir );
$dir=$this->getValidDir($dir); $this->chDirIfNecessary( $dir );
// now we change in our target directory
$this->chDirIfNecessary($dir); unset( $files ); unset( $dirs ); $files = array(); $dirs = array();
// unset our file and directory arrays
unset($files); unset($dirs); $files = array(); $dirs = array(); if( $handle = opendir( "." ) ) {
// so lets loop over our directory while( false !== ( $result = readdir( $handle ) ) ) {
if ($handle = opendir(".")) { if( $result == basename( $_SERVER['SCRIPT_NAME'] ) && $this->getScriptRoot() == getcwd() ) { }
while (false !== ($result = readdir($handle))) { // this awesome statement is the correct way to loop over a directory :) elseif( ( $result == ".htaccess" || $result==".htpasswd" ) && $this->config['showhtdocs'] != 1 ) {}
if( $result == basename( $_SERVER['SCRIPT_NAME'] ) && $this->getScriptRoot() == getcwd() ) { } // we don't want to see the script itself elseif( $result == "." ) {}
elseif( ( $result == ".htaccess" || $result==".htpasswd" ) && IFMConfig::showhtdocs != 1 ) {} // check if we are granted to see .ht-docs elseif( $result != ".." && substr( $result, 0, 1 ) == "." && $this->config['showhiddenfiles'] != 1 ) {}
elseif( $result == "." ) {} // the folder itself will also be invisible else {
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
$item = array(); $item = array();
$i = 0;
$item["name"] = $result; $item["name"] = $result;
$i++;
if( is_dir($result) ) { if( is_dir($result) ) {
$item["type"] = "dir"; $item["type"] = "dir";
} else {
$item["type"] = "file";
}
if( is_dir( $result ) ) {
if( $result == ".." ) if( $result == ".." )
$item["icon"] = "icon icon-up-open"; $item["icon"] = "icon icon-up-open";
else else
$item["icon"] = "icon icon-folder-empty"; $item["icon"] = "icon icon-folder-empty";
} else { } else {
$item["type"] = "file";
$type = substr( strrchr( $result, "." ), 1 ); $type = substr( strrchr( $result, "." ), 1 );
$item["icon"] = $this->getTypeIcon( $type ); $item["icon"] = $this->getTypeIcon( $type );
} }
if( IFMConfig::showlastmodified == 1 ) { $item["lastmodified"] = date( "d.m.Y, G:i e", filemtime( $result ) ); } if( $this->config['showlastmodified'] == 1 ) { $item["lastmodified"] = date( "d.m.Y, G:i e", filemtime( $result ) ); }
if( IFMConfig::showfilesize == 1 ) { if( $this->config['showfilesize'] == 1 ) {
$item["filesize"] = filesize( $result ); $item["size"] = filesize( $result );
if( $item["filesize"] > 1073741824 ) $item["filesize"] = round( ( $item["filesize"]/1073741824 ), 2 ) . " GB"; if( $item["size"] > 1073741824 ) $item["size"] = round( ( $item["size"]/1073741824 ), 2 ) . " GB";
elseif($item["filesize"]>1048576)$item["filesize"] = round( ( $item["filesize"]/1048576 ), 2 ) . " MB"; elseif($item["size"]>1048576)$item["size"] = round( ( $item["size"]/1048576 ), 2 ) . " MB";
elseif($item["filesize"]>1024)$item["filesize"] = round( ( $item["filesize"]/1024 ), 2 ) . " KB"; elseif($item["size"]>1024)$item["size"] = round( ( $item["size"]/1024 ), 2 ) . " KB";
else $item["filesize"] = $item["filesize"] . " Byte"; else $item["size"] = $item["size"] . " Byte";
} }
if( IFMConfig::showpermissions > 0 ) { if( $this->config['showpermissions'] > 0 ) {
if( IFMConfig::showpermissions == 1 ) $item["fileperms"] = substr( decoct( fileperms( $result ) ), -3 ); if( $this->config['showpermissions'] == 1 ) $item["fileperms"] = substr( decoct( fileperms( $result ) ), -3 );
elseif( IFMConfig::showpermissions == 2 ) $item["fileperms"] = $this->filePermsDecode( fileperms( $result ) ); elseif( $this->config['showpermissions'] == 2 ) $item["fileperms"] = $this->filePermsDecode( fileperms( $result ) );
if( $item["fileperms"] == "" ) $item["fileperms"] = " "; 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 ) { if ( function_exists( "posix_getpwuid" ) && fileowner($result) !== false ) {
$ownerarr = posix_getpwuid( fileowner( $result ) ); $ownerarr = posix_getpwuid( fileowner( $result ) );
$item["owner"] = $ownerarr['name']; $item["owner"] = $ownerarr['name'];
} else $item["owner"] = false; } else $item["owner"] = false;
} }
if( IFMConfig::showgroup == 1 ) { if( $this->config['showgroup'] == 1 ) {
if( function_exists( "posix_getgrgid" ) && filegroup( $result ) !== false ) { if( function_exists( "posix_getgrgid" ) && filegroup( $result ) !== false ) {
$grouparr = posix_getgrgid( filegroup( $result ) ); $grouparr = posix_getgrgid( filegroup( $result ) );
$item["group"] = $grouparr['name']; $item["group"] = $grouparr['name'];
@@ -256,6 +245,13 @@ class IFM {
echo json_encode( array_merge( $dirs, $files ) ); 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 ) { private function getFolderTreeRecursive( $start_dir ) {
$ret = array(); $ret = array();
$start_dir = realpath( $start_dir ); $start_dir = realpath( $start_dir );
@@ -271,7 +267,7 @@ class IFM {
} }
private function copyMove( $d ) { 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." ) ); echo json_encode( array( "status" => "ERROR", "message" => "No permission to copy or move files." ) );
exit( 1 ); exit( 1 );
} }
@@ -327,11 +323,11 @@ class IFM {
private function saveFile(array $d) { private function saveFile(array $d) {
if( isset( $d['filename'] ) && $d['filename'] != "" ) { if( isset( $d['filename'] ) && $d['filename'] != "" ) {
// if you are not allowed to see .ht-docs you can't save one // 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "You are not allowed to edit or create htdocs" ) );
} }
// same with hidden files // 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "You are not allowed to edit or create hidden files" ) );
} }
elseif(strpos($d['filename'],'/')!==false) { elseif(strpos($d['filename'],'/')!==false) {
@@ -358,7 +354,7 @@ class IFM {
// gets the content of a file // gets the content of a file
// notice: if the content is not JSON encodable it returns an error // notice: if the content is not JSON encodable it returns an error
private function getContent( array $d ) { 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 { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( file_exists( $d['filename'] ) ) { if( file_exists( $d['filename'] ) ) {
@@ -371,7 +367,7 @@ class IFM {
// deletes a file or a directory (recursive!) // deletes a file or a directory (recursive!)
private function deleteFile( array $d ) { 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "No permission to delete files" ) );
} }
else { else {
@@ -396,7 +392,7 @@ class IFM {
// deletes a bunch of files or directories // deletes a bunch of files or directories
private function deleteMultipleFiles( array $d ) { 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 { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
$err = array(); $errFLAG = -1; // -1 -> no files deleted; 0 -> at least some files deleted; 1 -> all files deleted $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 // renames a file
private function renameFile( array $d ) { 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "No permission to rename files" ) );
} else { } else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( strpos( $d['newname'], '/' ) !== false ) if( strpos( $d['newname'], '/' ) !== false )
echo json_encode( array( "status" => "ERROR", "message" => "No slashes allowed in filenames" ) ); 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" ) ); 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to rename file" ) );
else { else {
if( @rename( $d['filename'], $d['newname'] ) ) if( @rename( $d['filename'], $d['newname'] ) )
@@ -450,21 +446,21 @@ class IFM {
// provides a file for downloading // provides a file for downloading
private function downloadFile( array $d ) { 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" ) ); 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" ) ); 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to download hidden files" ) );
else { else {
$this->chDirIfNecessary( $d["dir"] ); $this->chDirIfNecessary( $d["dir"] );
$this->file_download( $d['filename'] ); $this->fileDownload( $d['filename'] );
} }
} }
// extracts a zip-archive // extracts a zip-archive
private function extractFile( array $d ) { 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "No permission to extract files" ) );
else { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
@@ -492,16 +488,16 @@ class IFM {
// uploads a file // uploads a file
private function uploadFile( array $d ) { 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "No permission to upload files" ) );
elseif( !isset( $_FILES['file'] ) ) elseif( !isset( $_FILES['file'] ) )
echo json_encode( array( "file" => $_FILE,"files" => $_FILES ) ); echo json_encode( array( "file" => $_FILE,"files" => $_FILES ) );
else { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
$newfilename = ( isset( $d["newfilename"] ) && $d["newfilename"]!="" ) ? $d["newfilename"] : $_FILES['file']['name']; $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" ) ); 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to upload hidden file" ) );
else { else {
if( $_FILES['file']['tmp_name'] ) { if( $_FILES['file']['tmp_name'] ) {
@@ -523,7 +519,7 @@ class IFM {
// change permissions of a file // change permissions of a file
private function changePermissions( array $d ) { 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( ! 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" ) ); } elseif( ! $this->isPathValid( $this->pathCombine( $d['dir'],$d['filename'] ) ) ) { echo json_encode( array( "status" => "ERROR", "message" => "Not allowed to change the permissions" ) ); }
else { else {
@@ -562,7 +558,7 @@ class IFM {
// zips a directory and provides it for downloading // 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 // 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 ) { 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "No permission to download directories" ) );
else { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
@@ -572,7 +568,7 @@ class IFM {
echo json_encode( array( "status" => "ERROR", "message" => "Filename not allowed" ) ); echo json_encode( array( "status" => "ERROR", "message" => "Filename not allowed" ) );
else { else {
unset( $zip ); 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 { try {
IFMZip::create( realpath( $d['filename'] ), $dfile, ( $d['filename'] == "." ) ); IFMZip::create( realpath( $d['filename'] ), $dfile, ( $d['filename'] == "." ) );
if( $d['filename'] == "." ) { if( $d['filename'] == "." ) {
@@ -581,7 +577,7 @@ class IFM {
else else
$d['filename'] = basename( getcwd() ); $d['filename'] = basename( getcwd() );
} }
$this->file_download( $dfile, $d['filename'] . ".zip" ); $this->fileDownload( $dfile, $d['filename'] . ".zip" );
} catch ( Exception $e ) { } catch ( Exception $e ) {
echo "An error occured: " . $e->getMessage(); echo "An error occured: " . $e->getMessage();
} finally { } finally {
@@ -593,7 +589,7 @@ class IFM {
// uploads a file from an other server using the curl extention // uploads a file from an other server using the curl extention
private function remoteUpload( array $d ) { 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" ) ); echo json_encode( array( "status" => "ERROR", "message" => "No permission to remote upload files" ) );
elseif( !isset( $d['method'] ) || !in_array( $d['method'], array( "curl", "file" ) ) ) 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']" ) ); echo json_encode( array( "status" => "error", "message" => "No valid method given. Valid methods: ['curl', 'file']" ) );
@@ -646,7 +642,7 @@ class IFM {
*/ */
public function checkAuth() { 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; $login_failed = false;
if( isset( $_POST["user"] ) && isset( $_POST["pass"] ) ) { if( isset( $_POST["user"] ) && isset( $_POST["pass"] ) ) {
if( $this->checkCredentials( $_POST["user"], $_POST["pass"] ) ) { if( $this->checkCredentials( $_POST["user"], $_POST["pass"] ) ) {
@@ -677,7 +673,7 @@ class IFM {
} }
private function checkCredentials( $user, $pass ) { private function checkCredentials( $user, $pass ) {
list( $src, $srcopt ) = explode( ";", IFMConfig::auth_source, 2 ); list( $src, $srcopt ) = explode( ";", $this->config['auth_source'], 2 );
switch( $src ) { switch( $src ) {
case "inline": case "inline":
list( $uname, $hash ) = explode( ":", $srcopt ); list( $uname, $hash ) = explode( ":", $srcopt );
@@ -762,7 +758,7 @@ class IFM {
return ""; return "";
} else { } else {
$rpDir = realpath( $dir ); $rpDir = realpath( $dir );
$rpConfig = realpath( IFMConfig::root_dir ); $rpConfig = realpath( $this->config['root_dir'] );
if( $rpConfig == "/" ) if( $rpConfig == "/" )
return $rpDir; return $rpDir;
elseif( $rpDir == $rpConfig ) elseif( $rpDir == $rpConfig )
@@ -785,7 +781,7 @@ class IFM {
$tmp_d = dirname( $tmp_d ); $tmp_d = dirname( $tmp_d );
} }
$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 = ( 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 if( ! is_string( $rpDir ) || ! is_string( $rpConfig ) ) // can happen if open_basedir is in effect
return false; return false;
elseif( $rpDir == $rpConfig ) elseif( $rpDir == $rpConfig )
@@ -907,9 +903,9 @@ class IFM {
// check if filename is allowed // check if filename is allowed
private function allowedFileName( $f ) { 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; return false;
elseif( IFMConfig::showhiddenfiles != 1 && substr( $f, 0, 1 ) == "." ) elseif( $this->config['showhiddenfiles'] != 1 && substr( $f, 0, 1 ) == "." )
return false; return false;
elseif( ! $this->isPathValid( $f ) ) elseif( ! $this->isPathValid( $f ) )
return false; return false;
@@ -931,7 +927,7 @@ class IFM {
else return true; else return true;
} }
private function file_download( $file, $name="" ) { private function fileDownload( $file, $name="" ) {
header( 'Content-Description: File Transfer' ); header( 'Content-Description: File Transfer' );
header( 'Content-Type: application/octet-stream' ); header( 'Content-Type: application/octet-stream' );
header( 'Content-Disposition: attachment; filename="' . ( trim( $name ) == "" ? basename( $file ) : $name ) . '"' ); header( 'Content-Disposition: attachment; filename="' . ( trim( $name ) == "" ? basename( $file ) : $name ) . '"' );
@@ -949,12 +945,51 @@ class IFM {
fclose($stdout_stream); 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();

View File

@@ -7,15 +7,18 @@ body {
font-size: 14pt; font-size: 14pt;
} }
#filetable tr td:nth-child(5) { #filetable td:nth-child(5), #filetable th:nth-child(5) {
text-align: center; text-align: center;
} }
#filetable tr td:nth-child(6) { #filetable td:nth-child(6), #filetable th:nth-child(6) {
text-align: center; text-align: center;
} }
#filetable tr td:last-child { #filetable tr td:last-child {
text-align: right; text-align: right;
} }
#filetable td:last-child a:hover {
text-decoration: none;
}
a { cursor: pointer !important; } a { cursor: pointer !important; }

82
src/templates/app.html Normal file
View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>

View 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>