1
0
mirror of https://github.com/misterunknown/ifm.git synced 2025-09-01 11:42:32 +02:00

new development version 2.2-dev

This commit is contained in:
Marco Dickert
2017-02-14 20:10:25 +01:00
parent f423253b85
commit 6892595c82
13 changed files with 1488 additions and 1262 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
.*.swp
*.zip

595
ifm.php

File diff suppressed because one or more lines are too long

14
src/ace/ace.js Normal file

File diff suppressed because one or more lines are too long

1
src/bootstrap-notify.min.js vendored Normal file

File diff suppressed because one or more lines are too long

6
src/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
src/bootstrap.min.js vendored Normal file

File diff suppressed because one or more lines are too long

2
src/ekko-lightbox.min.css vendored Normal file
View File

@@ -0,0 +1,2 @@
.ekko-lightbox-nav-overlay a:focus,.ekko-lightbox-nav-overlay a>:focus{outline:0}.ekko-lightbox-container{position:relative}.ekko-lightbox-container>div.ekko-lightbox-item{position:absolute;top:0;left:0;width:100%;transition:opacity .5s ease-in-out;opacity:1}.ekko-lightbox-nav-overlay{z-index:1;position:absolute;top:0;left:0;width:100%;height:100%;display:-ms-flexbox;display:flex}.ekko-lightbox-nav-overlay a{-ms-flex:1;flex:1;display:-ms-flexbox;display:flex;-ms-flex-align:center;align-items:center;opacity:0;transition:opacity .5s;color:#fff;font-size:30px;z-index:1}.ekko-lightbox-nav-overlay a>*{-ms-flex-positive:1;flex-grow:1}.ekko-lightbox-nav-overlay a span{padding:0 30px}.ekko-lightbox-nav-overlay a:last-child span{text-align:right}.ekko-lightbox-nav-overlay a:hover{text-decoration:none}.ekko-lightbox a:hover{opacity:1;text-decoration:none}.ekko-lightbox .modal-footer{text-align:left}.ekko-lightbox-loader{position:absolute;top:0;left:0;bottom:0;right:0;width:100%;display:-ms-flexbox;display:flex;-ms-flex-direction:column;flex-direction:column;-ms-flex-pack:center;justify-content:center;-ms-flex-align:center;align-items:center}.ekko-lightbox-loader>div{width:40px;height:40px;position:relative;text-align:center}.ekko-lightbox-loader>div>div{width:100%;height:100%;border-radius:50%;background-color:#fff;opacity:.6;position:absolute;top:0;left:0;animation:a 2s infinite ease-in-out}.ekko-lightbox-loader>div>div:last-child{animation-delay:-1s}@keyframes a{0%,to{transform:scale(0);-webkit-transform:scale(0)}50%{transform:scale(1);-webkit-transform:scale(1)}}
/*# sourceMappingURL=ekko-lightbox.min.css.map */

2
src/ekko-lightbox.min.js vendored Normal file

File diff suppressed because one or more lines are too long

106
src/fontello-embedded.css vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -1,15 +1,44 @@
// declare ifm object // IFM - js app
if(!ifm) {
var ifm = { function IFM() {
IFM_SCFN: "<?=basename($_SERVER['SCRIPT_NAME'])?>", // IFM_SCFM = ifm script file name; used for querying via AJAX var self = this; // reference to ourself, because "this" does not work within callbacks
config: jQuery.parseJSON('<?php echo json_encode(IFMConfig::getConstants()); ?>'), // serialize the PHP config array, so we can use it in JS too
editor: null, // global ace editor this.IFM_SCFN = "<?=basename($_SERVER['SCRIPT_NAME'])?>";
fileChanged: false, // was our file edited? this.config = jQuery.parseJSON('<?php echo json_encode(IFMConfig::getConstants()); ?>'); // serialize the PHP config array, so we can use it in JS too
currentDir: "", // this is the global variable for the current directory; it is used for AJAX requests this.editor = null; // global ace editor
// -------------- this.fileChanged = false; // flag for check if file was changed already
// main functions this.currentDir = ""; // this is the global variable for the current directory; it is used for AJAX requests
// -------------- this.loadingAnim = '<div id="loadingAnim"><div class="blockG" id="rotateG_01"></div><div class="blockG" id="rotateG_02"></div><div class="blockG" id="rotateG_03"></div><div class="blockG" id="rotateG_04"></div><div class="blockG" id="rotateG_05"></div><div class="blockG" id="rotateG_06"></div><div class="blockG" id="rotateG_07"></div><div class="blockG" id="rotateG_08"></div></div>';
refreshFileTable: function () {
// modal functions
this.showModal = function( content, options = {} ) {
var modal = $( document.createElement( 'div' ) )
.addClass( "modal fade" )
.attr( 'id', 'ifmmodal' )
.attr( 'role', 'dialog' );
var modalDialog = $( document.createElement( 'div' ) )
.addClass( "modal-dialog" )
.attr( 'role', 'document' );
if( options.large == true ) modalDialog.addClass( 'modal-lg' );
var modalContent = $(document.createElement('div'))
.addClass("modal-content")
.append( content );
modalDialog.append( modalContent );
modal.append( modalDialog );
$( document.body ).prepend( modal );
modal.modal();
modal.on( 'hide.bs.modal', function () {
self.fileChanged = false;
self.editor = null;
$( this ).remove();
});
};
this.hideModal = function() {
$('#ifmmodal').modal('hide');
};
this.refreshFileTable = function () {
if(document.getElementById("multiseloptions"))$("#multiseloptions").remove(); if(document.getElementById("multiseloptions"))$("#multiseloptions").remove();
var id=ifm.generateGuid(); var id=ifm.generateGuid();
ifm.task_add("Refresh", id); ifm.task_add("Refresh", id);
@@ -18,13 +47,18 @@ if(!ifm) {
type: "POST", type: "POST",
data: "api=getFiles&dir="+ifm.currentDir, data: "api=getFiles&dir="+ifm.currentDir,
dataType: "json", dataType: "json",
success: success: self.rebuildFileTable,
function(data) { error: function(response) { ifm.showMessage("General error occured: No or broken response", "e"); },
complete: function() { self.task_done( id ); }
});
};
this.rebuildFileTable = function( data ) {
$("#filetable tbody tr").remove(); $("#filetable tbody tr").remove();
for(i=0;i<data.length;i++) { for(i=0;i<data.length;i++) {
var newrow = "<tr>"; var newrow = "<tr>";
var multisel = ''; var multisel = '';
if(ifm.config.multiselect == 1) { if(self.config.multiselect == 1) {
multisel = '<input type="checkbox" '; multisel = '<input type="checkbox" ';
multisel += (!ifm.inArray(data[i].name, ["..", "."]))?'id="'+data[i].name+'" name="multisel"':'style="visibility:hidden"'; multisel += (!ifm.inArray(data[i].name, ["..", "."]))?'id="'+data[i].name+'" name="multisel"':'style="visibility:hidden"';
multisel += '>'; multisel += '>';
@@ -33,7 +67,7 @@ if(!ifm) {
newrow += '<td>'+multisel+'<a href="'+ifm.pathCombine(ifm.currentDir,data[i].name)+'"><span class="'+data[i].icon+'"></span> '+data[i].name+'</a></td>'; newrow += '<td>'+multisel+'<a href="'+ifm.pathCombine(ifm.currentDir,data[i].name)+'"><span class="'+data[i].icon+'"></span> '+data[i].name+'</a></td>';
else else
newrow += '<td>'+multisel+'<a onclick="ifm.changeDirectory(\''+data[i].name+'\')"><span class="'+data[i].icon+'"></span> '+data[i].name+'</a></td>' newrow += '<td>'+multisel+'<a onclick="ifm.changeDirectory(\''+data[i].name+'\')"><span class="'+data[i].icon+'"></span> '+data[i].name+'</a></td>'
if(ifm.config.download == 1) { if(self.config.download == 1) {
if( data[i].type != "dir" ) if( data[i].type != "dir" )
newrow += '<td class="download-link">\ newrow += '<td class="download-link">\
<form style="display:none;" id="fdownload'+i+'" method="post">\ <form style="display:none;" id="fdownload'+i+'" method="post">\
@@ -51,8 +85,8 @@ if(!ifm) {
if(data[i].lastmodified) newrow += '<td>'+data[i].lastmodified+'</td>'; if(data[i].lastmodified) newrow += '<td>'+data[i].lastmodified+'</td>';
if(data[i].filesize) newrow += '<td>'+data[i].filesize+'</td>'; if(data[i].filesize) newrow += '<td>'+data[i].filesize+'</td>';
if(data[i].fileperms) { if(data[i].fileperms) {
newrow += '<td><input type="text" name="newperms" value="'+data[i].fileperms+'"'; newrow += '<td><input type="text" name="newperms" class="form-control" value="'+data[i].fileperms+'"';
if(ifm.config.chmod == 1) if(self.config.chmod == 1)
newrow += ' onkeypress="ifm.changePermissions(event, \''+data[i].name+'\');"'; newrow += ' onkeypress="ifm.changePermissions(event, \''+data[i].name+'\');"';
else else
newrow += " readonly"; newrow += " readonly";
@@ -61,11 +95,11 @@ if(!ifm) {
} }
if(data[i].owner) newrow += '<td>'+data[i].owner+'</td>'; if(data[i].owner) newrow += '<td>'+data[i].owner+'</td>';
if(data[i].group) newrow += '<td>'+data[i].group+'</td>'; if(data[i].group) newrow += '<td>'+data[i].group+'</td>';
if(ifm.inArray(1,[ifm.config.edit, ifm.config.rename, ifm.config.delete, ifm.config.zipnload, ifm.config.extract])) { if(ifm.inArray(1,[self.config.edit, self.config.rename, self.config.delete, self.config.zipnload, self.config.extract])) {
newrow += '<td>'; newrow += '<td>';
if(data[i].type == "dir") { if(data[i].type == "dir") {
if( data[i].name == ".." ) data[i].name = "."; if( data[i].name == ".." ) data[i].name = ".";
if(ifm.config.zipnload == 1) { if(self.config.zipnload == 1) {
newrow += '<form method="post" style="display:inline-block;padding:0;margin:0;border:0;">\ newrow += '<form method="post" style="display:inline-block;padding:0;margin:0;border:0;">\
<fieldset style="display:inline-block;padding:0;margin:0;border:0;">\ <fieldset style="display:inline-block;padding:0;margin:0;border:0;">\
<input type="hidden" name="dir" value="'+ifm.currentDir+'">\ <input type="hidden" name="dir" value="'+ifm.currentDir+'">\
@@ -79,233 +113,218 @@ if(!ifm) {
} }
} }
else if(data[i].name.toLowerCase().substr(-4) == ".zip") { else if(data[i].name.toLowerCase().substr(-4) == ".zip") {
if(ifm.config.extract == 1) newrow += '<a href="" onclick="ifm.extractFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-archive" title="extract"></span></a>'; if(self.config.extract == 1) newrow += '<a href="" onclick="ifm.extractFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-archive" title="extract"></span></a>';
} }
else { else {
if(ifm.config.edit == 1) newrow += '<a onclick="ifm.showLoading();ifm.editFile(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-pencil" title="edit"></span></a>'; if(self.config.edit == 1) newrow += '<a onclick="ifm.showLoading();ifm.editFile(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-pencil" title="edit"></span></a>';
} }
if(data[i].name != ".." && data[i].name != ".") { if(data[i].name != ".." && data[i].name != ".") {
if(ifm.config.rename == 1) newrow += '<a onclick="ifm.renameFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-terminal" title="rename"></span></a>'; if(self.config.rename == 1) newrow += '<a onclick="ifm.renameFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-terminal" title="rename"></span></a>';
if(ifm.config.delete == 1) newrow += '<a onclick="ifm.deleteFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-trash" title="delete"></span></a>'; if(self.config.delete == 1) newrow += '<a onclick="ifm.deleteFileDialog(\''+ifm.JSEncode(data[i].name)+'\');return false;"><span class="icon icon-trash" title="delete"></span></a>';
} }
newrow += '</td></tr>'; newrow += '</td></tr>';
} }
$("#filetable tbody").append(newrow); $("#filetable tbody").append(newrow);
} }
// bind multiselect handler // bind multiselect handler
if(ifm.config.multiselect == 1) { if(self.config.multiselect == 1) {
$("input[name=multisel]").on("change", function(){ ifm.handleMultiSelect(); }); $("input[name=multisel]").on("change", function(){ ifm.handleMultiSelect(); });
} }
// bind Fancybox // todo: bootstrap-fancybox for images
//var piclinks = $('a[href$=".bmp"],a[href$=".gif"],a[href$=".jpg"],a[href$=".jpeg"],a[href$=".png"],a[href$=".BMP"],a[href$=".GIF"],a[href$=".JPG"],a[href$=".JPEG"],a[href$=".PNG"]'); };
//piclinks.attr('rel', 'fancybox').fancybox();
//var xOffset = 10; this.changeDirectory = function( newdir ) {
//var yOffset = 30;
//piclinks.hover(function(e){this.t = this.title;this.title = "";var c = (this.t != "") ? "<br/>" + this.t : "";$("body").append("<p id='mdPicPreview'><img src='"+ this.href +"' alt='Image preview' />"+ c +"</p>");$("#mdPicPreview").css("top",(e.pageY - xOffset) + "px").css("left",(e.pageX + yOffset) + "px").fadeIn("fast");},function(){this.title = this.t;$("#mdPicPreview").remove();});
//piclinks.mousemove(function(e){$("#mdPicPreview").css("top",(e.pageY - xOffset) + "px").css("left",(e.pageX + yOffset) + "px");});
},
error: function(response) { ifm.showMessage("General error occured: No or broken response", "e"); },
complete: function() { ifm.task_done(id); }
});
},
changeDirectory: function(newdir) {
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: self.IFM_SCFN,
type: "POST", type: "POST",
data: ({ data: ({
api: "getRealpath", api: "getRealpath",
dir: ifm.pathCombine(ifm.currentDir, newdir) dir: self.pathCombine( ifm.currentDir, newdir )
}), }),
dataType: "json", dataType: "json",
success: function(data){ success: function( data ){
ifm.currentDir = data.realpath; self.currentDir = data.realpath;
ifm.refreshFileTable(); self.refreshFileTable();
$("#currentDir").val(ifm.currentDir); $( "#currentDir" ).val( self.currentDir );
}, },
error: function() { ifm.showMessage("General error occured: No or broken response", "e"); } error: function() { self.showMessage( "General error occured: No or broken response", "e" ); }
}); });
}, };
showFileForm: function () {
this.showFileForm = function () {
var filename = arguments.length > 0 ? arguments[0] : "newfile.txt"; var filename = arguments.length > 0 ? arguments[0] : "newfile.txt";
var content = arguments.length > 1 ? arguments[1] : ""; var content = arguments.length > 1 ? arguments[1] : "";
var overlay = '<div class="modal fade" id="overlay" role="dialog" aria-labelledby="fileformLabel"><div class="modal-dialog" role="document"><div class="modal-content">'; var overlay = '<form id="showFile">';
overlay += '<form id="showFile"><div class="modal-header"><h4>' + ((arguments.length > 0)?'edit':'add') + ' file</h4></div>'; overlay += '<div class="modal-body"><fieldset><label>Filename:</label><input type="text" class="form-control" name="filename" value="'+filename+'" /><br>';
overlay += '<div class="modal-body"><fieldset><label>Filename:</label><input type="text" class="form-control" name="filename" value="'+filename+'" />'; overlay += '<div id="content" name="content"></div></fieldset></div><div class="modal-footer"><button type="button" class="btn btn-default" onclick="ifm.saveFile();ifm.hideModal();return false;">Save';
overlay += '<div id="content" name="content">'+content+'</div></fieldset></div><div class="modal-footer"><button class="btn btn-success" onclick="ifm.saveFile();ifm.closeFileForm();return false;">Save'; overlay += '</button><button type="button" onclick="ifm.saveFile();return false;" class="btn btn-default">Save without closing</button>';
overlay += '</button><button onclick="ifm.saveFile();return false;" class="btn btn-default">Save without closing</button>'; overlay += '<button type="button" class="btn btn-default" onclick="ifm.hideModal();return false;">Close</button></div></form>';
overlay += '<button class="btn btn-danger" onclick="$(\'#overlay\').modal(\'hide\');return false;">Close</button></div></form></div></div></div>'; self.showModal( overlay, { large: true } );
$(document.body).prepend(overlay); $('#ifmmodal').on('remove', function () { self.editor = null; self.fileChanged = false; });
if(filename=="")$("#showFile input[name=filename]").focus();
else $("#showFile #content").focus();
$('#overlay').modal();
$("#overlay").on('hide.bs.modal', function () {
$(this).remove();
});
$('#overlay').on('remove', function () { ifm.editor = null; ifm.fileChanged = false; });
// Start ACE // Start ACE
//ifm.editor = ace.edit("content"); self.editor = ace.edit("content");
//ifm.editor.getSession().setValue(content); self.editor.$blockScrolling = 'Infinity';
//ifm.editor.focus(); self.editor.getSession().setValue(content);
//ifm.editor.on("change", function() { ifm.fileChanged = true; }); self.editor.focus();
}, self.editor.on("change", function() { self.fileChanged = true; });
closeFileForm: function() { };
ifm.fileChanged = false;
ifm.editor = null; this.createDirForm = function() {
ifm.hideSaveQuestion(); self.showModal( '<form id="createDir">\
ifm.removeOverlay(); <div class="modal-body">\
},
removeOverlay: function() {
$('#overlay').remove();
},
createDirForm: function() {
$(document.body).prepend('<div class="overlay">\
<form id="createDir">\
<fieldset>\ <fieldset>\
<label>Directoy name:</label>\ <label>Directoy name:</label>\
<input type="text" name="dirname" value="" />\ <input class="form-control" type="text" name="dirname" value="" />\
<button onclick="ifm.createDir();$(\'.overlay\').remove();return false;">Save</button><button onclick="$(\'.overlay\').remove();return false;">Cancel</button>\
</fieldset>\ </fieldset>\
</form>\ </div>\
</div>'); <div class="modal-footer">\
}, <button class="btn btn-default" type="button" onclick="ifm.createDir();ifm.hideModal();return false;">Save</button>\
ajaxRequestDialog: function() { <button type="button" class="btn btn-default" onclick="ifm.hideModal();return false;">Cancel</button>\
$(document.body).prepend('<div class="overlay">\ </div>\
<form id="ajaxrequest">\ </form>' );
};
this.ajaxRequestDialog = function() {
self.showModal( '<form id="ajaxrequest">\
<div class="modal-body">\
<fieldset>\ <fieldset>\
<label>URL</label><br>\ <label>URL</label><br>\
<input type="text" id="ajaxurl" required><br>\ <input class="form-control" type="text" id="ajaxurl" required><br>\
<label>Data</label><br>\ <label>Data</label><br>\
<textarea id="ajaxdata"></textarea><br>\ <textarea class="form-control" id="ajaxdata"></textarea><br>\
<label>Method</label><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>\ <input type="radio" name="arMethod" value="GET">GET</input><input type="radio" name="arMethod" value="POST" checked="checked">POST</input><br>\
<button onclick="ifm.ajaxRequest();return false;">Request</button>\ <button type="button" class="btn btn-success" onclick="ifm.ajaxRequest();return false;">Request</button>\
<button onclick="$(\'.overlay\').remove();return false;">Close</button><br>\ <button type="button" class="btn btn-default" onclick="ifm.hideModal();return false;">Close</button><br>\
<label>Response</label><br>\ <label>Response</label><br>\
<textarea id="ajaxresponse"></textarea>\ <textarea class="form-control" id="ajaxresponse"></textarea>\
</fieldset>\ </fieldset>\
</form>\ </form>\
</div>'); </div>');
}, };
ajaxRequest: function() {
ifm.showLoading(); this.ajaxRequest = function() {
$.ajax({ $.ajax({
url : $("#ajaxurl").val(), url : $("#ajaxurl").val(),
cache : false, cache : false,
data : $('#ajaxdata').val().replace(/\n/g,"&"), data : $('#ajaxdata').val().replace(/\n/g,"&"),
type : $('#ajaxrequest input[name=arMethod]:checked').val(), type : $('#ajaxrequest input[name=arMethod]:checked').val(),
success : function(response) { $("#ajaxresponse").text(response); }, success : function(response) { $("#ajaxresponse").text(response); },
error : function(e) { ifm.showMessage("Error: "+e, "e"); console.log(e); }, error : function(e) { self.showMessage("Error: "+e, "e"); console.log(e); }
complete: function() { ifm.hideLoading(); }
}); });
}, };
saveFile: function() {
var _content = ifm.editor.getValue(); this.saveFile = function() {
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: self.IFM_SCFN,
type: "POST", type: "POST",
data: ({ data: ({
api: "saveFile", api: "saveFile",
dir: ifm.currentDir, dir: self.currentDir,
filename: $("#showFile input[name^=filename]").val(), filename: $("#showFile input[name^=filename]").val(),
content: _content content: ifm.editor.getValue()
}), }),
dataType: "json", dataType: "json",
success: function(data) { success: function( data ) {
if(data.status == "OK") { if( data.status == "OK" ) {
ifm.showMessage("File successfully edited/created.", "s"); self.showMessage( "File successfully edited/created.", "s" );
ifm.refreshFileTable(); self.refreshFileTable();
} else ifm.showMessage("File could not be edited/created:"+data.message, "e"); } else self.showMessage( "File could not be edited/created:" + data.message, "e" );
}, },
error: function() { ifm.showMessage("General error occured", "e"); } error: function() { self.showMessage( "General error occured", "e" ); }
}); });
ifm.fileChanged = false; self.fileChanged = false;
}, };
editFile: function(name) {
this.editFile = function( name ) {
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: self.IFM_SCFN,
type: "POST", type: "POST",
dataType: "json", dataType: "json",
data: ({ data: ({
api: "getContent", api: "getContent",
dir: ifm.currentDir, dir: self.currentDir,
filename: name filename: name
}), }),
success: function(data) { success: function( data ) {
if(data.status == "OK" && data.data.content != null) { if( data.status == "OK" && data.data.content != null ) {
ifm.showFileForm(data.data.filename, data.data.content); self.showFileForm( data.data.filename, data.data.content );
} }
else if(data.status == "OK" && data.data.content == null) { else if( data.status == "OK" && data.data.content == null ) {
ifm.showMessage("The content of this file cannot be fetched.", "e"); self.showMessage( "The content of this file cannot be fetched.", "e" );
} }
else ifm.showMessage("Error: "+data.message, "e"); else self.showMessage( "Error: "+data.message, "e" );
}, },
error: function() { ifm.showMessage("This file can not be displayed or edited.", "e"); }, error: function() { self.showMessage( "This file can not be displayed or edited.", "e" ); },
complete: function() { ifm.hideLoading(); } complete: function() { self.hideLoading(); }
}); });
}, };
deleteFileDialog: function(name) {
$(document.body).prepend('<div class="overlay">\ this.deleteFileDialog = function( name ) {
<form id="deleteFile">\ self.showModal( '<form id="deleteFile">\
<fieldset>\ <div class="modal-body">\
<label>Do you really want to delete the file '+name+'?\ <label>Do you really want to delete the file '+name+'?\
<button onclick="ifm.deleteFile(\''+ifm.JSEncode(name)+'\');$(\'.overlay\').remove();return false;">Yes</button><button onclick="$(\'.overlay\').remove();return false;">No</button>\ </div><div class="modal-footer">\
</fieldset>\ <button type="button" class="btn btn-danger" onclick="ifm.deleteFile(\''+ifm.JSEncode(name)+'\');ifm.hideModal();return false;">Yes</button><button type="button" class="btn btn-default" onclick="ifm.hideModal();return false;">No</button>\
</form>\ </div>\
</div>'); </form>' );
}, };
deleteFile: function(name) { this.deleteFile = function( name ) {
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: self.IFM_SCFN,
type: "POST", type: "POST",
data: ({ data: ({
api: "deleteFile", api: "deleteFile",
dir: ifm.currentDir, dir: self.currentDir,
filename: name filename: name
}), }),
dataType: "json", dataType: "json",
success: function(data) { success: function(data) {
if(data.status == "OK") { if(data.status == "OK") {
ifm.showMessage("File successfully deleted", "s"); self.showMessage("File successfully deleted", "s");
ifm.refreshFileTable(); self.refreshFileTable();
} else ifm.showMessage("File could not be deleted", "e"); } else self.showMessage("File could not be deleted", "e");
}, },
error: function() { ifm.showMessage("General error occured", "e"); } error: function() { self.showMessage("General error occured", "e"); }
}); });
}, };
createDir: function() {
this.createDir = function() {
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: self.IFM_SCFN,
type: "POST", type: "POST",
data: ({ data: ({
api: "createDir", api: "createDir",
dir: ifm.currentDir, dir: self.currentDir,
dirname: $("#createDir input[name^=dirname]").val() dirname: $("#createDir input[name^=dirname]").val()
}), }),
dataType: "json", dataType: "json",
success: function(data){ success: function(data){
if(data.status == "OK") { if(data.status == "OK") {
ifm.showMessage("Directory sucessfully created.", "s"); self.showMessage("Directory sucessfully created.", "s");
ifm.refreshFileTable(); self.refreshFileTable();
} }
else { else {
ifm.showMessage("Directory could not be created: "+data.message, "e"); self.showMessage("Directory could not be created: "+data.message, "e");
} }
}, },
error: function() { ifm.showMessage("General error occured.", "e"); } error: function() { self.showMessage("General error occured.", "e"); }
}); });
}, };
renameFileDialog: function(name) {
$(document.body).prepend('<div class="overlay">\ this.renameFileDialog = function(name) {
self.showModal( '<div class="modal-body">\
<form id="renameFile">\ <form id="renameFile">\
<fieldset>\ <fieldset>\
<label>Rename '+name+' to:</label>\ <label>Rename '+name+' to:</label>\
<input type="text" name="newname" />\ <input class="form-control" type="text" name="newname" /><br>\
<button onclick="ifm.renameFile(\''+ifm.JSEncode(name)+'\');$(\'.overlay\').remove();return false;">Rename</button><button onclick="$(\'.overlay\').remove();return false;">Cancel</button>\ <button class="btn btn-default" onclick="ifm.renameFile(\''+ifm.JSEncode(name)+'\');ifm.hideModal();return false;">Rename</button><button class="btn btn-default" onclick="ifm.hideModal();return false;">Cancel</button>\
</fieldset>\ </fieldset>\
</form>\ </form>\
</div>'); </div>' );
}, };
renameFile: function(name) {
this.renameFile = function(name) {
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: ifm.IFM_SCFN,
type: "POST", type: "POST",
@@ -324,69 +343,74 @@ if(!ifm) {
}, },
error: function() { ifm.showMessage("General error occured", "e"); } error: function() { ifm.showMessage("General error occured", "e"); }
}); });
}, };
extractFileDialog: function(name) {
this.extractFileDialog = function(name) {
var fuckWorkarounds=""; var fuckWorkarounds="";
if(fuckWorkarounds.lastIndexOf(".") > 1) if(fuckWorkarounds.lastIndexOf(".") > 1)
fuckWorkarounds = name.substr(0,name.length-4); fuckWorkarounds = name.substr(0,name.length-4);
else fuckWorkarounds = name; else fuckWorkarounds = name;
$(document.body).prepend('<div class="overlay">\ self.showModal( '<div class="modal-body">\
<form id="extractFile">\ <form id="extractFile">\
<fieldset>\ <fieldset>\
<label>Extract '+name+' to:</label>\ <label>Extract '+name+' to:</label>\
<button onclick="ifm.extractFile(\''+ifm.JSEncode(name)+'\', 0);$(\'.overlay\').remove();return false;">here</button>\ <button type="button" class="btn btn-default" onclick="ifm.extractFile(\''+ifm.JSEncode(name)+'\', 0);ifm.hideModal();return false;">here</button>\
<button onclick="ifm.extractFile(\''+ifm.JSEncode(name)+'\', 1);$(\'.overlay\').remove();return false;">'+fuckWorkarounds+'/</button>\ <button type="button" class="btn btn-default" onclick="ifm.extractFile(\''+ifm.JSEncode(name)+'\', 1);ifm.hideModal();return false;">'+fuckWorkarounds+'/</button>\
<button onclick="$(\'.overlay\').remove();return false;">Cancel</button>\ <button type="button" class="btn btn-default" onclick="ifm.hideModal();return false;">Cancel</button>\
</fieldset>\ </fieldset>\
</form>\ </form>\
</div>'); </div>');
}, };
extractFile: function(name, t) {
this.extractFile = function(name, t) {
var td = (t == 1)? name.substr(0,name.length-4) : ""; var td = (t == 1)? name.substr(0,name.length-4) : "";
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: self.IFM_SCFN,
type: "POST", type: "POST",
data: ({ data: ({
api: "extractFile", api: "extractFile",
dir: ifm.currentDir, dir: self.currentDir,
filename: name, filename: name,
targetdir: td targetdir: td
}), }),
dataType: "json", dataType: "json",
success: function(data) { success: function(data) {
if(data.status == "OK") { if(data.status == "OK") {
ifm.showMessage("File successfully extracted", "s"); self.showMessage("File successfully extracted", "s");
ifm.refreshFileTable(); self.refreshFileTable();
} else ifm.showMessage("File could not be extracted. Error: "+data.message, "e"); } else self.showMessage("File could not be extracted. Error: "+data.message, "e");
}, },
error: function() { ifm.showMessage("General error occured", "e"); } error: function() { self.showMessage("General error occured", "e"); }
}); });
}, };
uploadFileDialog: function() {
$(document.body).prepend('<div class="overlay">\ this.uploadFileDialog = function() {
<form id="uploadFile">\ self.showModal( '<form id="uploadFile">\
<div class="modal-body">\
<fieldset>\ <fieldset>\
<label>Upload file</label><br>\ <label>Upload file</label><br>\
<input type="file" name="ufile" id="ufile"><br>\ <input class="file" type="file" name="ufile" id="ufile"><br>\
<label>new filename</label>\ <label>new filename</label>\
<input type="text" name="newfilename"><br>\ <input class="form-control" type="text" name="newfilename"><br>\
<button onclick="ifm.uploadFile();$(\'.overlay\').remove();return false;">Upload</button>\
<button onclick="$(\'.overlay\').remove();return false;">Cancel</button>\
</fieldset>\ </fieldset>\
</form>\ </div><div class="modal-footer">\
</div>'); <button class="btn btn-default" onclick="ifm.uploadFile();ifm.hideModal();return false;">Upload</button>\
}, <button class="btn btn-default" onclick="ifm.hideModal();return false;">Cancel</button>\
uploadFile: function() { </div>\
</form>');
};
this.uploadFile = function() {
var ufile = document.getElementById('ufile').files[0]; var ufile = document.getElementById('ufile').files[0];
var data = new FormData(); var data = new FormData();
var newfilename = $("#uploadFile input[name^=newfilename]").val(); var newfilename = $("#uploadFile input[name^=newfilename]").val();
data.append('api', 'uploadFile'); data.append('api', 'uploadFile');
data.append('dir', ifm.currentDir); data.append('dir', self.currentDir);
data.append('file', ufile); data.append('file', ufile);
data.append('newfilename', newfilename); data.append('newfilename', newfilename);
var id = ifm.generateGuid(); var id = self.generateGuid();
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: self.IFM_SCFN,
type: "POST", type: "POST",
data: data, data: data,
processData: false, processData: false,
@@ -394,60 +418,62 @@ if(!ifm) {
dataType: "json", dataType: "json",
xhr: function(){ xhr: function(){
var xhr = $.ajaxSettings.xhr() ; var xhr = $.ajaxSettings.xhr() ;
xhr.upload.onprogress = function(evt){ ifm.task_update(evt.loaded/evt.total*100,id); } ; xhr.upload.onprogress = function(evt){ self.task_update(evt.loaded/evt.total*100,id); } ;
xhr.upload.onload = function(){ console.log('Uploading '+newfilename+' done.') } ; xhr.upload.onload = function(){ console.log('Uploading '+newfilename+' done.') } ;
return xhr ; return xhr ;
}, },
success: function(data) { success: function(data) {
if(data.status == "OK") { if(data.status == "OK") {
ifm.showMessage("File successfully uploaded", "s"); self.showMessage("File successfully uploaded", "s");
if(data.cd == ifm.currentDir) ifm.refreshFileTable(); if(data.cd == self.currentDir) self.refreshFileTable();
} else ifm.showMessage("File could not be uploaded: "+data.message, "e"); } else self.showMessage("File could not be uploaded: "+data.message, "e");
}, },
error: function() { ifm.showMessage("General error occured", "e"); }, error: function() { self.showMessage("General error occured", "e"); },
complete: function() { ifm.task_done(id); } complete: function() { self.task_done(id); }
}); });
ifm.task_add("Upload "+ufile.name, id); self.task_add("Upload "+ufile.name, id);
}, };
changePermissions: function(e, name) {
this.changePermissions = function(e, name) {
if(e.keyCode == '13') if(e.keyCode == '13')
$.ajax({ $.ajax({
url: ifm.IFM_SCFN, url: self.IFM_SCFN,
type: "POST", type: "POST",
data: ({ data: ({
api: "changePermissions", api: "changePermissions",
dir: ifm.currentDir, dir: self.currentDir,
filename: name, filename: name,
chmod: e.target.value chmod: e.target.value
}), }),
dataType: "json", dataType: "json",
success: function(data){ success: function(data){
if(data.status == "OK") { if(data.status == "OK") {
ifm.showMessage("Permissions successfully changed.", "s"); self.showMessage("Permissions successfully changed.", "s");
ifm.refreshFileTable(); self.refreshFileTable();
} }
else { else {
ifm.showMessage("Permissions could not be changed: "+data.message, "e"); self.showMessage("Permissions could not be changed: "+data.message, "e");
} }
}, },
error: function() { ifm.showMessage("General error occured.", "e"); } error: function() { self.showMessage("General error occured.", "e"); }
}); });
}, };
remoteUploadDialog: function() {
$(document.body).prepend('<div class="overlay">\ this.remoteUploadDialog = function() {
<form id="uploadFile">\ self.showModal( '<form id="uploadFile">\
<div class="modal-body">\
<fieldset>\ <fieldset>\
<label>Remote upload URL</label><br>\ <label>Remote upload URL</label><br>\
<input type="text" id="url" name="url" required><br>\ <input class="form-control" type="text" id="url" name="url" required><br>\
<label>Filename (required)</label>\ <label>Filename (required)</label>\
<input type="text" id="filename" name="filename" required><br>\ <input class="form-control" type="text" id="filename" name="filename" required><br>\
<label>Method</label>\ <label>Method</label>\
<input type="radio" name="method" value="curl" checked="checked">cURL<input type="radio" name="method" value="file">file</input><br>\ <input type="radio" name="method" value="curl" checked="checked">cURL<input type="radio" name="method" value="file">file</input><br>\
<button onclick="ifm.remoteUpload();$(\'.overlay\').remove();return false;">Upload</button>\ </fieldset><div class="modal-footer">\
<button onclick="$(\'.overlay\').remove();return false;">Cancel</button>\ <button type="button" class="btn btn-default" onclick="ifm.remoteUpload();ifm.hideModal();return false;">Upload</button>\
</fieldset>\ <button type="button" class="btn btn-default" onclick="ifm.hideModal();return false;">Cancel</button>\
</form>\ </div>\
</div>'); </form>' );
// guess the wanted filename, because it is required // guess the wanted filename, because it is required
// e.g http:/example.com/example.txt => filename: example.txt // e.g http:/example.com/example.txt => filename: example.txt
$("#url").on("change keyup", function(){ $("#url").on("change keyup", function(){
@@ -455,8 +481,9 @@ if(!ifm) {
}); });
// if the filename input field was edited manually remove the event handler above // if the filename input field was edited manually remove the event handler above
$("#filename").on("keyup", function() { $("#url").off(); }); $("#filename").on("keyup", function() { $("#url").off(); });
}, };
remoteUpload: function() {
this.remoteUpload = function() {
var filename = $("#filename").val(); var filename = $("#filename").val();
var id = ifm.generateGuid(); var id = ifm.generateGuid();
$.ajax({ $.ajax({
@@ -480,44 +507,52 @@ if(!ifm) {
complete: function() { ifm.task_done(id); } complete: function() { ifm.task_done(id); }
}); });
ifm.task_add("Remote upload: "+filename, id); ifm.task_add("Remote upload: "+filename, id);
}, };
// -------------------- // --------------------
// additional functions // additional functions
// -------------------- // --------------------
showMessage: function(m, t) { this.showMessage = function(m, t) {
var message = '<div id="mess"><div class="'; var msgType = (t == "e")?"danger":(t == "s")?"success":"info";
if(t == "e") message += "message_error"; $.notify(
else if(t == "s") message += "message_successful"; { message: m },
else message += "message"; { type: msgType, delay: 5000, mouse_over: 'pause' }
message += '">'+m+'</div></div>'; );
$(document.body).prepend(message); // var message = '<div id="mess"><div class="';
$("#mess").delay(2000).fadeOut('slow'); // if(t == "e") message += "message_error";
setTimeout(function() { // remove the message from the DOM after 3 seconds // else if(t == "s") message += "message_successful";
$('#mess').remove(); // else message += "message";
}, 3000); // message += '">'+m+'</div></div>';
}, // $(document.body).prepend(message);
showLoading: function() { // $("#mess").delay(2000).fadeOut('slow');
// setTimeout(function() { // remove the message from the DOM after 3 seconds
// $('#mess').remove();
// }, 3000);
};
this.showLoading = function() {
var loading = '<div id="loading">'+ifm.loadingAnim+'</div>'; var loading = '<div id="loading">'+ifm.loadingAnim+'</div>';
if(document.getElementById("loading")==null)$(document.body).prepend(loading); if(document.getElementById("loading")==null)$(document.body).prepend(loading);
}, };
hideLoading: function() { this.hideLoading = function() {
$("#loading").remove(); $("#loading").remove();
}, };
pathCombine: function(a, b) { this.pathCombine = function(a, b) {
if(a == "" && b == "") return ""; if(a == "" && b == "") return "";
if(b[0] == "/") b = b.substring(1); if(b[0] == "/") b = b.substring(1);
if(a == "") return b; if(a == "") return b;
if(a[a.length-1] == "/") a = a.substring(0, a.length-1); if(a[a.length-1] == "/") a = a.substring(0, a.length-1);
if(b == "") return a; if(b == "") return a;
return a+"/"+b; return a+"/"+b;
}, };
showSaveQuestion: function() { this.showSaveQuestion = function() {
var a = '<div id="savequestion"><label>Do you want to save this file?</label><br><button onclick="ifm.saveFile();ifm.closeFileForm(); return false;">Save</button><button onclick="ifm.closeFileForm();return false;">Dismiss</button>'; var a = '<div id="savequestion"><label>Do you want to save this file?</label><br><button onclick="ifm.saveFile();ifm.closeFileForm(); return false;">Save</button><button onclick="ifm.closeFileForm();return false;">Dismiss</button>';
$(document.body).prepend(a); $(document.body).prepend(a);
ifm.bindOverlayClickEvent(); self.bindOverlayClickEvent();
}, };
hideSaveQuestion: function() { $("#savequestion").remove(); }, this.hideSaveQuestion = function() {
handleMultiSelect: function() { $("#savequestion").remove();
};
this.handleMultiSelect = function() {
var amount = $("input[name=multisel]:checked").length; var amount = $("input[name=multisel]:checked").length;
if(amount > 0) { if(amount > 0) {
if(document.getElementById("multiseloptions")===null) { if(document.getElementById("multiseloptions")===null) {
@@ -536,8 +571,8 @@ if(!ifm) {
if(document.getElementById("multiseloptions")!==null) if(document.getElementById("multiseloptions")!==null)
$("#multiseloptions").remove(); $("#multiseloptions").remove();
} }
}, };
multiDelete: function() { this.multiDelete = function() {
var jel = $("input[name=multisel]:checked"); var jel = $("input[name=multisel]:checked");
if(jel.length == 0) { if(jel.length == 0) {
ifm.showMessage("No files chosen"); ifm.showMessage("No files chosen");
@@ -567,27 +602,27 @@ if(!ifm) {
}, },
error: function() { ifm.showMessage("General error occured", "e"); } error: function() { ifm.showMessage("General error occured", "e"); }
}); });
}, };
inArray: function(needle, haystack) { this.inArray = function(needle, haystack) {
for(var i = 0; i < haystack.length; i++) { if(haystack[i] == needle) return true; } return false; for(var i = 0; i < haystack.length; i++) { if(haystack[i] == needle) return true; } return false;
}, };
task_add: function(name,id) { // uFI stands for uploadFileInformation this.task_add = function(name,id) { // uFI stands for uploadFileInformation
if(!document.getElementById("waitqueue")) { if(!document.getElementById("waitqueue")) {
$(document.body).prepend('<div id="waitqueue"></div>'); $(document.body).prepend('<div id="waitqueue"></div>');
//$("#waitqueue").on("mouseover", function() { $(this).toggleClass("left"); }); //$("#waitqueue").on("mouseover", function() { $(this).toggleClass("left"); });
} }
$("#waitqueue").append('<div id="'+id+'" class="progress"><div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemax="100" style="100%"></div>'+name+'</div>'); $("#waitqueue").append('<div id="'+id+'" class="progress"><div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="100" aria-valuemax="100" style="100%"></div>'+name+'</div>');
}, };
task_done: function(id) { this.task_done = function(id) {
$("#"+id).remove(); $("#"+id).remove();
if($("#waitqueue>div").length == 0) { if($("#waitqueue>div").length == 0) {
$("#waitqueue").remove(); $("#waitqueue").remove();
} }
}, };
task_update: function(progress, id) { this.task_update = function(progress, id) {
$('#'+id+' .progress-bar').css('width', progress+'%').attr('aria-valuenow', progress); $('#'+id+' .progress-bar').css('width', progress+'%').attr('aria-valuenow', progress);
}, };
generateGuid: function() { this.generateGuid = function() {
var result, i, j; var result, i, j;
result = ''; result = '';
for(j=0; j<20; j++) { for(j=0; j<20; j++) {
@@ -595,32 +630,29 @@ if(!ifm) {
result = result + i; result = result + i;
} }
return result; return result;
}, };
JSEncode: function(s) { this.JSEncode = function(s) {
return s.replace(/'/g, '\\x27').replace(/"/g, '\\x22'); return s.replace(/'/g, '\\x27').replace(/"/g, '\\x22');
}, };
// static button bindings and filetable initial filling // static button bindings and filetable initial filling
init: function() { this.init = function() {
// fill file table // fill file table
this.refreshFileTable(); this.refreshFileTable();
// bind static buttons // bind static buttons
$("#refresh").click(function(){ $("#refresh").click(function(){
ifm.refreshFileTable(); self.refreshFileTable();
}); });
$("#createFile").click(function(){ $("#createFile").click(function(){
ifm.showFileForm(); self.showFileForm();
}); });
$("#createDir").click(function(){ $("#createDir").click(function(){
ifm.createDirForm(); self.createDirForm();
}); });
$("#upload").click(function(){ $("#upload").click(function(){
ifm.uploadFileDialog(); self.uploadFileDialog();
}); });
}, };
// ---------------
// further members
// ---------------
loadingAnim: '<div id="loadingAnim"><div class="blockG" id="rotateG_01"></div><div class="blockG" id="rotateG_02"></div><div class="blockG" id="rotateG_03"></div><div class="blockG" id="rotateG_04"></div><div class="blockG" id="rotateG_05"></div><div class="blockG" id="rotateG_06"></div><div class="blockG" id="rotateG_07"></div><div class="blockG" id="rotateG_08"></div></div>'
}
} }
$(document).ready(function() {ifm.init()}); // init ifm
var ifm = new IFM();
ifm.init();

4
src/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -11,7 +11,7 @@
*/ */
class IFM { class IFM {
const VERSION = '2.1'; const VERSION = '2.2-dev';
public function __construct() { public function __construct() {
session_start(); session_start();
@@ -70,11 +70,11 @@ class IFM {
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">'; 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; $options = false;
if( IFMConfig::remoteupload == 1 ) { if( IFMConfig::remoteupload == 1 ) {
print '<li><a href="/fatfree/padlock/public/lang/de"><span class="icon icon-upload-cloud"></span> remote upload</a></li>'; print '<li><a onclick="ifm.remoteUploadDialog();return false;"><span class="icon icon-upload-cloud"></span> remote upload</a></li>';
$options = true; $options = true;
} }
if( IFMConfig::ajaxrequest == 1 ) { if( IFMConfig::ajaxrequest == 1 ) {
print '<li><a href="/fatfree/padlock/public/lang/en"><span class="icon icon-link-ext"></span> ajax request</a></li>'; print '<li><a onclick="ifm.ajaxRequestDialog();return false;"><span class="icon icon-link-ext"></span> ajax request</a></li>';
$options = true; $options = true;
} }
if( !$options ) print '<li>No options available</li>'; if( !$options ) print '<li>No options available</li>';
@@ -103,10 +103,11 @@ class IFM {
</table> </table>
</div> </div>
<footer>IFM - improved file manager | ifm.php hidden | <a href="http://github.com/misterunknown/ifm">Visit the project on GitHub</a></footer> <footer>IFM - improved file manager | ifm.php hidden | <a href="http://github.com/misterunknown/ifm">Visit the project on GitHub</a></footer>
<script>';?> @@@src/ace/ace.js@@@ <?php print '</script>
<script>';?> @@@src/jquery.min.js@@@ <?php print '</script> <script>';?> @@@src/jquery.min.js@@@ <?php print '</script>
<script>';?> @@@src/bootstrap.min.js@@@ <?php print '</script> <script>';?> @@@src/bootstrap.min.js@@@ <?php print '</script>
<script>';?> @@@src/bootstrap-notify.min.js@@@ <?php print '</script>
<script>';?> @@@src/ekko-lightbox.min.js@@@ <?php print '</script> <script>';?> @@@src/ekko-lightbox.min.js@@@ <?php print '</script>
<script>';?> @@@src/ace.js@@@ <?php print '</script>
<script>';?> @@@src/ifm.js@@@ <?php print '</script> <script>';?> @@@src/ifm.js@@@ <?php print '</script>
</body> </body>
</html> </html>

View File

@@ -6,8 +6,16 @@ body {
font-size: 14pt; font-size: 14pt;
} }
#filetable tr td:nth-child(5) {
text-align: center;
}
#filetable tr td:nth-child(6) {
text-align: center;
}
#filetable tr td:last-child { #filetable tr td:last-child {
text-align: right; text-align: right;
} }
a { cursor: pointer !important; } a { cursor: pointer !important; }
div#content { width: 100%; height: 350px; }