Verified Commit c2e9268c authored by Luc Didry's avatar Luc Didry

Fix #123 - Option to force "Burn after reading" for each uploaded file

parent 13e8553c
......@@ -3,6 +3,7 @@ Revision history for Lufi
0.03 2018-??-??
- Use Mojo::SQLite instead of ORLite
- Use FiatTux plugins
- Option to force "Burn after reading" for each uploaded file
0.02.2 2017-09-18
- Fix cron tasks bug
......
......@@ -4,7 +4,7 @@ requires 'Mojolicious::Plugin::DebugDumperHelper';
requires 'Mojolicious::Plugin::I18N';
requires 'Mojolicious::Plugin::Mail';
requires 'Mojolicious::Plugin::FiatTux::Helpers', '== 0.01', url => 'https://framagit.org/luc/mojolicious-plugin-fiattux-helpers/-/archive/0.01/mojolicious-plugin-fiattux-helpers-0.01.tar.gz';
requires 'Mojolicious::Plugin::FiatTux::GrantAccess', '== 0.01', url => 'https://framagit.org/luc/mojolicious-plugin-fiattux-grantaccess/-/archive/0.01/mojolicious-plugin-fiattux-grantaccess-0.01.tar.gz';
requires 'Mojolicious::Plugin::FiatTux::GrantAccess', '== 0.03', url => 'https://framagit.org/luc/mojolicious-plugin-fiattux-grantaccess/-/archive/0.03/mojolicious-plugin-fiattux-grantaccess-0.03.tar.gz';
requires 'EV';
requires 'Filesys::DiskUsage';
requires 'Switch';
......
......@@ -986,7 +986,6 @@ DISTRIBUTIONS
Mojolicious::Lite undef
Mojolicious::Plugin undef
Mojolicious::Plugin::Config undef
Mojolicious::Plugin::Config::Sandbox undef
Mojolicious::Plugin::DefaultHelpers undef
Mojolicious::Plugin::EPLRenderer undef
Mojolicious::Plugin::EPRenderer undef
......@@ -1690,6 +1689,7 @@ DISTRIBUTIONS
requirements:
Authen::SASL 2.00
Convert::ASN1 0.2
Digest::HMAC_MD5 0
Digest::MD5 0
ExtUtils::MakeMaker 6.42
File::Basename 0
......
......@@ -14,24 +14,25 @@ sub startup {
my $config = $self->plugin('Config' => {
default => {
prefix => '/',
provisioning => 100,
provis_step => 5,
length => 10,
token_length => 32,
secrets => ['hfudsifdsih'],
default_delay => 0,
max_delay => 0,
mail => {
prefix => '/',
provisioning => 100,
provis_step => 5,
length => 10,
token_length => 32,
secrets => ['hfudsifdsih'],
default_delay => 0,
max_delay => 0,
mail => {
how => 'sendmail'
},
mail_sender => 'no-reply@lufi.io',
theme => 'default',
upload_dir => 'files',
session_duration => 3600,
allow_pwd_on_files => 0,
dbtype => 'sqlite',
db_path => 'lufi.db',
mail_sender => 'no-reply@lufi.io',
theme => 'default',
upload_dir => 'files',
session_duration => 3600,
allow_pwd_on_files => 0,
dbtype => 'sqlite',
db_path => 'lufi.db',
force_burn_after_reading => 0,
}
});
......@@ -155,6 +156,16 @@ sub startup {
shift->render(template => 'about');
})->name('about');
# Generated js files
$r->get('/partial/:file' => sub {
my $c = shift;
$c->render(
template => 'partial/'.$c->param('file'),
format => 'js',
layout => undef,
);
})->name('partial');
# Get instance stats
$r->get('/fullstats')
->to('Misc#fullstats')
......
......@@ -111,9 +111,11 @@ sub upload {
if (defined($c->config('ldap')) || defined($c->config('htpasswd'))) {
$creator = 'User: '.$c->current_user.', IP: '.$creator;
}
my $delete_at_first_view = ($json->{del_at_first_view}) ? 1 : 0;
$delete_at_first_view = 1 if $c->app->config('force_burn_after_reading');
$f = Lufi::DB::File->new(app => $c->app)->get_empty()
->created_by($creator)
->delete_at_first_view(($json->{del_at_first_view}) ? 1 : 0)
->delete_at_first_view($delete_at_first_view)
->delete_at_day($delay)
->mediatype($json->{type})
->filename($json->{name})
......
......@@ -20,27 +20,28 @@ sub startup {
{
file => $cfile,
default => {
prefix => '/',
theme => 'default',
dbtype => 'sqlite',
prefix => '/',
provisioning => 100,
provis_step => 5,
length => 10,
token_length => 32,
secrets => ['hfudsifdsih'],
default_delay => 0,
max_delay => 0,
mail => {
prefix => '/',
theme => 'default',
dbtype => 'sqlite',
prefix => '/',
provisioning => 100,
provis_step => 5,
length => 10,
token_length => 32,
secrets => ['hfudsifdsih'],
default_delay => 0,
max_delay => 0,
mail => {
how => 'sendmail'
},
mail_sender => 'no-reply@lufi.io',
theme => 'default',
upload_dir => 'files',
session_duration => 3600,
allow_pwd_on_files => 0,
dbtype => 'sqlite',
db_path => 'lufi.db',
mail_sender => 'no-reply@lufi.io',
theme => 'default',
upload_dir => 'files',
session_duration => 3600,
allow_pwd_on_files => 0,
dbtype => 'sqlite',
db_path => 'lufi.db',
force_burn_after_reading => 0,
}
}
);
......
......@@ -158,9 +158,13 @@
#session_duration => 3600,
# allow to add a password on files, asked before allowing to download files
# optional, default to 0
# optional, default is 0
#allow_pwd_on_files => 0,
# force all files to be in "Burn after reading mode"
# optional, default is 0
#force_burn_after_reading => 0,
# if set, the files' URLs will always use this domain
# optional
#fixed_domain => 'example.org',
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -108,3 +108,7 @@ a.classic:focus {
.no_border {
border: 0;
}
.like-label {
color: #9e9e9e;
font-size: 1.5rem;
}
function confirmExit() {
console.log(i18n.confirmExit);
return i18n.confirmExit;
}
// Is the browser IE?
var isIE = /*@cc_on!@*/false || !!document.documentMode;
// If the browser is IE, add readAsBinaryString function and store the data
if (isIE == true){
if (FileReader.prototype.readAsBinaryString === undefined) {
FileReader.prototype.readAsBinaryString = function (fileData) {
var binary = "";
var pt = this;
var reader = new FileReader();
reader.onload = function (e) {
var bytes = new Uint8Array(reader.result);
var length = bytes.byteLength;
for (var i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
//pt.result - readonly so assign content to another property
pt.content = binary;
$(pt).trigger('onloadend');
}
reader.readAsArrayBuffer(fileData);
}
}
}
$(document).ready(function() {
$(".button-collapse").sideNav();
});
......@@ -38,21 +38,6 @@
</table>
</div>
%= javascript begin
% if (defined($self->config('fixed_domain')) && $self->config('fixed_domain')) {
var baseURL = '<%= url_for('/')->host($self->config('fixed_domain'))->to_abs() %>';
% } else {
var baseURL = '<%= url_for('/')->to_abs() %>';
% }
var actionURL = '<%= url_for('/')->to_abs() %>';
var counterURL = '<%== url_for('counter') %>';
var i18n = {
noExpiration: '<%= l('No expiration delay') %>',
importProcessed: '<%= l('The data has been successfully imported.') %>',
};
$(document).ready(function() {
populateFilesTable();
});
% end
%= javascript '/partial/files.js.ep'
%= javascript '/js/lufi-files.js'
%= javascript '/js/moment-with-locales.min.js'
......@@ -59,8 +59,18 @@
</div>
</div>
<div class="input-field">
<p class="col s12 m6 text-left">
<input type="checkbox" id="first-view" data-checked="">
% if ($self->config('force_burn_after_reading')) {
<p class="col s12 m6 text-left like-label">
<%= l('Files deleted at first download') %>
</p>
% }
<p class="col s12 m6 text-left<%= ' hiddendiv' if $self->config('force_burn_after_reading') %>">
<input
type="checkbox"
id="first-view"
data-checked="<%= 'data-checked' if $self->config('force_burn_after_reading') %>"
<%= 'disabled="disabled"' if $self->config('force_burn_after_reading') %>
>
<label for="first-view"><%= l('Delete at first download?') %></label>
</p>
</div>
......@@ -88,37 +98,7 @@
</ul>
</div>
%= include 'delays'
%= javascript begin
$(document).ready(function(){
$('.modal-trigger').leanModal();
$('select').material_select();
});
var ws_url = '<%= url_for('upload')->to_abs() %>';
% if (defined($self->config('fixed_domain')) && $self->config('fixed_domain')) {
var baseURL = '<%= url_for('/')->host($self->config('fixed_domain'))->to_abs() %>';
% } else {
var baseURL = '<%= url_for('/')->to_abs() %>';
% }
var actionURL = '<%= url_for('/')->to_abs() %>';
var i18n = {
confirmExit: '<%= l('You have attempted to leave this page. The upload will be canceled. Are you sure?') %>',
copyAll: '<%= l('Copy all links to clipboard') %>',
copySuccess: '<%= l('The link(s) has been copied to your clipboard') %>',
copyFail: '<%= l('Unable to copy the link(s) to your clipboard') %>',
cpText: '<%= l('Copy to clipboard') %>',
delText: '<%= l('Deletion link') %>',
dlText: '<%= l('Download link') %>',
download: '<%= l('Download') %>',
encrypting: '<%= l('Encrypting part XX1 of XX2') %>',
expiration: '<%= l('Expiration:') %>',
hit: '<%= l('Hit Enter, then Ctrl+C to copy the download link') %>',
hits: '<%= l('Hit Enter, then Ctrl+C to copy all the download links') %>',
mailTo: '<%= l('Send all links by email') %>',
noLimit: '<%= l('No expiration delay') %>',
sending: '<%= l('Sending part XX1 of XX2. Please, be patient, the progress bar can take a while to move.') %>',
wsProblem: '<%= l('Websocket communication error') %>',
};
% end
%= javascript '/partial/index.js'
%= javascript '/js/sjcl.js'
%= javascript '/js/moment-with-locales.min.js'
%= javascript '/js/lufi-up.js'
......
......@@ -17,37 +17,7 @@
<link rel="apple-touch-icon-precomposed" sizes="128x128" href="<%= url_for('/img/lufi128.png') %>">
%= stylesheet '/css/materialize.min.css'
%= stylesheet '/css/lufi.css'
%= javascript begin
function confirmExit() {
console.log(i18n.confirmExit);
return i18n.confirmExit;
}
// Is the browser IE?
var isIE = /*@cc_on!@*/false || !!document.documentMode;
// If the browser is IE, add readAsBinaryString function and store the data
if (isIE == true){
if (FileReader.prototype.readAsBinaryString === undefined) {
FileReader.prototype.readAsBinaryString = function (fileData) {
var binary = "";
var pt = this;
var reader = new FileReader();
reader.onload = function (e) {
var bytes = new Uint8Array(reader.result);
var length = bytes.byteLength;
for (var i = 0; i < length; i++) {
binary += String.fromCharCode(bytes[i]);
}
//pt.result - readonly so assign content to another property
pt.content = binary;
$(pt).trigger('onloadend');
}
reader.readAsArrayBuffer(fileData);
}
}
}
% end
%= javascript '/js/ie-detection.js'
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
......@@ -90,10 +60,6 @@
<img src="<%== config('piwik_img') %>" class="no_border" alt="" />
% }
%= javascript '/js/materialize.js'
%= javascript begin
$(document).ready(function() {
$(".button-collapse").sideNav();
});
%end
%= javascript '/js/sidenav.js'
</body>
</html>
......@@ -46,63 +46,5 @@
<a href="#" class="btn btn-primary" id="mailto"><%= l('Send with your own mail software') %></a>
</form>
<div>
%= javascript begin
function findItem(name) {
var files = localStorage.getItem('files');
if (files === null) {
files = new Array();
} else {
files = JSON.parse(files);
}
var i;
for (i = 0; i < files.length; i++) {
if (files[i].short === name) {
return files[i];
}
}
}
function updateMailtoLink() {
var btn = document.getElementById('mailto');
var emails = document.getElementById('emails');
var subject = document.getElementById('subject');
var text = document.getElementById('body');
btn.href = 'mailto:'+encodeURIComponent(emails.value)+'?subject='+encodeURIComponent(subject.value)+'&body='+encodeURIComponent(text.value);
}
function populateBody() {
var links = [
% for my $link (@{$links}) {
'<%= $link %>',
% }
];
var text = "<%== l('Hello,\n\nHere\'s some files I want to share with you:\n') %>";
links.forEach(function(name, index, array) {
var item = findItem(name);
if (item !== null && item !== undefined) {
var limit = (item.delay === 0) ? null : moment.unix(item.delay * 86400 + item.created_at).locale(window.navigator.language).format('LLLL');
text = text+'- '+item.name+'<%= l(':') %> '+item.url;
if (limit !== null) {
text = text+"\n (<%= l('deadline: ') %>"+limit+')';
}
text = text+"\n";
}
});
text = text+"\n--\n<%= l('Share your files in total privacy on %1', url_for('/')->to_abs) %>";
tArea = document.getElementById('body').value = text;
updateMailtoLink();
}
document.addEventListener('DOMContentLoaded', function() {
% unless (defined(stash('msg')) || defined(stash('values'))) {
populateBody();
% }
var emails = document.getElementById('emails');
var subject = document.getElementById('subject');
var text = document.getElementById('body');
emails.addEventListener('change', updateMailtoLink);
subject.addEventListener('change', updateMailtoLink);
text.addEventListener('change', updateMailtoLink);
});
% end
%= javascript '/partial/mail.js'
%= javascript '/js/moment-with-locales.min.js'
% # vim:set sts=4 sw=4 ts=4 ft=javascript expandtab:
% if (defined($self->config('fixed_domain')) && $self->config('fixed_domain')) {
var baseURL = '<%= url_for('/')->host($self->config('fixed_domain'))->to_abs() %>';
% } else {
var baseURL = '<%= url_for('/')->to_abs() %>';
% }
var actionURL = '<%= url_for('/')->to_abs() %>';
var counterURL = '<%== url_for('counter') %>';
var i18n = {
noExpiration: '<%= l('No expiration delay') %>',
importProcessed: '<%= l('The data has been successfully imported.') %>',
};
$(document).ready(function() {
populateFilesTable();
});
% # vim:set sts=4 sw=4 ts=4 ft=javascript expandtab:
$(document).ready(function(){
$('.modal-trigger').leanModal();
$('select').material_select();
});
var ws_url = '<%= url_for('upload')->to_abs() %>';
% if (defined($self->config('fixed_domain')) && $self->config('fixed_domain')) {
var baseURL = '<%= url_for('/')->host($self->config('fixed_domain'))->to_abs() %>';
% } else {
var baseURL = '<%= url_for('/')->to_abs() %>';
% }
var actionURL = '<%= url_for('/')->to_abs() %>';
var i18n = {
confirmExit: '<%= l('You have attempted to leave this page. The upload will be canceled. Are you sure?') %>',
copyAll: '<%= l('Copy all links to clipboard') %>',
copySuccess: '<%= l('The link(s) has been copied to your clipboard') %>',
copyFail: '<%= l('Unable to copy the link(s) to your clipboard') %>',
cpText: '<%= l('Copy to clipboard') %>',
delText: '<%= l('Deletion link') %>',
dlText: '<%= l('Download link') %>',
download: '<%= l('Download') %>',
encrypting: '<%= l('Encrypting part XX1 of XX2') %>',
expiration: '<%= l('Expiration:') %>',
hit: '<%= l('Hit Enter, then Ctrl+C to copy the download link') %>',
hits: '<%= l('Hit Enter, then Ctrl+C to copy all the download links') %>',
mailTo: '<%= l('Send all links by email') %>',
noLimit: '<%= l('No expiration delay') %>',
sending: '<%= l('Sending part XX1 of XX2. Please, be patient, the progress bar can take a while to move.') %>',
wsProblem: '<%= l('Websocket communication error') %>',
};
% # vim:set sts=4 sw=4 ts=4 ft=javascript expandtab:
function findItem(name) {
var files = localStorage.getItem('files');
if (files === null) {
files = new Array();
} else {
files = JSON.parse(files);
}
var i;
for (i = 0; i < files.length; i++) {
if (files[i].short === name) {
return files[i];
}
}
}
function updateMailtoLink() {
var btn = document.getElementById('mailto');
var emails = document.getElementById('emails');
var subject = document.getElementById('subject');
var text = document.getElementById('body');
btn.href = 'mailto:'+encodeURIComponent(emails.value)+'?subject='+encodeURIComponent(subject.value)+'&body='+encodeURIComponent(text.value);
}
function populateBody() {
var links = [
% for my $link (@{$links}) {
'<%= $link %>',
% }
];
var text = "<%== l('Hello,\n\nHere\'s some files I want to share with you:\n') %>";
links.forEach(function(name, index, array) {
var item = findItem(name);
if (item !== null && item !== undefined) {
var limit = (item.delay === 0) ? null : moment.unix(item.delay * 86400 + item.created_at).locale(window.navigator.language).format('LLLL');
text = text+'- '+item.name+'<%= l(':') %> '+item.url;
if (limit !== null) {
text = text+"\n (<%= l('deadline: ') %>"+limit+')';
}
text = text+"\n";
}
});
text = text+"\n--\n<%= l('Share your files in total privacy on %1', url_for('/')->to_abs) %>";
tArea = document.getElementById('body').value = text;
updateMailtoLink();
}
document.addEventListener('DOMContentLoaded', function() {
% unless (defined(stash('msg')) || defined(stash('values'))) {
populateBody();
% }
var emails = document.getElementById('emails');
var subject = document.getElementById('subject');
var text = document.getElementById('body');
emails.addEventListener('change', updateMailtoLink);
subject.addEventListener('change', updateMailtoLink);
text.addEventListener('change', updateMailtoLink);
});
% # vim:set sts=4 sw=4 ts=4 ft=javascript expandtab:
var ws_url = '<%= url_for('download')->to_abs() %>';
var i18n = {
aborted1: '<%= l('Download aborted.') %>',
aborted2: '<%= l('Click here to refresh the page and restart the download.') %>',
badkey: '<%= l('It seems that the key in your URL is incorrect. Please, verify your URL.') %>',
confirmExit: '<%= l('You have attempted to leave this page. The download will be canceled. Are you sure?') %>',
download: '<%= l('Get the file') %>',
loading: '<%= l('Asking for file part XX1 of %1', stash('f')->nbslices) %>',
nokey: '<%= l('You don\'t seem to have a key in your URL. You won\'t be able to decrypt the file. Download canceled.') %>',
}
......@@ -41,18 +41,7 @@
<div class="file-abort col s12<%= (stash('file_pwd')) ? ' hide' : '' %>">
<a id="abort" class="waves-effect waves-light btn"><%= l('Abort') %></a>
</div>
%= javascript begin
var ws_url = '<%= url_for('download')->to_abs() %>';
var i18n = {
aborted1: '<%= l('Download aborted.') %>',
aborted2: '<%= l('Click here to refresh the page and restart the download.') %>',
badkey: '<%= l('It seems that the key in your URL is incorrect. Please, verify your URL.') %>',
confirmExit: '<%= l('You have attempted to leave this page. The download will be canceled. Are you sure?') %>',
download: '<%= l('Get the file') %>',
loading: '<%= l('Asking for file part XX1 of %1', stash('f')->nbslices) %>',
nokey: '<%= l('You don\'t seem to have a key in your URL. You won\'t be able to decrypt the file. Download canceled.') %>',
}
% end
%= javascript '/partial/render.js'
%= javascript '/js/filesize.min.js'
%= javascript '/js/sjcl.js'
%= javascript '/js/lufi-down.js'
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment