1
0
mirror of https://github.com/misterunknown/ifm.git synced 2025-08-14 12:04:05 +02:00

Merge pull request #75 from misterunknown/dev-3.0.0

Dev 3.0.0
This commit is contained in:
Marco Dickert
2017-09-01 16:03:52 +02:00
committed by GitHub
15 changed files with 2023 additions and 2142 deletions

View File

@@ -66,13 +66,11 @@ See [authentication](https://github.com/misterunknown/ifm/wiki/Authentication).
The docker image is based on alpine 3.5 for a small image footprint, with necessary apache, php and supporting packages installed and exposes port 80 The docker image is based on alpine 3.5 for a small image footprint, with necessary apache, php and supporting packages installed and exposes port 80
### build image ### build image
Run the following command from the top source dir: Run the following command from the top source dir:
`docker build -t ifm .` `docker build -t ifm .`
### run image ### run image
The script is installed inside the image at `/var/www/html/index.php`. Its default configuration is unchanged, thus it will display the contents of the document root (`/var/www/html`) The script is installed inside the image at `/var/www/html/index.php`. Its default configuration is unchanged, thus it will display the contents of the document root (`/var/www/html`)
Here is an example of how to start up a container with this image: Here is an example of how to start up a container with this image:

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -18,6 +18,21 @@ $IFM_BUILD_STANDALONE = "ifm.php";
$IFM_BUILD_STANDALONE_COMPRESSED = "build/ifm.min.php"; $IFM_BUILD_STANDALONE_COMPRESSED = "build/ifm.min.php";
$IFM_BUILD_LIB_PHP = "build/libifm.php"; $IFM_BUILD_LIB_PHP = "build/libifm.php";
$options = getopt( null, array( "language::" ) );
$vars['languages'] = isset( $options['language'] ) ? explode( ',', $options['language'] ) : array( "en" );
$vars['defaultlanguage'] = $vars['languages'][0];
$vars['languageincludes'] = "";
foreach( $vars['languages'] as $l ) {
if( file_exists( "src/i18n/".$l.".json" ) )
$vars['languageincludes'] .=
'$i18n["'.$l.'"] = <<<\'f00bar\'' . "\n"
. file_get_contents( "src/i18n/".$l.".json" ) . "\n"
. 'f00bar;' . "\n"
. '$i18n["'.$l.'"] = json_decode( $i18n["'.$l.'"], true );' . "\n" ;
else
print "WARNING: Language file src/i18n/".$l.".json not found.\n";
}
/** /**
* Concat PHP Files * Concat PHP Files
*/ */
@@ -30,13 +45,20 @@ foreach( $IFM_SRC_PHP as $phpfile ) {
$compiled = join( $compiled ); $compiled = join( $compiled );
/** /**
* Process includes * Process file includes
*/ */
$includes = NULL; $includes = NULL;
preg_match_all( "/\@\@\@file:([^\@]+)\@\@\@/", $compiled, $includes, PREG_SET_ORDER ); preg_match_all( "/\@\@\@file:([^\@]+)\@\@\@/", $compiled, $includes, PREG_SET_ORDER );
foreach( $includes as $file ) { foreach( $includes as $file )
$compiled = str_replace( $file[0], file_get_contents( $file[1] ), $compiled ); $compiled = str_replace( $file[0], file_get_contents( $file[1] ), $compiled );
}
/**
* Process variable includes
*/
$includes = NULL;
preg_match_all( "/\@\@\@vars:([^\@]+)\@\@\@/", $compiled, $includes, PREG_SET_ORDER );
foreach( $includes as $var )
$compiled = str_replace( $var[0], $vars[$var[1]], $compiled );
/** /**
* Build standalone script * Build standalone script

964
ifm.php

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +1,86 @@
{ {
"ajax_request": "AJAX Request", "ajax_request": "AJAX Request",
"archivename": "Name des Archivs",
"archive_create_success": "Das Archiv wurde erfolgreich erstellt.",
"archive_create_error": "Das Archiv konnte nicht erstellt werden.",
"archive_invalid_format": "Ungültiges Archivformat angegeben.",
"cancel": "Abbrechen", "cancel": "Abbrechen",
"close": "Schließen", "close": "Schließen",
"copy": "Kopieren", "copy": "Kopieren",
"copy_error": "Folgende Dateien konnten nicht kopiert werden:",
"copy_success": "Datei(en) erfolgreich kopiert.",
"create_archive": "Archiv erstellen",
"data": "Daten", "data": "Daten",
"delete": "Löschen", "delete": "Löschen",
"directoryname": "Ordner Name", "directoryname": "Ordner Name",
"download": "Download",
"edit": "Bearbeiten",
"editor_options": "Editor Optionen", "editor_options": "Editor Optionen",
"extract": "Auspacken", "error": "Fehler:",
"extract_filename": "Folgende Datei auspacken -", "extract": "Entpacken",
"file_delete_confirm": "Soll die folgende Datei wirklich gelöscht werden -", "extract_error": "Das Archiv konnte nicht entpackt werden.",
"file_edit_success": "Datei erfolgreich geändert / angelegt.", "extract_filename": "Folgende Datei entpacken -",
"file_multi_delete_confirm": "Sollen diese Dateien wirklich gelöscht werden -", "extract_success": "Das Archiv wurde erfolgreich entpackt.",
"file_copy_to": "nach",
"file_delete_confirm": "Soll die folgende Datei wirklich gelöscht werden:",
"file_delete_error": "Folgende Dateien konnten nicht gelöscht werden:",
"file_delete_success": "Datei(en) erfolgreich gelöscht",
"file_display_error": "Die Datei kann nicht angezeigt oder geändert werden",
"file_new": "Neue Datei", "file_new": "Neue Datei",
"file_save_confirm": "Soll diese Datei wirklich gelöscht werden -", "file_load_error": "Der Inhalt der Datei konnte nicht geladen werden",
"file_open_error": "Die Datei konnte nicht geöffnet werden.",
"file_new": "Neue Datei",
"file_no_permission": "Sie haben keine Berechtigung diese Datei zu erstellen/bearbeiten.",
"file_not_found": "Die Datei wurde nicht gefunden, oder kann nicht geöffnet werden.",
"file_rename": "Datei umbenennen",
"file_rename_error": "Datei konnte nicht umbenannt werden: ",
"file_rename_success": "Datei erfolgreich umbenannt.",
"file_save_error": "Datei konnte nicht gespeichert werden.",
"file_save_success": "Datei erfolgreich gespeichert.",
"file_save_confirm": "Soll diese Datei wirklich gespeichert werden -",
"file_save_error": "Datei konnte nicht geändert oder angelegt werden: ",
"file_upload_error": "Datei konnte nicht hochgeladen werden.",
"file_upload_success": "Datei erfolgreich hochgeladen",
"filename": "Dateiname", "filename": "Dateiname",
"filename_new": "Neuer Dateiname", "filename_new": "Neuer Dateiname",
"filename_slashes": "Der Dateiname darf keine Schrägstriche enthalten.",
"folder_create_error": "Verzeichnis konnte nicht angelegt werden.",
"folder_create_success": "Verzeichnis erfolgreich angelegt.",
"folder_new": "Neue Ordner", "folder_new": "Neue Ordner",
"folder_not_found": "Das Verzeichnis wurde nicht gefunden.",
"folder_tree_load_error": "Fehler bei Laden des Verzeichnisbaums.",
"footer": "IFM - verbesserter file manager | ifm.php versteckt |", "footer": "IFM - verbesserter file manager | ifm.php versteckt |",
"general_error": "Genereller Fehler aufgetreten: Keine oder unvollständige Antwort vom Server",
"github": "Besuche das Projekt auf GitHub", "github": "Besuche das Projekt auf GitHub",
"group": "Gruppe", "group": "Gruppe",
"invalid_action": "Fehlerhafte Aktion übergeben.",
"invalid_archive_format": "Ungültiges Archiv-Format. Möglich sind zip, tar, tar.gz oder tar.bz2.",
"invalid_data": "Fehlerhafte Daten vom Server erhalten.",
"invalid_dir": "Ungültiges Verzeichnis übergegeben.",
"invalid_filename": "Ungültiger Dateiname übergegeben.",
"invalid_params": "Ungültige Parameter übergegeben.",
"invalid_url": "Ungültige URL übergegeben.",
"json_encode_error": "Konnte die Antwort nicht als JSON formatieren:",
"last_modified": "Zuletzt geändert", "last_modified": "Zuletzt geändert",
"load_config_error": "Konfiguration konnte nicht geladen werden.",
"load_template_error": "Vorlagen konnten nicht geladen werden.",
"load_text_error": "Texte konnten nicht geladen werden.",
"login": "Anmeldung", "login": "Anmeldung",
"login_failed": "Anmeldung fehlgeschlagen.",
"logout": "Abmelden", "logout": "Abmelden",
"method": "Methode", "method": "Methode",
"move": "Verschieben", "move": "Verschieben",
"move_error": "Folgende Dateien konnten nicht verschoben werden:",
"move_success": "Datei(en) erfolgreich verschoben.",
"nopermissions": "Sie haben nicht die nötige Berechtigung dafür.",
"options": "Optionen", "options": "Optionen",
"owner": "Besitzer", "owner": "Besitzer",
"password": "Passwort", "password": "Passwort",
"path_content": "Inhalt von", "path_content": "Inhalt von",
"pattern_error_slashes": "Das Muster darf keine Slashes enthalten.",
"permission_change_error": "Berechtigungen konnten nicht geändert werden.",
"permission_change_success": "Berechtigungen erfolgreich geändert.",
"permission_parse_error": "Berechtigungen konnten nicht geparst werden.",
"permissions": "Berechtigungen", "permissions": "Berechtigungen",
"refresh": "Auffrischen", "refresh": "Auffrischen",
"rename": "Umbenennen", "rename": "Umbenennen",
@@ -36,7 +88,7 @@
"request": "Anfrage", "request": "Anfrage",
"response": "Antwort", "response": "Antwort",
"save": "Speichen", "save": "Speichen",
"save_wo_close": "Speichen ohne Schließen", "save_wo_close": "Speichen ohne schließen",
"search": "Suchen", "search": "Suchen",
"search_pattern": "Muster", "search_pattern": "Muster",
"select_destination": "Zielort auswählen", "select_destination": "Zielort auswählen",
@@ -46,7 +98,7 @@
"tasks": "Aufgaben", "tasks": "Aufgaben",
"toggle_nav": "Navigation umschalten", "toggle_nav": "Navigation umschalten",
"upload": "Hochladen", "upload": "Hochladen",
"upload_drop": "Dateien zum hochladen hier hinziehen", "upload_drop": "Dateien zum hochladen hier ablegen",
"upload_file": "Datei hochladen", "upload_file": "Datei hochladen",
"upload_remote": "Hochladen von ausserhalb", "upload_remote": "Hochladen von ausserhalb",
"upload_remote_url": "Entfernte URL zum hochladen", "upload_remote_url": "Entfernte URL zum hochladen",

View File

@@ -1,34 +1,86 @@
{ {
"ajax_request": "AJAX Request", "ajax_request": "AJAX request",
"archivename": "Name of the archive",
"archive_create_success": "Archive successfully created.",
"archive_create_error": "Could not create archive.",
"archive_invalid_format": "Invalid archive format given.",
"cancel": "Cancel", "cancel": "Cancel",
"close": "Close", "close": "Close",
"copy": "Copy", "copy": "Copy",
"copy_error": "The following files could not be copied:",
"copy_success": "File(s) copied successfully.",
"create_archive": "Create archive",
"data": "Data", "data": "Data",
"delete": "Delete", "delete": "Delete",
"directoryname": "Directory Name", "directoryname": "Directory Name",
"download": "Download",
"edit": "Edit",
"editor_options": "Editor Options", "editor_options": "Editor Options",
"extract": "Extract", "error": "Error:",
"extract": "extract",
"extract_error": "Could not extract archive.",
"extract_filename": "Extract file - ", "extract_filename": "Extract file - ",
"extract_success": "Archive extracted successfully.",
"file_copy_to": "to",
"file_delete_confirm": "Do you really want to delete the following file -", "file_delete_confirm": "Do you really want to delete the following file -",
"file_edit_success": "File successfully edited / created.", "file_delete_error": "File(s) could not be deleted.",
"file_multi_delete_confirm": "Do you really want to delete these files -", "file_delete_success": "File(s) successfully deleted.",
"file_display_error": "This file can not be displayed or edited.",
"file_new": "New File", "file_new": "New File",
"file_load_error": "Content could not be loaded.",
"file_open_error": "Could not open the file.",
"file_new": "New file",
"file_no_permission": "No permission to edit/create file.",
"file_not_found": "File was not found or could not be opened.",
"file_rename": "Rename File",
"file_rename_error": "File could not be renamed: ",
"file_rename_success": "File successfully renamed.",
"file_save_error": "File could not be saved.",
"file_save_success": "File was saved successfully.",
"file_save_confirm": "Do you want to save the following file -", "file_save_confirm": "Do you want to save the following file -",
"file_save_error": "File could not be edited or created: ",
"file_upload_error": "File could not be uploaded.",
"file_upload_success": "File successfully uploaded.",
"filename": "Filename", "filename": "Filename",
"filename_new": "New Filename", "filename_new": "New Filename",
"filename_slashes": "The filename must not contain slashes.",
"folder_create_error": "Directory could not be created: ",
"folder_create_success": "Directory sucessfully created.",
"folder_new": "New Folder", "folder_new": "New Folder",
"folder_not_found": "The directory could not be found.",
"folder_tree_load_error": "Error while fetching the folder tree.",
"footer": "IFM - improved file manager | ifm.php hidden |", "footer": "IFM - improved file manager | ifm.php hidden |",
"general_error": "General error occured: No or broken response.",
"github": "Visit the project on GitHub", "github": "Visit the project on GitHub",
"group": "Group", "group": "Group",
"invalid_action": "Invalid action given.",
"invalid_archive_format": "Invalid archive format given. Possible formats are zip, tar, tar.gz or tar.bz2.",
"invalid_data": "Invalid data from server.",
"invalid_dir": "Invalid directory given.",
"invalid_filename": "Invalid filename given.",
"invalid_params": "Invalid parameter given.",
"invalid_url": "Invalid URL given.",
"json_encode_error": "Could not format the response as JSON:",
"last_modified": "Last Modified", "last_modified": "Last Modified",
"load_config_error": "Could not load configuration.",
"load_template_error": "Could not load templates.",
"load_text_error": "Could not load texts.",
"login": "Login", "login": "Login",
"login_failed": "Login failed.",
"logout": "Log Off", "logout": "Log Off",
"method": "Method", "method": "Method",
"move": "Move", "move": "Move",
"move_error": "The following files could not be moved:",
"move_success": "File(s) successfully moved.",
"nopermissions": "You don't have the permission to do that.",
"options": "Options", "options": "Options",
"owner": "Owner", "owner": "Owner",
"password": "Password", "password": "Password",
"path_content": "Content of", "path_content": "Content of",
"pattern_error_slashes": "Pattern must not contain slashes.",
"permission_change_error": "Permissions could not be changed: ",
"permission_change_success": "Permissions successfully changed.",
"permission_parse_error": "Permissions could not be parsed correctly.",
"permissions": "Permissions", "permissions": "Permissions",
"refresh": "Refresh", "refresh": "Refresh",
"rename": "Rename", "rename": "Rename",
@@ -37,6 +89,7 @@
"response": "Response", "response": "Response",
"save": "Save", "save": "Save",
"save_wo_close": "Save w/o Close", "save_wo_close": "Save w/o Close",
"search": "Search",
"search_pattern": "Pattern", "search_pattern": "Pattern",
"select_destination": "Select Destination", "select_destination": "Select Destination",
"size": "Size", "size": "Size",
@@ -51,4 +104,4 @@
"upload_remote_url": "Remote Upload URL", "upload_remote_url": "Remote Upload URL",
"username": "username", "username": "username",
"word_wrap": "Word Wrap" "word_wrap": "Word Wrap"
} }

View File

@@ -67,7 +67,7 @@ function IFM( params ) {
*/ */
this.refreshFileTable = function () { this.refreshFileTable = function () {
var taskid = self.generateGuid(); var taskid = self.generateGuid();
self.task_add( { id: taskid, name: "Refresh" } ); self.task_add( { id: taskid, name: self.i18n.refresh } );
$.ajax({ $.ajax({
url: self.api, url: self.api,
type: "POST", type: "POST",
@@ -77,7 +77,7 @@ function IFM( params ) {
}, },
dataType: "json", dataType: "json",
success: self.rebuildFileTable, success: self.rebuildFileTable,
error: function() { self.showMessage( "General error occured: No or broken response", "e" ); }, error: function() { self.showMessage( self.i18n.general_error, "e" ); },
complete: function() { self.task_done( taskid ); } complete: function() { self.task_done( taskid ); }
}); });
}; };
@@ -92,7 +92,7 @@ function IFM( params ) {
this.showMessage( data.message, "e" ); this.showMessage( data.message, "e" );
return; return;
} else if ( ! Array.isArray( data ) ) { } else if ( ! Array.isArray( data ) ) {
this.showMessage( "Invalid data from server", "e" ); this.showMessage( self.i18n.invalid_data, "e" );
return; return;
} }
data.forEach( function( item ) { data.forEach( function( item ) {
@@ -140,6 +140,7 @@ function IFM( params ) {
} }
} }
if( ! self.inArray( item.name, [".", ".."] ) ) { if( ! self.inArray( item.name, [".", ".."] ) ) {
item.dragdrop = 'draggable="true"';
if( self.config.copymove ) if( self.config.copymove )
item.button.push({ item.button.push({
action: "copymove", action: "copymove",
@@ -179,16 +180,17 @@ function IFM( params ) {
filetable.tBodies[0].addEventListener( 'click', function( e ) { filetable.tBodies[0].addEventListener( 'click', function( e ) {
if( e.target.tagName == "TD" && e.target.parentElement.classList.contains( 'clickable-row' ) && e.target.parentElement.dataset.filename !== ".." && e.ctrlKey ) if( e.target.tagName == "TD" && e.target.parentElement.classList.contains( 'clickable-row' ) && e.target.parentElement.dataset.filename !== ".." && e.ctrlKey )
e.target.parentElement.classList.toggle( 'selectedItem' ); e.target.parentElement.classList.toggle( 'selectedItem' );
else if( e.target.classList.contains( 'ifmitem' ) ) { else if( e.target.classList.contains( 'ifmitem' ) || e.target.parentElement.classList.contains( 'ifmitem' ) ) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
if( e.target.dataset.type == "dir" ) ifmitem = ( e.target.classList.contains( 'ifmitem' ) ? e.target : e.target.parentElement );
self.changeDirectory( e.target.parentElement.parentElement.dataset.filename ); if( ifmitem.dataset.type == "dir" )
self.changeDirectory( ifmitem.parentElement.parentElement.dataset.filename );
else else
if( self.config.isDocroot ) if( self.config.isDocroot )
window.location.href = self.hrefEncode( self.pathCombine( self.currentDir, e.target.parentElement.parentElement.dataset.filename ) ); window.location.href = self.hrefEncode( self.pathCombine( self.currentDir, ifmitem.parentElement.parentElement.dataset.filename ) );
else else
document.forms["d_"+e.target.id].submit(); document.forms["d_"+ifmitem.id].submit();
} else if( e.target.parentElement.name == 'start_download' ) { } else if( e.target.parentElement.name == 'start_download' ) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
@@ -196,7 +198,7 @@ function IFM( params ) {
} else if( e.target.parentElement.name && e.target.parentElement.name.substring(0, 3) == "do-" ) { } else if( e.target.parentElement.name && e.target.parentElement.name.substring(0, 3) == "do-" ) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
var item = self.fileCache.find( x => x.guid === e.target.parentElement.dataset.id ); var item = self.fileCache.find( function( x ) { if( x.guid === e.target.parentElement.dataset.id ) return x; } );
switch( e.target.parentElement.name.substr( 3 ) ) { switch( e.target.parentElement.name.substr( 3 ) ) {
case "rename": case "rename":
self.showRenameFileDialog( item.name ); self.showRenameFileDialog( item.name );
@@ -243,11 +245,11 @@ function IFM( params ) {
}, },
actionsGroups:[ actionsGroups:[
['edit', 'extract', 'rename'], ['edit', 'extract', 'rename'],
['copymove', 'download', 'delete'] ['copymove', 'download', 'createarchive', 'delete']
], ],
actions: { actions: {
edit: { edit: {
name: "edit", name: self.i18n.edit,
onClick: function( data ) { onClick: function( data ) {
self.editFile( data.clicked.name ); self.editFile( data.clicked.name );
}, },
@@ -257,7 +259,7 @@ function IFM( params ) {
} }
}, },
extract: { extract: {
name: "extract", name: self.i18n.extract,
onClick: function( data ) { onClick: function( data ) {
self.showExtractFileDialog( data.clicked.name ); self.showExtractFileDialog( data.clicked.name );
}, },
@@ -267,7 +269,7 @@ function IFM( params ) {
} }
}, },
rename: { rename: {
name: "rename", name: self.i18n.rename,
onClick: function( data ) { onClick: function( data ) {
self.showRenameFileDialog( data.clicked.name ); self.showRenameFileDialog( data.clicked.name );
}, },
@@ -277,9 +279,9 @@ function IFM( params ) {
copymove: { copymove: {
name: function( data ) { name: function( data ) {
if( data.selected.length > 0 ) if( data.selected.length > 0 )
return 'copy/move <span class="badge">'+data.selected.length+'</span>'; return self.i18n.copy+'/'+self.i18n.move+' <span class="badge">'+data.selected.length+'</span>';
else else
return 'copy/move'; return self.i18n.copy+'/'+self.i18n.move;
}, },
onClick: function( data ) { onClick: function( data ) {
if( data.selected.length > 0 ) if( data.selected.length > 0 )
@@ -293,9 +295,9 @@ function IFM( params ) {
download: { download: {
name: function( data ) { name: function( data ) {
if( data.selected.length > 0 ) if( data.selected.length > 0 )
return 'download <span class="badge">'+data.selected.length+'</span>'; return self.i18n.download+' <span class="badge">'+data.selected.length+'</span>';
else else
return 'download'; return self.i18n.download;
}, },
onClick: function( data ) { onClick: function( data ) {
if( data.selected.length > 0 ) if( data.selected.length > 0 )
@@ -306,12 +308,28 @@ function IFM( params ) {
iconClass: "icon icon-download", iconClass: "icon icon-download",
isShown: function() { return !!self.config.download; } isShown: function() { return !!self.config.download; }
}, },
createarchive: {
name: function( data ) {
if( data.selected.length > 0 )
return self.i18n.create_archive+' <span class="badge">'+data.selected.length+'</span>';
else
return self.i18n.create_archive;
},
onClick: function( data ) {
if( data.selected.length > 0 )
self.showCreateArchiveDialog( data.selected );
else
self.showCreateArchiveDialog( data.clicked );
},
iconClass: "icon icon-archive",
isShown: function( data ) { return !!( self.config.createarchive && data.clicked.name != ".." ); }
},
'delete': { 'delete': {
name: function( data ) { name: function( data ) {
if( data.selected.length > 0 ) if( data.selected.length > 0 )
return 'delete <span class="badge">'+data.selected.length+'</span>'; return self.i18n.delete+' <span class="badge">'+data.selected.length+'</span>';
else else
return 'delete'; return self.i18n.delete;
}, },
onClick: function( data ) { onClick: function( data ) {
if( data.selected.length > 0 ) if( data.selected.length > 0 )
@@ -352,7 +370,7 @@ function IFM( params ) {
$( "#currentDir" ).val( self.currentDir ); $( "#currentDir" ).val( self.currentDir );
if( config.pushState ) history.pushState( { dir: self.currentDir }, self.currentDir, "#"+encodeURIComponent( self.currentDir ) ); if( config.pushState ) history.pushState( { dir: self.currentDir }, self.currentDir, "#"+encodeURIComponent( self.currentDir ) );
}, },
error: function() { self.showMessage( "General error occured: No or broken response", "e" ); } error: function() { self.showMessage( self.i18n.general_error, "e" ); }
}); });
}; };
@@ -445,11 +463,11 @@ function IFM( params ) {
dataType: "json", dataType: "json",
success: function( data ) { success: function( data ) {
if( data.status == "OK" ) { if( data.status == "OK" ) {
self.showMessage( self.i18n.file_edit_success, "s" ); self.showMessage( self.i18n.file_save_success, "s" );
self.refreshFileTable(); self.refreshFileTable();
} else self.showMessage( "File could not be edited/created:" + data.message, "e" ); } else self.showMessage( self.i18n.file_save_error + data.message, "e" );
}, },
error: function() { self.showMessage( "General error occured", "e" ); } error: function() { self.showMessage( self.i18n.general_error, "e" ); }
}); });
self.fileChanged = false; self.fileChanged = false;
}; };
@@ -474,11 +492,11 @@ function IFM( params ) {
self.showFileDialog( data.data.filename, data.data.content ); self.showFileDialog( data.data.filename, data.data.content );
} }
else if( data.status == "OK" && data.data.content == null ) { else if( data.status == "OK" && data.data.content == null ) {
self.showMessage( "The content of this file cannot be fetched.", "e" ); self.showMessage( self.i18n.file_load_error, "e" );
} }
else self.showMessage( "Error: "+data.message, "e" ); else self.showMessage( self.i18n.error +data.message, "e" );
}, },
error: function() { self.showMessage( "This file can not be displayed or edited.", "e" ); } error: function() { self.showMessage( self.i18n.file_display_error, "e" ); }
}); });
}; };
@@ -522,14 +540,14 @@ function IFM( params ) {
dataType: "json", dataType: "json",
success: function( data ){ success: function( data ){
if( data.status == "OK" ) { if( data.status == "OK" ) {
self.showMessage( "Directory sucessfully created.", "s" ); self.showMessage( self.i18n.folder_create_success, "s" );
self.refreshFileTable(); self.refreshFileTable();
} }
else { else {
self.showMessage( "Directory could not be created: "+data.message, "e" ); self.showMessage( self.i18n.folder_create_error +data.message, "e" );
} }
}, },
error: function() { self.showMessage( "General error occured.", "e" ); } error: function() { self.showMessage( self.i18n.general_error, "e" ); }
}); });
}; };
@@ -575,11 +593,11 @@ function IFM( params ) {
dataType: "json", dataType: "json",
success: function( data ) { success: function( data ) {
if( data.status == "OK" ) { if( data.status == "OK" ) {
self.showMessage( "File(s) successfully deleted", "s" ); self.showMessage( self.i18n.file_delete_success, "s" );
self.refreshFileTable(); self.refreshFileTable();
} else self.showMessage( "File(s) could not be deleted", "e" ); } else self.showMessage( self.i18n.file_delete_error, "e" );
}, },
error: function() { self.showMessage( "General error occured", "e" ); } error: function() { self.showMessage( self.i18n.general_error, "e" ); }
}); });
}; };
@@ -628,11 +646,11 @@ function IFM( params ) {
dataType: "json", dataType: "json",
success: function(data) { success: function(data) {
if(data.status == "OK") { if(data.status == "OK") {
ifm.showMessage("File successfully renamed", "s"); ifm.showMessage( self.i18n.file_rename_success, "s");
ifm.refreshFileTable(); ifm.refreshFileTable();
} else ifm.showMessage("File could not be renamed: "+data.message, "e"); } else ifm.showMessage( self.i18n.file_rename_error +data.message, "e");
}, },
error: function() { ifm.showMessage("General error occured", "e"); } error: function() { ifm.showMessage( self.i18n.general_error, "e"); }
}); });
}; };
@@ -672,7 +690,7 @@ function IFM( params ) {
} }
}); });
}, },
error: function() { self.hideModal(); self.showMessage( "Error while fetching the folder tree.", "e" ) } error: function() { self.hideModal(); self.showMessage( self.i18n.folder_tree_load_error, "e" ) }
}); });
var form = document.forms.formCopyMove; var form = document.forms.formCopyMove;
form.addEventListener( 'click', function( e ) { form.addEventListener( 'click', function( e ) {
@@ -694,42 +712,40 @@ function IFM( params ) {
/** /**
* Copy or moves a file * Copy or moves a file
* *
* @params {string} source - name of the file * @params {string} sources - array of fileCache items
* @params {string} destination - target directory * @params {string} destination - target directory
* @params {string} action - action (copy|move) * @params {string} action - action (copy|move)
*/ */
this.copyMove = function( sources, destination, action ) { this.copyMove = function( sources, destination, action ) {
if( ! Array.isArray( sources ) ) if( ! Array.isArray( sources ) )
sources = [sources]; sources = [sources];
sources.forEach( function( source ) { var id = self.generateGuid();
var id = self.generateGuid(); self.task_add( { id: id, name: self.i18n[action] + " " + ( sources.length > 1 ? sources.length : sources[0].name ) + " " + self.i18n.file_copy_to + " " + destination } );
self.task_add( { id: id, name: action.charAt(0).toUpperCase() + action.slice(1) + " " + source.name + " to " + destination } ); $.ajax({
$.ajax({ url: self.api,
url: self.api, type: "POST",
type: "POST", data: {
data: { dir: self.currentDir,
dir: self.currentDir, api: "copyMove",
api: "copyMove", action: action,
action: action, filenames: sources.map( function( e ) { return e.name } ),
filename: source.name, destination: destination
destination: destination },
}, dataType: "json",
dataType: "json", success: function( data ) {
success: function( data ) { if( data.status == "OK" ) {
if( data.status == "OK" ) { self.showMessage( data.message, "s" );
self.showMessage( data.message, "s" ); } else {
} else { self.showMessage( data.message, "e" );
self.showMessage( data.message, "e" );
}
self.refreshFileTable();
},
error: function() {
self.showMessage( "General error occured.", "e" );
},
complete: function() {
self.task_done( id );
} }
}); self.refreshFileTable();
},
error: function() {
self.showMessage( self.i18n.general_error, "e" );
},
complete: function() {
self.task_done( id );
}
}); });
}; };
@@ -787,11 +803,11 @@ function IFM( params ) {
dataType: "json", dataType: "json",
success: function( data ) { success: function( data ) {
if( data.status == "OK" ) { if( data.status == "OK" ) {
self.showMessage( "File successfully extracted", "s" ); self.showMessage( data.message, "s" );
self.refreshFileTable(); self.refreshFileTable();
} else self.showMessage( "File could not be extracted. Error: " + data.message, "e" ); } else self.showMessage( data.message, "e" );
}, },
error: function() { self.showMessage( "General error occured", "e" ); }, error: function() { self.showMessage( self.i18n.general_error, "e" ); },
complete: function() { self.task_done( id ); } complete: function() { self.task_done( id ); }
}); });
}; };
@@ -852,11 +868,11 @@ function IFM( params ) {
}, },
success: function(data) { success: function(data) {
if(data.status == "OK") { if(data.status == "OK") {
self.showMessage("File successfully uploaded", "s"); self.showMessage( self.i18n.file_upload_success, "s");
if(data.cd == self.currentDir) self.refreshFileTable(); if(data.cd == self.currentDir) self.refreshFileTable();
} else self.showMessage("File could not be uploaded: "+data.message, "e"); } else self.showMessage( data.message, "e");
}, },
error: function() { self.showMessage("General error occured", "e"); }, error: function() { self.showMessage( self.i18n.general_error, "e"); },
complete: function() { self.task_done(id); } complete: function() { self.task_done(id); }
}); });
self.task_add( { id: id, name: "Upload " + file.name } ); self.task_add( { id: id, name: "Upload " + file.name } );
@@ -881,14 +897,14 @@ function IFM( params ) {
dataType: "json", dataType: "json",
success: function( data ){ success: function( data ){
if( data.status == "OK" ) { if( data.status == "OK" ) {
self.showMessage( "Permissions successfully changed.", "s" ); self.showMessage( self.i18n.permission_change_success, "s" );
self.refreshFileTable(); self.refreshFileTable();
} }
else { else {
self.showMessage( "Permissions could not be changed: "+data.message, "e"); self.showMessage( data.message, "e");
} }
}, },
error: function() { self.showMessage("General error occured.", "e"); } error: function() { self.showMessage( self.i18n.general_error, "e"); }
}); });
}; };
@@ -939,15 +955,15 @@ function IFM( params ) {
dataType: "json", dataType: "json",
success: function(data) { success: function(data) {
if(data.status == "OK") { if(data.status == "OK") {
self.showMessage( "File successfully uploaded", "s" ); self.showMessage( self.i18n.file_upload_success, "s" );
self.refreshFileTable(); self.refreshFileTable();
} else } else
self.showMessage( "File could not be uploaded:<br />" + data.message, "e" ); self.showMessage( self.i18n.file_upload_error + data.message, "e" );
}, },
error: function() { self.showMessage("General error occured", "e"); }, error: function() { self.showMessage( self.i18n.general_error, "e"); },
complete: function() { self.task_done(id); } complete: function() { self.task_done(id); }
}); });
self.task_add( { id: id, name: "Remote upload: "+filename } ); self.task_add( { id: id, name: self.i18n.upload_remote+" "+filename } );
}; };
/** /**
@@ -1016,6 +1032,7 @@ function IFM( params ) {
if( e.key == 'Enter' ) { if( e.key == 'Enter' ) {
e.preventDefault(); e.preventDefault();
if( e.target.value.trim() === '' ) return; if( e.target.value.trim() === '' ) return;
document.getElementById( 'searchResults' ).tBodies[0].innerHTML = '<tr><td style="text-align:center;"><span class="icon icon-spin5 animate-spin"></span></td></tr>';
self.search.lastSearch = e.target.value; self.search.lastSearch = e.target.value;
$.ajax({ $.ajax({
url: self.api, url: self.api,
@@ -1027,17 +1044,89 @@ function IFM( params ) {
}, },
dataType: "json", dataType: "json",
success: function( data ) { success: function( data ) {
data.forEach( function(e) { if( data.status == 'ERROR' ) {
e.folder = e.name.substr( 0, e.name.lastIndexOf( '/' ) ); self.hideModal();
e.linkname = e.name.substr( e.name.lastIndexOf( '/' ) + 1 ); self.showMessage( data.message, "e" );
}); } else {
updateResults( data ); data.forEach( function(e) {
e.folder = e.name.substr( 0, e.name.lastIndexOf( '/' ) );
e.linkname = e.name.substr( e.name.lastIndexOf( '/' ) + 1 );
});
updateResults( data );
}
} }
}); });
} }
}); });
}; };
/**
* Shows the create archive dialog
*/
this.showCreateArchiveDialog = function( items ) {
self.showModal( Mustache.render( self.templates.createarchive, { i18n: self.i18n } ) );
var form = document.forms.formCreateArchive;
form.elements.archivename.addEventListener( 'keypress', function( e ) {
if( e.key == 'Enter' ) {
e.preventDefault();
self.createArchive( items, e.target.value );
self.hideModal();
}
});
form.addEventListener( 'click', function( e ) {
if( e.target.id == 'buttonSave' ) {
e.preventDefault();
self.createArchive( items, form.elements.archivename.value );
self.hideModal();
} else if( e.target.id == 'buttonCancel' ) {
e.preventDefault();
self.hideModal();
}
}, false );
};
this.createArchive = function( items, archivename ) {
var type = "";
if( archivename.substr( -3 ).toLowerCase() == "zip" )
type = "zip";
else if( archivename.substr( -3 ).toLowerCase() == "tar" )
type = "tar";
else if( archivename.substr( -6 ).toLowerCase() == "tar.gz" )
type = "tar.gz";
else if( archivename.substr( -7 ).toLowerCase() == "tar.bz2" )
type = "tar.bz2";
else {
self.showMessage( self.i18n.invalid_archive_format, "e" );
return;
}
var id = self.generateGuid();
self.task_add( { id: id, name: self.i18n.create_archive+" "+archivename } );
$.ajax({
url: self.api,
type: "POST",
data: {
api: "createArchive",
dir: self.currentDir,
archivename: archivename,
filenames: items.map( function( e ) { return e.name; } ),
format: type
},
dataType: "json",
success: function( data ) {
console.log( data );
if( data.status == "OK" ) {
self.showMessage( data.message, "s" );
self.refreshFileTable();
} else
self.showMessage( data.message, "e" );
},
error: function() { self.showMessage( self.i18n.general_error, "e" ); },
complete: function() { self.task_done( id ); }
});
};
// -------------------- // --------------------
// helper functions // helper functions
// -------------------- // --------------------
@@ -1194,7 +1283,10 @@ function IFM( params ) {
var highlightedItem = document.getElementsByClassName( 'highlightedItem' )[0]; var highlightedItem = document.getElementsByClassName( 'highlightedItem' )[0];
if( ! highlightedItem ) { if( ! highlightedItem ) {
highlight( document.getElementById( 'filetable' ).tBodies[0].firstElementChild ); if( document.activeElement.classList.contains( 'ifmitem' ) )
highlight( document.activeElement.parentElement.parentElement );
else
highlight( document.getElementById( 'filetable' ).tBodies[0].firstElementChild );
} else { } else {
var newItem = ( direction=="next" ? highlightedItem.nextElementSibling : highlightedItem.previousElementSibling ); var newItem = ( direction=="next" ? highlightedItem.nextElementSibling : highlightedItem.previousElementSibling );
if( newItem != null ) if( newItem != null )
@@ -1477,7 +1569,7 @@ function IFM( params ) {
self.initLoadTemplates(); self.initLoadTemplates();
}, },
error: function() { error: function() {
throw new Error( "IFM: could not load configuration" ); throw new Error( self.i18n.load_config_error );
} }
}); });
}; };
@@ -1497,7 +1589,7 @@ function IFM( params ) {
self.initLoadI18N(); self.initLoadI18N();
}, },
error: function() { error: function() {
throw new Error( "IFM: could not load templates" ); throw new Error( self.i18n.load_template_error );
} }
}); });
}; };
@@ -1517,7 +1609,7 @@ function IFM( params ) {
self.initApplication(); self.initApplication();
}, },
error: function() { error: function() {
throw new Error( "IFM: could not load I18N" ); throw new Error( self.i18n.load_text_error );
} }
}); });
}; };
@@ -1555,33 +1647,100 @@ function IFM( params ) {
document.getElementById( 'buttonAjaxRequest' ).onclick = function() { self.showAjaxRequestDialog(); }; document.getElementById( 'buttonAjaxRequest' ).onclick = function() { self.showAjaxRequestDialog(); };
if( self.config.upload ) if( self.config.upload )
document.addEventListener( 'dragover', function( e ) { document.addEventListener( 'dragover', function( e ) {
e.preventDefault(); if( Array.prototype.indexOf.call(e.dataTransfer.types, "Files") != -1 ) {
e.stopPropagation();
var div = document.getElementById( 'filedropoverlay' );
div.style.display = 'block';
div.ondrop = function( e ) {
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
var files = e.dataTransfer.files; var div = document.getElementById( 'filedropoverlay' );
for( var i = 0; i < files.length; i++ ) { div.style.display = 'block';
self.uploadFile( files[i] ); div.ondrop = function( e ) {
} e.preventDefault();
if( e.target.id == 'filedropoverlay' ) e.stopPropagation();
e.target.style.display = 'none'; var files = e.dataTransfer.files;
else if( e.target.parentElement.id == 'filedropoverlay' ) { for( var i = 0; i < files.length; i++ ) {
e.target.parentElement.style.display = 'none'; self.uploadFile( files[i] );
} }
}; if( e.target.id == 'filedropoverlay' )
div.ondragleave = function( e ) { e.target.style.display = 'none';
e.preventDefault(); else if( e.target.parentElement.id == 'filedropoverlay' ) {
e.stopPropagation(); e.target.parentElement.style.display = 'none';
if( e.target.id == 'filedropoverlay' ) }
e.target.style.display = 'none'; };
else if( e.target.parentElement.id == 'filedropoverlay' ) { div.ondragleave = function( e ) {
e.target.parentElement.style.display = 'none'; e.preventDefault();
} e.stopPropagation();
}; if( e.target.id == 'filedropoverlay' )
e.target.style.display = 'none';
else if( e.target.parentElement.id == 'filedropoverlay' ) {
e.target.parentElement.style.display = 'none';
}
};
} else {
var div = document.getElementById( 'filedropoverlay' );
if( div.style.display == 'block' )
div.stye.display == 'none';
}
}); });
// drag and drop of filetable items
if( self.config.copymove ) {
var isFile = function(e) { return Array.prototype.indexOf.call(e.dataTransfer.types, "Files") != -1 };
document.addEventListener( 'dragstart', function( e ) {
var selectedItems = document.getElementsByClassName( 'selectedItem' );
var data;
if( selectedItems.length > 0 )
data = self.fileCache.filter(
x => self.inArray(
x.guid,
[].slice.call( selectedItems ).map( function( e ) { return e.dataset.id; } )
)
);
else
data = self.fileCache.find( x => x.guid === e.target.dataset.id );
e.dataTransfer.setData( 'text/plain', JSON.stringify( data ) );
var dragImage = document.createElement( 'div' );
dragImage.style.display = 'inline';
dragImage.style.padding = '10px';
dragImage.innerHTML = '<span class="icon icon-folder-open-empty"></span> '+self.i18n.move+' '+( data.length || data.name );
document.body.appendChild( dragImage );
setTimeout(function() {
dragImage.remove();
});
e.dataTransfer.setDragImage( dragImage, 0, 0 );
});
document.addEventListener( 'dragover', function( e ) { if( ! isFile( e ) && e.target.parentElement.classList.contains( 'isDir' ) ) e.preventDefault(); } );
document.addEventListener( 'dragenter', function( e ) {
if( ! isFile( e ) && e.target.tagName == "TD" && e.target.parentElement.classList.contains( 'isDir' ) )
e.target.parentElement.classList.add( 'highlightedItem' );
});
document.addEventListener( 'dragleave', function( e ) {
if( ! isFile( e ) && e.target.tagName == "TD" && e.target.parentElement.classList.contains( 'isDir' ) )
e.target.parentElement.classList.remove( 'highlightedItem' );
});
document.addEventListener( 'drop', function( e ) {
if( ! isFile( e ) && e.target.tagName == "TD" && e.target.parentElement.classList.contains( 'isDir' ) ) {
e.preventDefault();
e.stopPropagation();
try {
var source = JSON.parse( e.dataTransfer.getData( 'text' ) );
self.log( "source:" );
self.log( source );
var destination = self.fileCache.find( x => x.guid === e.target.firstElementChild.id );
if( ! Array.isArray( source ) )
source = [source];
if( source.find( x => x.name === destination.name ) )
self.showMessage( "Source and destination are equal." );
else
self.copyMove( source, destination.name, "move" );
} catch( e ) {
console.log( e );
} finally {
[].slice.call( document.getElementsByClassName( 'highlightedItem' ) ).forEach( function( e ) {
e.classList.remove( 'highlightedItem' );
});
}
}
});
}
// handle keystrokes // handle keystrokes
document.onkeydown = self.handleKeystrokes; document.onkeydown = self.handleKeystrokes;

View File

@@ -1,37 +1,41 @@
<?php <?php
/* ======================================================================= /**
* =======================================================================
* Improved File Manager * Improved File Manager
* --------------------- * ---------------------
* License: This project is provided under the terms of the MIT LICENSE * License: This project is provided under the terms of the MIT LICENSE
* http://github.com/misterunknown/ifm/blob/master/LICENSE * http://github.com/misterunknown/ifm/blob/master/LICENSE
* ======================================================================= * =======================================================================
* *
* zip class * archive class
* *
* this was adapted from http://php.net/manual/de/class.ziparchive.php#110719 * This class provides support for various archive types for the IFM. It can
* create and extract the following formats:
* * zip
* * tar
* * tar.gz
* * tar.bz2
*/ */
class IFMArchive { class IFMArchive {
/** /**
* Add a folder to the zip file * Add a folder to an archive
*/ */
private static function folderToZip($folder, &$zipFile, $exclusiveLength) { private static function addFolder( &$archive, $folder, $offset=0 ) {
if( $offset == 0 )
$offset = strlen( dirname( $folder ) ) + 1;
$archive->addEmptyDir( substr( $folder, $offset ) );
$handle = opendir( $folder ); $handle = opendir( $folder );
while( false !== $f = readdir( $handle ) ) { while( false !== $f = readdir( $handle ) ) {
if( $f != '.' && $f != '..' ) { if( $f != '.' && $f != '..' ) {
$filePath = "$folder/$f"; $filePath = $folder . '/' . $f;
if( file_exists( $filePath ) && is_readable( $filePath ) ) { if( file_exists( $filePath ) && is_readable( $filePath ) )
// Remove prefix from file path before add to zip. if( is_file( $filePath ) )
$localPath = substr($filePath, $exclusiveLength); $archive->addFile( $filePath, substr( $filePath, $offset ) );
if( is_file( $filePath ) ) { elseif( is_dir( $filePath ) )
$zipFile->addFile( $filePath, $localPath ); self::addFolder( $archive, $filePath, $offset );
} elseif( is_dir( $filePath ) ) {
// Add sub-directory.
$zipFile->addEmptyDir( $localPath );
self::folderToZip( $filePath, $zipFile, $exclusiveLength );
}
}
} }
} }
closedir( $handle ); closedir( $handle );
@@ -40,22 +44,24 @@ class IFMArchive {
/** /**
* Create a zip file * Create a zip file
*/ */
public static function createZip( $src, $out, $root=false ) public static function createZip( $src, $out )
{ {
$z = new ZipArchive(); $a = new ZipArchive();
$z->open( $out, ZIPARCHIVE::CREATE); $a->open( $out, ZIPARCHIVE::CREATE);
if( $root ) {
self::folderToZip( realpath( $src ), $z, strlen( realpath( $src ) . '/' ) ); if( ! is_array( $src ) )
} else { $src = array( $src );
$z->addEmptyDir( basename( $src ) );
self::folderToZip( realpath( $src ), $z, strlen( dirname( $src ) . '/' ) ); foreach( $src as $s )
} if( is_dir( $s ) )
self::addFolder( $a, $s );
elseif( is_file( $s ) )
$a->addFile( $s, substr( $s, strlen( dirname( $s ) ) + 1 ) );
try { try {
if( ( $res = $z->close() ) !== true ) { return $a->close();
throw new Exception("Error while creating zip archive: ". $z->getStatusString());
}
} catch ( Exception $e ) { } catch ( Exception $e ) {
throw $e; return false;
} }
} }
@@ -63,17 +69,54 @@ class IFMArchive {
* Unzip a zip file * Unzip a zip file
*/ */
public static function extractZip( $file, $destination="./" ) { public static function extractZip( $file, $destination="./" ) {
if( ! file_exists( $file ) )
return false;
$zip = new ZipArchive; $zip = new ZipArchive;
$res = $zip->open( $file ); $res = $zip->open( $file );
if( $res === true ) { if( $res === true ) {
$zip->extractTo( $destination ); $zip->extractTo( $destination );
$zip->close(); $zip->close();
return true; return true;
} else { } else
return false;
}
/**
* Creates a tar archive
*/
public static function createTar( $src, $out, $t ) {
$tmpf = substr( $out, 0, strlen( $out ) - strlen( $t ) ) . "tar";
$a = new PharData( $tmpf );
try {
if( ! is_array( $src ) )
$src = array( $src );
foreach( $src as $s )
if( is_dir( $s ) )
self::addFolder( $a, $s );
elseif( is_file( $s ) )
$a->addFile( $s, substr( $s, strlen( dirname( $s ) ) +1 ) );
switch( $t ) {
case "tar.gz":
$a->compress( Phar::GZ );
@unlink( $tmpf );
break;
case "tar.bz2":
$a->compress( Phar::BZ2 );
@unlink( $tmpf );
break;
}
return true;
} catch( Exception $e ) {
@unlink( $tmpf );
return false; return false;
} }
} }
/**
* Extracts a tar archive
*/
public static function extractTar( $file, $destination="./" ) { public static function extractTar( $file, $destination="./" ) {
if( ! file_exists( $file ) ) if( ! file_exists( $file ) )
return false; return false;
@@ -81,13 +124,8 @@ class IFMArchive {
try { try {
$tar->extractTo( $destination, null, true ); $tar->extractTo( $destination, null, true );
return true; return true;
} catch (Exception $e) { } catch( Exception $e ) {
return false; return false;
} }
} }
public static function createTar( $src, $out, $root=false ) {
$tar = new PharData( $out );
$tar->buildFromDirectory( $src );
}
} }

View File

@@ -14,8 +14,6 @@ error_reporting( E_ALL );
ini_set( 'display_errors', 'OFF' ); ini_set( 'display_errors', 'OFF' );
class IFM { class IFM {
const VERSION = '2.4.2';
private $defaultconfig = array( private $defaultconfig = array(
// general config // general config
"auth" => 0, "auth" => 0,
@@ -24,7 +22,7 @@ class IFM {
"tmp_dir" => "", "tmp_dir" => "",
"defaulttimezone" => "Europe/Berlin", "defaulttimezone" => "Europe/Berlin",
"forbiddenChars" => array(), "forbiddenChars" => array(),
"language" => "en", "language" => "@@@vars:defaultlanguage@@@",
// api controls // api controls
"ajaxrequest" => 1, "ajaxrequest" => 1,
@@ -40,6 +38,7 @@ class IFM {
"remoteupload" => 1, "remoteupload" => 1,
"rename" => 1, "rename" => 1,
"zipnload" => 1, "zipnload" => 1,
"createarchive" => 1,
// gui controls // gui controls
"showlastmodified" => 0, "showlastmodified" => 0,
@@ -86,6 +85,7 @@ class IFM {
$this->config['remoteupload'] = getenv('IFM_API_REMOTEUPLOAD') !== false ? intval( getenv('IFM_API_REMOTEUPLOAD') ) : $this->config['remoteupload'] ; $this->config['remoteupload'] = getenv('IFM_API_REMOTEUPLOAD') !== false ? intval( getenv('IFM_API_REMOTEUPLOAD') ) : $this->config['remoteupload'] ;
$this->config['rename'] = getenv('IFM_API_RENAME') !== false ? intval( getenv('IFM_API_RENAME') ) : $this->config['rename'] ; $this->config['rename'] = getenv('IFM_API_RENAME') !== false ? intval( getenv('IFM_API_RENAME') ) : $this->config['rename'] ;
$this->config['zipnload'] = getenv('IFM_API_ZIPNLOAD') !== false ? intval( getenv('IFM_API_ZIPNLOAD') ) : $this->config['zipnload'] ; $this->config['zipnload'] = getenv('IFM_API_ZIPNLOAD') !== false ? intval( getenv('IFM_API_ZIPNLOAD') ) : $this->config['zipnload'] ;
$this->config['createarchive'] = getenv('IFM_API_CREATEARCHIVE') !== false ? intval( getenv('IFM_API_CREATEARCHIVE') ) : $this->config['createarchive'] ;
$this->config['showlastmodified'] = getenv('IFM_GUI_SHOWLASTMODIFIED') !== false ? intval( getenv('IFM_GUI_SHOWLASTMODIFIED') ) : $this->config['showlastmodified'] ; $this->config['showlastmodified'] = getenv('IFM_GUI_SHOWLASTMODIFIED') !== false ? intval( getenv('IFM_GUI_SHOWLASTMODIFIED') ) : $this->config['showlastmodified'] ;
$this->config['showfilesize'] = getenv('IFM_GUI_SHOWFILESIZE') !== false ? intval( getenv('IFM_GUI_SHOWFILESIZE') ) : $this->config['showfilesize'] ; $this->config['showfilesize'] = getenv('IFM_GUI_SHOWFILESIZE') !== false ? intval( getenv('IFM_GUI_SHOWFILESIZE') ) : $this->config['showfilesize'] ;
$this->config['showowner'] = getenv('IFM_GUI_SHOWOWNER') !== false ? intval( getenv('IFM_GUI_SHOWOWNER') ) : $this->config['showowner'] ; $this->config['showowner'] = getenv('IFM_GUI_SHOWOWNER') !== false ? intval( getenv('IFM_GUI_SHOWOWNER') ) : $this->config['showowner'] ;
@@ -123,6 +123,9 @@ f00bar;
f00bar; f00bar;
$templates['createdir'] = <<<'f00bar' $templates['createdir'] = <<<'f00bar'
@@@file:src/templates/modal.createdir.html@@@ @@@file:src/templates/modal.createdir.html@@@
f00bar;
$templates['createarchive'] = <<<'f00bar'
@@@file:src/templates/modal.createarchive.html@@@
f00bar; f00bar;
$templates['deletefile'] = <<<'f00bar' $templates['deletefile'] = <<<'f00bar'
@@@file:src/templates/modal.deletefile.html@@@ @@@file:src/templates/modal.deletefile.html@@@
@@ -154,15 +157,13 @@ f00bar;
$this->templates = $templates; $this->templates = $templates;
$i18n = array(); $i18n = array();
$i18n['en'] = <<<'f00bar' @@@vars:languageincludes@@@
@@@file:src/i18n/en.json@@@
f00bar;
$i18n['en'] = json_decode($i18n['en'], true);
$i18n['de'] = <<<'f00bar'
@@@file:src/i18n/de.json@@@
f00bar;
$i18n['de'] = json_decode($i18n['de'], true);
$this->i18n = $i18n; $this->i18n = $i18n;
if( in_array( $this->config['language'], array_keys( $this->i18n ) ) )
$this->l = $this->i18n[$this->config['language']];
else
$this->l = $this->i18n[0];
} }
/** /**
@@ -228,9 +229,9 @@ f00bar;
private function handleRequest() { private function handleRequest() {
if( $_REQUEST["api"] == "getRealpath" ) { if( $_REQUEST["api"] == "getRealpath" ) {
if( isset( $_REQUEST["dir"] ) && $_REQUEST["dir"] != "" ) if( isset( $_REQUEST["dir"] ) && $_REQUEST["dir"] != "" )
echo $this->jsonResponse( array( "realpath" => $this->getValidDir( $_REQUEST["dir"] ) ) ); $this->jsonResponse( array( "realpath" => $this->getValidDir( $_REQUEST["dir"] ) ) );
else else
echo $this->jsonResponse( array( "realpath" => "" ) ); $this->jsonResponse( array( "realpath" => "" ) );
} }
elseif( $_REQUEST["api"] == "getFiles" ) { elseif( $_REQUEST["api"] == "getFiles" ) {
if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) ) if( isset( $_REQUEST["dir"] ) && $this->isPathValid( $_REQUEST["dir"] ) )
@@ -244,9 +245,9 @@ f00bar;
elseif( $_REQUEST["api"] == "getFolders" ) { elseif( $_REQUEST["api"] == "getFolders" ) {
$this->getFolders( $_REQUEST ); $this->getFolders( $_REQUEST );
} elseif( $_REQUEST["api"] == "getTemplates" ) { } elseif( $_REQUEST["api"] == "getTemplates" ) {
echo $this->jsonResponse( $this->templates ); $this->jsonResponse( $this->templates );
} elseif( $_REQUEST["api"] == "getI18N" ) { } elseif( $_REQUEST["api"] == "getI18N" ) {
echo $this->jsonResponse( $this->i18n[$this->config['language']] ); $this->jsonResponse( $this->l );
} elseif( $_REQUEST["api"] == "logout" ) { } elseif( $_REQUEST["api"] == "logout" ) {
unset( $_SESSION ); unset( $_SESSION );
session_destroy(); session_destroy();
@@ -271,7 +272,7 @@ f00bar;
case "getFolderTree": $this->getFolderTree( $_REQUEST ); break; case "getFolderTree": $this->getFolderTree( $_REQUEST ); break;
case "createArchive": $this->createArchive( $_REQUEST ); break; case "createArchive": $this->createArchive( $_REQUEST ); break;
default: default:
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid api action given" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid api action given" ) );
break; break;
} }
} else { } else {
@@ -303,6 +304,7 @@ f00bar;
api functions api functions
*/ */
private function getFiles( $dir ) { private function getFiles( $dir ) {
$this->chDirIfNecessary( $dir ); $this->chDirIfNecessary( $dir );
@@ -381,7 +383,7 @@ f00bar;
$ret = $this->config; $ret = $this->config;
$ret['inline'] = ( $this->mode == "inline" ) ? true : false; $ret['inline'] = ( $this->mode == "inline" ) ? true : false;
$ret['isDocroot'] = ( $this->getRootDir() == $this->getScriptRoot() ) ? true : false; $ret['isDocroot'] = ( $this->getRootDir() == $this->getScriptRoot() ) ? true : false;
echo $this->jsonResponse( $ret ); $this->jsonResponse( $ret );
} }
private function getFolders( $d ) { private function getFolders( $d ) {
@@ -409,21 +411,21 @@ f00bar;
), ),
$ret $ret
); );
echo $this->jsonResponse( $ret ); $this->jsonResponse( $ret );
} }
} }
private function searchItems( $d ) { private function searchItems( $d ) {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( strpos( $d['pattern'], '/' ) !== false ) { if( strpos( $d['pattern'], '/' ) !== false ) {
echo json_decode( array( "status" => "ERROR", "message" => "Pattern must not contain slashes" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['pattern_error_slashes'] ) );
exit( 1 ); exit( 1 );
} }
try { try {
$results = $this->searchItemsRecursive( $d['pattern'] ); $results = $this->searchItemsRecursive( $d['pattern'] );
echo $this->jsonResponse( $results ); $this->jsonResponse( $results );
} catch( Exception $e ) { } catch( Exception $e ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => $e->getMessage() ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['error'] . " " . $e->getMessage() ) );
} }
} }
@@ -440,7 +442,7 @@ f00bar;
} }
private function getFolderTree( $d ) { private function getFolderTree( $d ) {
echo $this->jsonResponse( $this->jsonResponse(
array_merge( array_merge(
array( array(
0 => array( 0 => array(
@@ -479,65 +481,75 @@ f00bar;
private function copyMove( $d ) { private function copyMove( $d ) {
if( $this->config['copymove'] != 1 ) { if( $this->config['copymove'] != 1 ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to copy or move files." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
exit( 1 ); exit( 1 );
} }
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( ! isset( $d['destination'] ) || ! $this->isPathValid( realpath( $d['destination'] ) ) ) { if( ! isset( $d['destination'] ) || ! $this->isPathValid( realpath( $d['destination'] ) ) ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid destination directory given." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_dir'] ) );
exit( 1 ); exit( 1 );
} }
if( ! file_exists( $d['filename'] ) || $d['filename'] == ".." ) { if( ! is_array( $d['filenames'] ) ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid filename given." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_params'] ) );
exit( 1 ); exit( 1 );
} }
if( $d['action'] == "copy" ) { if( ! in_array( $d['action'], array( 'copy', 'move' ) ) ) {
if( $this->xcopy( $d['filename'], $d['destination'] ) ) { $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_action'] ) );
echo $this->jsonResponse( array( "status" => "OK", "message" => "File(s) were successfully copied." ) );
exit( 0 );
} else {
$err = error_get_last();
echo $this->jsonResponse( array( "status" => "ERROR", "message" => $err['message'] ) );
exit( 1 );
}
} elseif( $d['action'] == "move" ) {
if( rename( $d['filename'], $this->pathCombine( $d['destination'], basename( $d['filename'] ) ) ) ) {
echo $this->jsonResponse( array( "status" => "OK", "message" => "File(s) were successfully moved." ) );
exit( 0 );
} else {
$err = error_get_last();
echo $this->jsonResponse( array( "status" => "ERROR", "message" => $err['message'] ) );
exit( 1 );
}
} else {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid action given." ) );
exit( 1 ); exit( 1 );
} }
$err = array(); $errFlag = -1; // -1 -> all errors; 0 -> at least some errors; 1 -> no errors
foreach( $d['filenames'] as $file ) {
if( ! file_exists( $file ) || $file == ".." || ! $this->isFilenameValid( $file ) ) {
array_push( $err, $file );
}
if( $d['action'] == "copy" ) {
if( $this->xcopy( $file, $d['destination'] ) )
$errFlag = 0;
else
array_push( $err, $file );
} elseif( $d['action'] == "move" ) {
if( rename( $file, $this->pathCombine( $d['destination'], basename( $file ) ) ) )
$errFlag = 0;
else
array_push( $err, $file );
}
}
$action = ( $d['action'] == "copy" ? "copied" : "moved" );
if( empty( $err ) ) {
$this->jsonResponse( array( "status" => "OK", "message" => ( $d['action'] == "copy" ? $this->l['copy_success'] : $this->l['move_success'] ), "errflag" => "1" ) );
}
else {
$errmsg = ( $d['action'] == "copy" ? $this->l['copy_error'] : $this->l['move_error'] ) . "<ul>";
foreach( $err as $item )
$errmsg .= "<li>".$item."</li>";
$errmsg .= "</ul>";
$this->jsonResponse( array( "status" => "OK", "message" => $errmsg, "flag" => $errFlag ) );
}
} }
// creates a directory // creates a directory
private function createDir($w, $dn) { private function createDir($w, $dn) {
if( $this->config['createdir'] != 1 ) { if( $this->config['createdir'] != 1 ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to create directories.") ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
exit( 1 ); exit( 1 );
} }
if( $dn == "" ) if( $dn == "" )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid directory name") ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_dir'] ) );
elseif( ! $this->isFilenameValid( $dn ) ) elseif( ! $this->isFilenameValid( $dn ) )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid directory name" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_dir'] ) );
else { else {
$this->chDirIfNecessary( $w ); $this->chDirIfNecessary( $w );
if( @mkdir( $dn ) ) if( @mkdir( $dn ) )
echo $this->jsonResponse( array( "status" => "OK", "message" => "Directory successful created" ) ); $this->jsonResponse( array( "status" => "OK", "message" => $this->l['folder_create_success'] ) );
else else
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Could not create directory" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['folder_create_error'] ) );
} }
} }
// save a file // save a file
private function saveFile( $d ) { private function saveFile( $d ) {
if( ( file_exists( $this->pathCombine( $d['dir'], $d['filename'] ) ) && $this->config['edit'] != 1 ) || ( ! file_exists( $this->pathCombine( $d['dir'], $d['filename'] ) ) && $this->config['createfile'] != 1 ) ) { if( ( file_exists( $this->pathCombine( $d['dir'], $d['filename'] ) ) && $this->config['edit'] != 1 ) || ( ! file_exists( $this->pathCombine( $d['dir'], $d['filename'] ) ) && $this->config['createfile'] != 1 ) ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "You are not allowed to edit/create this file." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
exit( 1 ); exit( 1 );
} }
if( isset( $d['filename'] ) && $this->isFilenameValid( $d['filename'] ) ) { if( isset( $d['filename'] ) && $this->isFilenameValid( $d['filename'] ) ) {
@@ -546,34 +558,34 @@ f00bar;
// work around magic quotes // work around magic quotes
$content = get_magic_quotes_gpc() == 1 ? stripslashes( $d['content'] ) : $d['content']; $content = get_magic_quotes_gpc() == 1 ? stripslashes( $d['content'] ) : $d['content'];
if( @file_put_contents( $d['filename'], $content ) !== false ) { if( @file_put_contents( $d['filename'], $content ) !== false ) {
echo $this->jsonResponse( array( "status" => "OK", "message" => "File successfully saved" ) ); $this->jsonResponse( array( "status" => "OK", "message" => $this->l['file_save_success'] ) );
} else } else
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Could not write content" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['file_save_error'] ) );
} else } else
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Got no content" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['file_save_error'] ) );
} else } else
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid filename given" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_filename'] ) );
} }
// 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( $this->config['edit'] != 1 ) if( $this->config['edit'] != 1 )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "You are not allowed to edit files." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['npermissions'] ) );
else { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( isset( $d['filename'] ) && $this->isFilenameAllowed( $d['filename'] ) && file_exists( $d['filename'] ) && is_readable( $d['filename'] ) ) { if( isset( $d['filename'] ) && $this->isFilenameAllowed( $d['filename'] ) && file_exists( $d['filename'] ) && is_readable( $d['filename'] ) ) {
$content = @file_get_contents( $d['filename'] ); $content = @file_get_contents( $d['filename'] );
if( function_exists( "mb_check_encoding" ) && ! mb_check_encoding( $content, "UTF-8" ) ) if( function_exists( "mb_check_encoding" ) && ! mb_check_encoding( $content, "UTF-8" ) )
$content = utf8_encode( $content ); $content = utf8_encode( $content );
echo $this->jsonResponse( array( "status" => "OK", "data" => array( "filename" => $d['filename'], "content" => $content ) ) ); $this->jsonResponse( array( "status" => "OK", "data" => array( "filename" => $d['filename'], "content" => $content ) ) );
} else echo $this->jsonResponse( array( "status" => "ERROR", "message" => "File not found or not readable." ) ); } else $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['file_not_found'] ) );
} }
} }
// deletes a bunch of files or directories // deletes a bunch of files or directories
private function deleteFiles( array $d ) { private function deleteFiles( array $d ) {
if( $this->config['delete'] != 1 ) $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to delete files" ) ); if( $this->config['delete'] != 1 ) $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
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
@@ -596,14 +608,14 @@ f00bar;
} }
} }
if( empty( $err ) ) { if( empty( $err ) ) {
echo $this->jsonResponse( array( "status" => "OK", "message" => "Files deleted successfully", "errflag" => "1" ) ); $this->jsonResponse( array( "status" => "OK", "message" => $this->l['file_delete_success'], "errflag" => "1" ) );
} }
else { else {
$errmsg = "The following files could not be deleted:<ul>"; $errmsg = $this->l['file_delete_error'] . "<ul>";
foreach($err as $item) foreach($err as $item)
$errmsg .= "<li>".$item."</li>"; $errmsg .= "<li>".$item."</li>";
$errmsg .= "</ul>"; $errmsg .= "</ul>";
echo $this->jsonResponse( array( "status" => "OK", "message" => $errmsg, "flag" => $errFLAG ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $errmsg, "flag" => $errFLAG ) );
} }
} }
} }
@@ -611,22 +623,22 @@ f00bar;
// renames a file // renames a file
private function renameFile( array $d ) { private function renameFile( array $d ) {
if( $this->config['rename'] != 1 ) { if( $this->config['rename'] != 1 ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to rename files" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
} elseif( ! $this->isFilenameValid( $d['filename'] ) ) { } elseif( ! $this->isFilenameValid( $d['filename'] ) ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid file name given" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_filename'] ) );
} else { } else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( strpos( $d['newname'], '/' ) !== false ) if( strpos( $d['newname'], '/' ) !== false )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No slashes allowed in filenames" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['filename_slashes'] ) );
elseif( $this->config['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 $this->jsonResponse( array( "status" => "ERROR", "message" => "Not allowed to rename this file" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
elseif( $this->config['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 $this->jsonResponse( array( "status" => "ERROR", "message" => "Not allowed to rename file" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
else { else {
if( @rename( $d['filename'], $d['newname'] ) ) if( @rename( $d['filename'], $d['newname'] ) )
echo $this->jsonResponse( array( "status" => "OK", "message" => "File successful renamed" ) ); $this->jsonResponse( array( "status" => "OK", "message" => $this->l['file_rename_success'] ) );
else else
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "File could not be renamed" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['file_rename_error'] ) );
} }
} }
} }
@@ -634,11 +646,11 @@ f00bar;
// provides a file for downloading // provides a file for downloading
private function downloadFile( array $d ) { private function downloadFile( array $d ) {
if( $this->config['download'] != 1 ) if( $this->config['download'] != 1 )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Not allowed to download files" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
elseif( $this->config['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 $this->jsonResponse( array( "status" => "ERROR", "message"=>"Not allowed to download htdocs" ) ); $this->jsonResponse( array( "status" => "ERROR", "message"=> $this->l['nopermissions'] ) );
elseif( $this->config['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 $this->jsonResponse( array( "status" => "ERROR", "message" => "Not allowed to download hidden files" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
else { else {
$this->chDirIfNecessary( $d["dir"] ); $this->chDirIfNecessary( $d["dir"] );
$this->fileDownload( $d['filename'] ); $this->fileDownload( $d['filename'] );
@@ -648,34 +660,34 @@ f00bar;
// extracts a zip-archive // extracts a zip-archive
private function extractFile( array $d ) { private function extractFile( array $d ) {
if( $this->config['extract'] != 1 ) if( $this->config['extract'] != 1 )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to extract files" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
else { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( ! file_exists( $d['filename'] ) ) { if( ! file_exists( $d['filename'] ) ) {
echo $this->jsonResponse( array( "status" => "ERROR","message" => "No valid archive found" ) ); $this->jsonResponse( array( "status" => "ERROR","message" => $this->l['invalid_filename'] ) );
exit( 1 ); exit( 1 );
} }
if( ! isset( $d['targetdir'] ) || trim( $d['targetdir'] ) == "" ) if( ! isset( $d['targetdir'] ) || trim( $d['targetdir'] ) == "" )
$d['targetdir'] = "./"; $d['targetdir'] = "./";
if( ! $this->isPathValid( $d['targetdir'] ) ) { if( ! $this->isPathValid( $d['targetdir'] ) ) {
echo $this->jsonResponse( array( "status" => "ERROR","message" => "Target directory is not valid." ) ); $this->jsonResponse( array( "status" => "ERROR","message" => $this->l['invalid_dir'] ) );
exit( 1 ); exit( 1 );
} }
if( ! is_dir( $d['targetdir'] ) && ! mkdir( $d['targetdir'], 0777, true ) ) { if( ! is_dir( $d['targetdir'] ) && ! mkdir( $d['targetdir'], 0777, true ) ) {
echo $this->jsonResponse( array( "status" => "ERROR","message" => "Could not create target directory." ) ); $this->jsonResponse( array( "status" => "ERROR","message" => $this->l['folder_create_error'] ) );
exit( 1 ); exit( 1 );
} }
if( substr( strtolower( $d['filename'] ), -4 ) == ".zip" ) { if( substr( strtolower( $d['filename'] ), -4 ) == ".zip" ) {
if( ! IFMArchive::extractZip( $d['filename'], $d['targetdir'] ) ) { if( ! IFMArchive::extractZip( $d['filename'], $d['targetdir'] ) ) {
echo $this->jsonResponse( array( "status" => "ERROR","message" => "File could not be extracted" ) ); $this->jsonResponse( array( "status" => "ERROR","message" => $this->l['extract_error'] ) );
} else { } else {
echo $this->jsonResponse( array( "status" => "OK","message" => "File successfully extracted." ) ); $this->jsonResponse( array( "status" => "OK","message" => $this->l['extract_success'] ) );
} }
} else { } else {
if( ! IFMArchive::extractTar( $d['filename'], $d['targetdir'] ) ) { if( ! IFMArchive::extractTar( $d['filename'], $d['targetdir'] ) ) {
echo $this->jsonResponse( array( "status" => "ERROR","message" => "File could not be extracted" ) ); $this->jsonResponse( array( "status" => "ERROR","message" => $this->l['extract_error'] ) );
} else { } else {
echo $this->jsonResponse( array( "status" => "OK","message" => "File successfully extracted." ) ); $this->jsonResponse( array( "status" => "OK","message" => $this->l['extract_success'] ) );
} }
} }
} }
@@ -684,35 +696,35 @@ f00bar;
// uploads a file // uploads a file
private function uploadFile( array $d ) { private function uploadFile( array $d ) {
if( $this->config['upload'] != 1 ) if( $this->config['upload'] != 1 )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to upload files" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
elseif( !isset( $_FILES['file'] ) ) elseif( !isset( $_FILES['file'] ) )
echo $this->jsonResponse( array( "file" => $_FILE,"files" => $_FILES ) ); $this->jsonResponse( 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( ! $this->isFilenameValid( $newfilename ) ) if( ! $this->isFilenameValid( $newfilename ) )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Invalid filename given" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_filename'] ) );
else { else {
if( $_FILES['file']['tmp_name'] ) { if( $_FILES['file']['tmp_name'] ) {
if( is_writable( getcwd( ) ) ) { if( is_writable( getcwd( ) ) ) {
if( move_uploaded_file( $_FILES['file']['tmp_name'], $newfilename ) ) if( move_uploaded_file( $_FILES['file']['tmp_name'], $newfilename ) )
echo $this->jsonResponse( array( "status" => "OK", "message" => "The file ".$_FILES['file']['name']." was uploaded successfully", "cd" => $d['dir'] ) ); $this->jsonResponse( array( "status" => "OK", "message" => $this->l['file_upload_success'], "cd" => $d['dir'] ) );
else else
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "File could not be uploaded" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['file_upload_error'] ) );
} }
else else
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "File could not be uploaded since it has no permissions to write in this directory" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['file_upload_success'] ) );
} else } else
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No file found" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['file_not_found'] ) );
} }
} }
} }
// change permissions of a file // change permissions of a file
private function changePermissions( array $d ) { private function changePermissions( array $d ) {
if( $this->config['chmod'] != 1 ) echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No rights to change permissions" ) ); if( $this->config['chmod'] != 1 ) $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
elseif( ! isset( $d["chmod"] )||$d['chmod']=="" ) echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Could not identify new permissions" ) ); elseif( ! isset( $d["chmod"] )||$d['chmod']=="" ) $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['permission_parse_error'] ) );
elseif( ! $this->isPathValid( $this->pathCombine( $d['dir'],$d['filename'] ) ) ) { echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Not allowed to change the permissions" ) ); } elseif( ! $this->isPathValid( $this->pathCombine( $d['dir'],$d['filename'] ) ) ) { $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) ); }
else { else {
$this->chDirIfNecessary( $d['dir'] ); $chmod = $d["chmod"]; $cmi = true; $this->chDirIfNecessary( $d['dir'] ); $chmod = $d["chmod"]; $cmi = true;
if( ! is_numeric( $chmod ) ) { if( ! is_numeric( $chmod ) ) {
@@ -737,12 +749,12 @@ f00bar;
if( $cmi ) { if( $cmi ) {
try { try {
chmod( $d["filename"], (int)octdec( $chmod ) ); chmod( $d["filename"], (int)octdec( $chmod ) );
echo $this->jsonResponse( array( "status" => "OK", "message" => "Permissions changed successfully" ) ); $this->jsonResponse( array( "status" => "OK", "message" => $this->l['permission_change_success'] ) );
} catch ( Exception $e ) { } catch ( Exception $e ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Error while changing permissions" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['permission_change_error'] ) );
} }
} }
else echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Could not determine permission format" ) ); else $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['permission_parse_error'] ) );
} }
} }
@@ -750,18 +762,18 @@ f00bar;
// 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( $this->config['zipnload'] != 1 ) if( $this->config['zipnload'] != 1 )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to download directories" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermission'] ) );
else { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
if( ! file_exists( $d['filename'] ) ) if( ! file_exists( $d['filename'] ) )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Directory not found" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['folder_not_found'] ) );
elseif ( ! $this->isFilenameValid( $d['filename'] ) ) elseif ( ! $this->isFilenameValid( $d['filename'] ) )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Filename not valid" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_filename'] ) );
else { else {
unset( $zip ); unset( $zip );
$dfile = $this->pathCombine( $this->config['tmp_dir'], uniqid( "ifm-tmp-" ) . ".zip" ); // temporary filename $dfile = $this->pathCombine( $this->config['tmp_dir'], uniqid( "ifm-tmp-" ) . ".zip" ); // temporary filename
try { try {
IFMArchive::createZip( realpath( $d['filename'] ), $dfile, ( $d['filename'] == "." ) ); IFMArchive::createZip( realpath( $d['filename'] ), $dfile );
if( $d['filename'] == "." ) { if( $d['filename'] == "." ) {
if( getcwd() == $this->getScriptRoot() ) if( getcwd() == $this->getScriptRoot() )
$d['filename'] = "root"; $d['filename'] = "root";
@@ -770,7 +782,7 @@ f00bar;
} }
$this->fileDownload( $dfile, $d['filename'] . ".zip" ); $this->fileDownload( $dfile, $d['filename'] . ".zip" );
} catch ( Exception $e ) { } catch ( Exception $e ) {
echo "An error occured: " . $e->getMessage(); echo $this->l['error'] . " " . $e->getMessage();
} finally { } finally {
if( file_exists( $dfile ) ) @unlink( $dfile ); if( file_exists( $dfile ) ) @unlink( $dfile );
} }
@@ -781,65 +793,92 @@ f00bar;
// 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( $this->config['remoteupload'] != 1 ) if( $this->config['remoteupload'] != 1 )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to remote upload files" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
elseif( !isset( $d['method'] ) || !in_array( $d['method'], array( "curl", "file" ) ) ) elseif( !isset( $d['method'] ) || !in_array( $d['method'], array( "curl", "file" ) ) )
echo $this->jsonResponse( array( "status" => "error", "message" => "Invalid method given. Valid methods: ['curl', 'file']" ) ); $this->jsonResponse( array( "status" => "error", "message" => $this->l['invalid_params'] ) );
elseif( $d['method']=="curl" && $this->checkCurl( ) == false ) elseif( $d['method']=="curl" && $this->checkCurl( ) == false )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "cURL extention not installed. Please install the cURL extention to use remote file upload." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['error']." cURL extention not installed." ) );
elseif( $d['method']=="curl" && $this->checkCurl( ) == true ) { elseif( $d['method']=="curl" && $this->checkCurl( ) == true ) {
$filename = ( isset( $d['filename'] )&&$d['filename']!="" )?$d['filename']:"curl_".uniqid( ); $filename = ( isset( $d['filename'] )&&$d['filename']!="" )?$d['filename']:"curl_".uniqid( );
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
$ch = curl_init( ); $ch = curl_init( );
if( $ch ) { if( $ch ) {
if( $this->isFilenameValid( $filename ) == false ) if( $this->isFilenameValid( $filename ) == false )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "This filename is not valid." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_filename'] ) );
elseif( filter_var( $d['url'], FILTER_VALIDATE_URL ) === false ) elseif( filter_var( $d['url'], FILTER_VALIDATE_URL ) === false )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "The passed URL is not valid" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_url'] ) );
else { else {
$fp = fopen( $filename, "w" ); $fp = fopen( $filename, "w" );
if( $fp ) { if( $fp ) {
if( !curl_setopt( $ch, CURLOPT_URL, $d['url'] ) || !curl_setopt( $ch, CURLOPT_FILE, $fp ) || !curl_setopt( $ch, CURLOPT_HEADER, 0 ) || !curl_exec( $ch ) ) if( !curl_setopt( $ch, CURLOPT_URL, $d['url'] ) || !curl_setopt( $ch, CURLOPT_FILE, $fp ) || !curl_setopt( $ch, CURLOPT_HEADER, 0 ) || !curl_exec( $ch ) )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Failed to set options and execute cURL" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['error']." ".curl_error( $ch ) ) );
else { else {
echo $this->jsonResponse( array( "status" => "OK", "message" => "File sucessfully uploaded" ) ); $this->jsonResponse( array( "status" => "OK", "message" => $this->l['file_upload_success'] ) );
} }
curl_close( $ch ); curl_close( $ch );
fclose( $fp ); fclose( $fp );
} else { } else {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Failed to open file" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['file_open_error'] ) );
} }
} }
} else { } else {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "Failed to init cURL." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['error']." curl init" ) );
} }
} }
elseif( $d['method']=='file' ) { elseif( $d['method']=='file' ) {
$filename = ( isset( $d['filename'] ) && $d['filename']!="" ) ? $d['filename'] : "curl_".uniqid( ); $filename = ( isset( $d['filename'] ) && $d['filename']!="" ) ? $d['filename'] : "curl_".uniqid( );
if( $this->isFilenameValid( $filename ) == false ) if( $this->isFilenameValid( $filename ) == false )
echo $this->jsonResponse( array( "status" => "ERROR", "message" => "This filename is not valid." ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_filename'] ) );
else { else {
$this->chDirIfNecessary( $d['dir'] ); $this->chDirIfNecessary( $d['dir'] );
try { try {
file_put_contents( $filename, file_get_contents( $d['url'] ) ); file_put_contents( $filename, file_get_contents( $d['url'] ) );
echo $this->jsonResponse( array( "status" => "OK", "message" => "File successfully uploaded" ) ); $this->jsonResponse( array( "status" => "OK", "message" => $this->l['file_upload_success'] ) );
} catch( Exception $e ) { } catch( Exception $e ) {
echo $this->jsonResponse( array( "status" => "ERROR", "message" => $e->getMessage() ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['error'] . " " . $e->getMessage() ) );
} }
} }
} }
else else
echo $this->jsonResponse( array( "status" => "error", "message" => "Corrupt parameter data" ) ); $this->jsonResponse( array( "status" => "error", "message" => $this->l['invalid_params'] ) );
} }
private function createArchive( $d ) { private function createArchive( $d ) {
// if( $config['createarchive'] != 1 ) { if( $this->config['createarchive'] != 1 ) {
// echo $this->jsonResponse( array( "status" => "ERROR", "message" => "No permission to create archives" ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['nopermissions'] ) );
// return false; return false;
// } }
// $this->chDirIfNecessary( $d['dir'] ); if( ! $this->isFilenameValid( $d['archivename'] ) ) {
// switch( $d['format'] ) { $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_filename'] ) );
// case "zip": return false;
// }
$this->chDirIfNecessary( $d['dir'] );
$filenames = array();
foreach( $d['filenames'] as $file )
if( ! $this->isFilenameValid( $file ) ) {
$this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['invalid_filename'] ) );
exit( 1 );
} else
array_push( $filenames, realpath( $file ) );
switch( $d['format'] ) {
case "zip":
if( IFMArchive::createZip( $filenames, $d['archivename'] ) )
$this->jsonResponse( array( "status" => "OK", "message" => $this->l['archive_create_success'] ) );
else
$this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['archive_create_error'] ) );
break;
case "tar":
case "tar.gz":
case "tar.bz2":
if( IFMArchive::createTar( $filenames, $d['archivename'], $d['format'] ) )
$this->jsonResponse( array( "status" => "OK", "message" => $this->l['archive_create_success'] ) );
else
$this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['archive_create_error'] ) );
break;
default:
$this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['archive_invalid_format'] ) );
break;
}
} }
/* /*
@@ -878,7 +917,7 @@ f00bar;
break; break;
} }
$this->jsonResponse( array( "status" => "ERROR", "message" => "Could not encode json: " . $err ) ); $this->jsonResponse( array( "status" => "ERROR", "message" => $this->l['json_encode_error'] . " " . $err ) );
} else { } else {
echo $json; echo $json;
} }
@@ -913,9 +952,9 @@ f00bar;
} else { } else {
if( isset( $_POST["api"] ) ) { if( isset( $_POST["api"] ) ) {
if( $login_failed === true ) if( $login_failed === true )
echo $this->jsonResponse( array( "status"=>"ERROR", "message"=>"authentication failed" ) ); $this->jsonResponse( array( "status"=>"ERROR", "message"=>"authentication failed" ) );
else else
echo $this->jsonResponse( array( "status"=>"ERROR", "message"=>"not authenticated" ) ); $this->jsonResponse( array( "status"=>"ERROR", "message"=>"not authenticated" ) );
} else { } else {
$this->loginForm($login_failed); $this->loginForm($login_failed);
} }
@@ -962,9 +1001,8 @@ f00bar;
$authenticated = false; $authenticated = false;
} }
ldap_unbind( $ds ); ldap_unbind( $ds );
} else { } else
$authenticated = false; $authenticated = false;
}
return $authenticated; return $authenticated;
break; break;
} }
@@ -974,12 +1012,12 @@ f00bar;
private function loginForm($loginFailed=false) { private function loginForm($loginFailed=false) {
$err = ""; $err = "";
if( $loginFailed ) if( $loginFailed )
$err = '<div class="alert alert-danger">Login failed.</div>'; $err = '<div class="alert alert-danger">'.$this->l['login_failed'].'</div>';
$this->getHTMLHeader(); $this->getHTMLHeader();
$html = str_replace( "{{error}}", $err, $this->templates['login'] ); $html = str_replace( "{{error}}", $err, $this->templates['login'] );
$html = str_replace( "{{i18n.username}}", $this->i18n[$this->config['language']]['username'], $html ); $html = str_replace( "{{i18n.username}}", $this->l['username'], $html );
$html = str_replace( "{{i18n.password}}", $this->i18n[$this->config['language']]['password'], $html ); $html = str_replace( "{{i18n.password}}", $this->l['password'], $html );
$html = str_replace( "{{i18n.login}}", $this->i18n[$this->config['language']]['login'], $html ); $html = str_replace( "{{i18n.login}}", $this->l['login'], $html );
print $html; print $html;
$this->getHTMLFooter(); $this->getHTMLFooter();
} }

View File

@@ -1,6 +1,13 @@
body { body {
padding-top: 70px; padding-top: 70px;
overflow-y: scroll; overflow-y: scroll !important;
}
/*
* This prevents the content from moving when opening a modal
*/
.modal-open {
padding-right: 0 !important;
} }
.icon { .icon {
@@ -27,7 +34,7 @@ img.imgpreview { max-width: 100%; }
div#content { width: 100%; height: 350px; } div#content { width: 100%; height: 350px; }
input[name=newperms] { width: 7em; } input[name=newpermissions] { padding: 6px 8px; }
#filetable tr th.buttons { min-width: 95px; } #filetable tr th.buttons { min-width: 95px; }
#filetable tbody tr.highlightedItem { box-shadow: 0px 0px 10px 2px #337ab7; } #filetable tbody tr.highlightedItem { box-shadow: 0px 0px 10px 2px #337ab7; }
@@ -76,17 +83,19 @@ footer {
width: 100%; width: 100%;
height: 100%; height: 100%;
text-align: center; text-align: center;
background-color: #FFF; color: #FFF;
filter: alpha(opacity=50); background-color: lightblue;
-moz-opacity: 0.5; filter: alpha(opacity=70);
opacity: 0.5; -moz-opacity: 0.7;
opacity: 0.7;
} }
#filedropoverlay div { #filedropoverlay div {
border-radius: 5px; border-radius: 5px;
color: #000; color: #000;
background-color: #fff;
position:relative; position:relative;
top:50%; top:50%;
font-size: 6em; font-size: 6em;
} }
.td-permissions { width: 1px; }

View File

@@ -1,5 +1,5 @@
{{#items}} {{#items}}
<tr class="clickable-row {{rowclasses}}" data-filename="{{name}}" data-eaction="{{eaction}}"> <tr class="clickable-row {{rowclasses}}" {{{dragdrop}}} data-id="{{guid}}" data-filename="{{name}}" data-eaction="{{eaction}}">
<td> <td>
<a {{{href}}} tabindex="0" id="{{guid}}" class="ifmitem" {{{tooltip}}} data-type="{{type}}"> <a {{{href}}} tabindex="0" id="{{guid}}" class="ifmitem" {{{tooltip}}} data-type="{{type}}">
<span class="{{icon}}"></span> <span class="{{icon}}"></span>
@@ -25,8 +25,8 @@
<td>{{size}}</td> <td>{{size}}</td>
{{/config.showfilesize}} {{/config.showfilesize}}
{{#config.showpermissions}} {{#config.showpermissions}}
<td class="hidden-xs"> <td class="hidden-xs td-permissions">
<input type="text" name="newpermissions" class="form-control {{filepermmode}}" value="{{fileperms}}" data-filename="{{name}}" {{readonly}}> <input type="text" size="11" name="newpermissions" class="form-control {{filepermmode}}" value="{{fileperms}}" data-filename="{{name}}" {{readonly}}>
</td> </td>
{{/config.showpermissions}} {{/config.showpermissions}}
{{#config.showowner}} {{#config.showowner}}

View File

@@ -0,0 +1,12 @@
<form id="formCreateArchive">
<div class="modal-body">
<fieldset>
<label>{{i18n.archivename}}:</label>
<input class="form-control" type="text" name="archivename" value="" />
</fieldset>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" id="buttonSave">{{i18n.save}}</button>
<button type="button" class="btn btn-default" id="buttonCancel">{{i18n.cancel}}</button>
</div>
</form>

View File

@@ -6,7 +6,7 @@
</fieldset> </fieldset>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button type="button" class="btn btn-default" id="buttonRename">{{i18n.rename_filename}}</button> <button type="button" class="btn btn-default" id="buttonRename">{{i18n.file_rename}}</button>
<button type="button" class="btn btn-default" id="buttonCancel">{{i18n.cancel}} </button> <button type="button" class="btn btn-default" id="buttonCancel">{{i18n.cancel}} </button>
</div> </div>
</form> </form>

View File

@@ -2,7 +2,7 @@
<div class="modal-body"> <div class="modal-body">
<fieldset> <fieldset>
<label>{{i18n.search_pattern}}:</label> <label>{{i18n.search_pattern}}:</label>
<input type="text" class="form-control" id="searchPattern" name="pattern" value="{{lastSearch}}"><br> <input type="text" class="form-control" id="searchPattern" name="pattern" autocomplete="off" value="{{lastSearch}}"><br>
<table id="searchResults" class="table"> <table id="searchResults" class="table">
</table> </table>
</fieldset> </fieldset>