File manager for Webmin

Currently index.cgi sends multipart/form-data to upload.cgi, that accepts and manages it in one pass of the script. So if we add some more logic to upload.cgi like trying to ask user what to do with this file or that file, it will increase script complexity and will reduce user friendliness. AJAX way will allow to do two way communication between currently open page and upload.cgi that will allow to handle situations that require user intervention without actually breaking process.

There are also some cool libraries that make great help, like this one https://blueimp.github.io/jQuery-File-Upload/. But for now I decided not to increase Filemin complexity by adding third party libraries and do as much as possible using Webmin core.

Going to the link you provided, right mouse click on RAW and Copy Link Address. That’s the link you need.

Thanks for Filemin - it’s awesome!

I think there is no reason to disable sorting on size column. It can be implemented the way it’s done in Authentic Theme. I made it working by making custom extension for dataTables (based on Webmin data used), which took me hours to figure this out! It works in 99% cases. Now you can test in in Disk Quotas module and add it to Filemin! :wink:

1 . Open your filemin-lib.pl

and on line 290, replace

print ““columnDefs”: [ { “orderable”: false, “targets”: [0, 1, 4] }, ],”;

With:

print ““columnDefs”: [ { “orderable”: false, “targets”: [0, 4], “sType”: “file-size”, “targets”: [1] }, ],”;

Now when using Authentic Theme, the sorting files by size will work!

2 . Another improvement is to enable dataTable save state mode. dataTable uses browser’s localStorage to do it in favor of dated cookies. For example, if user has chosen to sort table by name or pagination number, you WOULD obviously WANT to save this selection, when user opens another page, right?

So add this to your dataTable init: print ““bStateSave”: true,”;

3 . The following can be added to some place in your js codes. (I tested it with dataTables.bootstrap.js and it worked)

A . Let user navigate with arrows (left/right) when trying to do pagination:

$(document).on('keydown', function (event) { var keycode = event.keyCode ? event.keyCode : event.which; if (!$('input').is(':focus') && !$('select').is(':focus') && !$('textarea').is(':focus')) { if (keycode === 39) { $('.paginate_button.next').trigger('click'); } if (keycode === 37) { $('.paginate_button.previous').trigger('click'); } } });

B . Hide paginations when there is nothing to paginate. Add the following on init, let’s say below bPaginate:

__

print " “fnDrawCallback”: function(oSettings) {
console.log(oSettings._iDisplayLength);
if (($(‘table > tbody > tr:visible’).length - 1) >= oSettings._iDisplayLength) {
$(’.dataTables_paginate’).show();
} else {
$(’.dataTables_paginate’).hide();
}
},";

This is it for now. It will make already cool Filemin File Manager even cooler! :wink:

Tell me how it works for you, folks!?

B . Hide paginations requires a bit of work. It fails a bit sometimes…

Oops. :slight_smile: fix for the first part.

This:

print ““columnDefs”: [ { “orderable”: false, “targets”: [0, 4], “sType”: “file-size”, “targets”: [1] }, ],”;

Has to be:

print ““columnDefs”: [ { “orderable”: false, “targets”: [0, 1] }, { “type”: “file-size”, “targets”: [4] } ],”;

There will be more, fixes, I think.

Another fix for fnDrawCallback function:

print " \"fnDrawCallback\": function(oSettings) { if (oSettings.fnRecordsTotal() <= oSettings._iDisplayLength) { \$('.dataTables_paginate').hide(); } else { \$('.dataTables_paginate').show(); } },";

Another point as we don’t need to store search results on page reload and we WANT the search field be automatically focused:

Add it below the on that is above:

print " \"initComplete\": function() { \$('div.dataTables_filter input').val('').trigger('keyup'); \$('div.dataTables_filter input').focus(); },";

Sorry for so many posts. :smiley:

I have finally fixed the sorting function for sizes that gave sometimes unaccurate results. Now it’s all cool!

In the new version of Authentic Theme It will be fixed and with proposed above pieces of codes it will LITERALLY sort files in Filemin (and all other stuff across Webmin) - PERFECTLY.

In case you’re impatient you can test it by finding the following in Authentic Theme package.min.js:

Find:

$.fn.extend(jQuery.fn.dataTableExt.oSort,{"file-size-pre":function(b){z=b.match(/<[^>]*>([\s\S]*?)<.*>/);z&&z[1]?(y=z[1]):(y=b);x=y.match(/(\+|-)?((\d+(\.\d+)?)|(\.\d+))/);x&&(x=x[0]);return(b.match(/TB/i)||b.match(/ТБ/i))?(x*1024*1024*1024*1024):(b.match(/GB/i)||b.match(/ГБ/i))?(x*1024*1024*1024):(b.match(/MB/i)||b.match(/МБ/i))?(x*1024*1024):(b.match(/kB/i)||b.match(/КБ/i))?(x*1024):1},"file-size-asc":function(d,c){return((dc)?1:0))},"file-size-desc":function(d,c){return((dc)?-1:0))}});

Replace with:

$.fn.extend(jQuery.fn.dataTableExt.oSort,{"file-size-pre":function(t){return z=t.match(/<[^>]*>([\s\S]*?)<.*>/),y=z&&z[1]?z[1]:t,x=y.match(/(\+|-)?((\d+(\.\d+)?)|(\.\d+))/),x&&(x=x[0]),x=t.match(/Byte/i)||t.match(/Bytes/i)||t.match(/Байт/i)?1*x:t.match(/kB/i)||t.match(/КБ/i)?1024*x:t.match(/MB/i)||t.match(/МБ/i)?1024*x*1024:t.match(/GB/i)||t.match(/ГБ/i)?1024*x*1024*1024:t.match(/TB/i)||t.match(/ТБ/i)?1024*x*1024*1024*1024:1,x},"file-size-asc":function(t,i){return i>t?-1:t>i?1:0},"file-size-desc":function(t,i){return i>t?1:t>i?-1:0}});

Original, fixed and working code:

$.fn.extend(jQuery.fn.dataTableExt.oSort, {
“file-size-pre”: function (a) {
z = a.match(/<[^>]>([\s\S]?)<.*>/);
z && z[1] ? (y = z[1]) : (y = a);
x = y.match(/(+|-)?((\d+(.\d+)?)|(.\d+))/);
x && (x = x[0]);
if (a.match(/Byte/i) || a.match(/Bytes/i) || a.match(/Байт/i)) {
x = (x * 1);
} else if (a.match(/kB/i) || a.match(/КБ/i)) {
x = (x * 1024);
} else if (a.match(/MB/i) || a.match(/МБ/i)) {
x = (x * 1024 * 1024);
} else if (a.match(/GB/i) || a.match(/ГБ/i)) {
x = (x * 1024 * 1024 * 1024);
} else if (a.match(/TB/i) || a.match(/ТБ/i)) {
x = (x * 1024 * 1024 * 1024 * 1024);
} else {
x = 1;
}
return x;
},
“file-size-asc”: function (a, b) {
return ((a < b) ? -1 : ((a > b) ? 1 : 0));
},
“file-size-desc”: function (a, b) {
return ((a < b) ? 1 : ((a > b) ? -1 : 0));
}
});

@RealGeako.

First of all, you should also exclude Actions from sorting. :slight_smile:

Besides, I wouldn’t recommend using Perl part for generating table header for Filemin, because later, you use hard-coded init settings on columnDefs, referring to the column, by it’s number which is always DIFFERENT based on user settings.

So there are two options:

  1. Hiding/Showing columns using dataTables API (that will not break things like now)

  2. Using Perl to count and later supply the correct numbers in columnDefs. (0 , 1, 3 - to exclude from sorting and for file-size is 4 - this is default and it works ok, if user doesn’t change anything in settings) - well you must make those numbers dynamic.

Small fix to make it work. No it doesn’t matter what user settings are it will not fail. Now, for example, if user disables size column the whole thing will not work, if you do proper size sorting options set.

Put it to init_datatables, at the very top:

my ($a, $b, $c); $a = '0, 1, 3'; $b = '4'; $c = ''; if ($userconfig{'columns'} =~ /type/) { $a = '0, 1, 4'; $b = '5'; } if ($userconfig{'columns'} =~ /size/) { $c = '{ "type": "file-size", "targets": [' . $b . '] },'; }

And part for print columnDefs:

print "\"columnDefs\": [ { \"orderable\": false, \"targets\": [$a] }, $c ],";

It will exclude columns properly based on different user settings and will make sorting files by size work correctly.

Sorting by Last Modification time still not working but this we will fix later.

Please make those change in a commit.

P.S. Please add SELinux labels support.

Regards,
Ilia

…and all together to save people’s time:

For filemin-lib.pl:

sub init_datatables {
my ($a, $b, $c);
$a = '0, 1, 3';
$b = '4';
$c = '';
if ($userconfig{'columns'} =~ /type/) {
    $a = '0, 1, 4';
    $b = '5';
}
if ($userconfig{'columns'} =~ /size/) {
    $c = '{ "type": "file-size", "targets": [' . $b . '] },';
}

if($userconfig{'disable_pagination'}) {
    $bPaginate = 'false';
} else {
    $bPaginate = 'true';
}

print “”;
}

For main.js:

$(document).on(‘keydown’, function (event) {
var keycode = event.keyCode ? event.keyCode : event.which;
if (!$(‘input’).is(’:focus’) && !$(‘select’).is(’:focus’) && !$(‘textarea’).is(’:focus’) && !$(‘body’).find(’.application-modal’).length) {
if (keycode === 39) {
$(’.paginate_button.next’).trigger(‘click’);
}
if (keycode === 37) {
$(’.paginate_button.previous’).trigger(‘click’);
}
}
});

Enjoy.

Dear friends, hi! :wink:

I have made an enormous attempt (over 33 hours of work), to be available for all Authentic Theme 15+ users, on its birthday release (1 year :slight_smile: ), to make Filemin fully AJAXed (run all functions in background, without page reload).

It will bring you absolutely new experience and will make your Filemin faster from 3 to 5 times.

Please leave your feedbacks and comments or found bugs here (https://github.com/Real-Gecko/filemin/issues/48)

Best regards,
Ilia

Version 0.9.6 is out.
Urgent update is advised.
Cause of https://github.com/Real-Gecko/filemin/issues/54

Full list of changes:

  • Fixed `Undefined subroutine &filemin::ceil
    Caused on some systems by not including POSIX package in filemin-lib.pl.
  • Major Authentic interface improvement by Ilia Rostovtsev
    1. Working sorting files by size (with next Authentic Theme - perfectly, now just alright).
      This fix will also prevent fatal code breaks despite of user settings
    2. Store user chose on columns sorting upon page refresh
    3. Hide paginations when there is nothing to paginate.
    4. Let user navigate with arrows (left/right) when trying to do pagination
  • Fixing conflict with Authentic Theme codeMirror
    By Ilia.
  • Code cleanup and security tightening by Jamie Cameron
  • Add ACL options to allowing running as a specific user, thanks Jamie :slight_smile:
  • WARNING: work as root is now DEFAULT behavior.
    IF YOU GRANTED FILEMIN ACCESS TO ANY USERS NOT SUPPOSED TO WORK AS ROOT - GO AND CHECK ACL!!!

#46 fixed:

  • Module is now installable from Usermin.
    When running in Usermin, access is always as the connected user.

#52 fixed:

  • Working as non UNIX user is now possible. By Jamie Cameron.

#54 fixed:

  • Pasting a directory either by copy or cut pasted not the directory, but it’s content.

I tried
https://github.com/Real-Gecko/filemin/raw/master/distrib/webmin-filemin_0.9.6_all.deb

But it did not work.

How to install this?
Thanks

How did you try to install? dpkg?

From webmin

The link you provided is deb package for installation with dpkg.
https://github.com/Real-Gecko/filemin/raw/master/distrib/filemin-0.9.6.linux.wbm.gz
Here is Linux wbm for installation from Webmin.

Thanks, this one works. However, I cannot find this link by browsing on Github.

They can be found in module readme.

Hello RG,

I ask you to display files and directories quantity.
Thanks,
M