This commit is contained in:
Luc Didry
2014-06-01 18:40:16 +02:00
parent 75dde62989
commit 846d8a1bfe
20 changed files with 242 additions and 97 deletions
+2
View File
@@ -1,6 +1,8 @@
Revision history for Lutim
0.3 2014-
- Add a delete link to images (#28)
- Concatenated css and js with Mojolicious::Plugin::AssetPack
- Antiflood protection for the "Download by URL" feature (#29)
- Stats page improved
- Self-documented configuration template
+13 -12
View File
@@ -59,19 +59,20 @@ vi lutim.conf
The `lutim.conf.template` is self-documented but here is the options that you can set:
* hypnotoad: address and port to listen to, user and group which runs hypnotoad (if you run Lutim with a different user from what is defined here, be sure that the user which launchs hypnotoad is able to setuid/setgid to the defined user/group, otherwise it will not work and you'll have 100% CPU consumption. Launch hypnotoad with the root user or with the user which is defined here);
* contact: write something which make people able to contact you (contact form URL, email address, whatever) ;
* contact: write something which make people able to contact you (contact form URL, email address, whatever);
* secrets: an array of random string. Used by Mojolicious for encrypting session cookies.
* piwik_img: the Piwik image provides you records of visits without javascript (better privacy than js and cookies) ;
* length: length of the random string part of image's URL (default is 8) ;
* provis_step: Lutim provisions random strings for image's URL per pack of `provis_step` (default is 5) ;
* provisioning: number of random strings to provision (default is 100) ;
* hosted_by: if someone hosts your Lutim instance, you can add some HTML (a logo for example) to make it appear on index page ;
* tweet_card_via: a Twitter account which will appear on Twitter cards ;
* max_file_size: well, this is explicit (default is 10Mio = 10485760 octets) ;
* https: 1 if you want to provide secure images URLs (default is 0) DEPRECATED, PASS A `X-Forwarded-Proto` HEADER TO LUTIM FROM YOUR REVERSE PROXY INSTEAD ;
* stats_day_num: when you generate statistics with `script/lutim cron stats`, you will have stats for the last `stats_day_num` days (default is 365) ;
* keep_ip_during: when you delete IP addresses of image's senders with `script/lutim cron cleanbdd`, the IP addresses of images older than `keep_ip_during` days will be deleted (default is 365) ;
* broadcast_message: put some string (not HTML) here and this message will be displayed on all Lutim pages (not in JSON responses) ;
* piwik_img: the Piwik image provides you records of visits without javascript (better privacy than js and cookies);
* length: length of the random string part of image's URL (default is 8);
* provis_step: Lutim provisions random strings for image's URL per pack of `provis_step` (default is 5);
* provisioning: number of random strings to provision (default is 100);
* hosted_by: if someone hosts your Lutim instance, you can add some HTML (a logo for example) to make it appear on index page;
* tweet_card_via: a Twitter account which will appear on Twitter cards;
* max_file_size: well, this is explicit (default is 10Mio = 10485760 octets);
* https: 1 if you want to provide secure images URLs (default is 0) DEPRECATED, PASS A `X-Forwarded-Proto` HEADER TO LUTIM FROM YOUR REVERSE PROXY INSTEAD;
* token_length: length of the secret token used to allow people to delete their images when they want;
* stats_day_num: when you generate statistics with `script/lutim cron stats`, you will have stats for the last `stats_day_num` days (default is 365);
* keep_ip_during: when you delete IP addresses of image's senders with `script/lutim cron cleanbdd`, the IP addresses of images older than `keep_ip_during` days will be deleted (default is 365);
* broadcast_message: put some string (not HTML) here and this message will be displayed on all Lutim pages (not in JSON responses);
* allowed_domains: array of authorized domains for API calls. Example: `['http://1.example.com', 'http://2.example.com']`. If you want to authorize everyone to use the API: `['\*']`.
* default_delay: what is the default time limit for files? Valid values are 0, 1, 7, 30 and 365;
* max_delay: if defined, the images will be deleted after that delay (in days), even if they were uploaded with "no delay" (or value superior to max_delay) option and a warning message will be displayed on homepage;
+58
View File
@@ -0,0 +1,58 @@
{
"name": "",
"css_prefix_text": "icon-",
"css_use_suffix": false,
"hinting": true,
"units_per_em": 1000,
"ascent": 850,
"glyphs": [
{
"uid": "c5fd349cbd3d23e4ade333789c29c729",
"css": "eye",
"code": 59399,
"src": "fontawesome"
},
{
"uid": "9a76bc135eac17d2c8b8ad4a5774fc87",
"css": "download",
"code": 59397,
"src": "fontawesome"
},
{
"uid": "f48ae54adfb27d8ada53d0fd9e34ee10",
"css": "trash",
"code": 59396,
"src": "fontawesome"
},
{
"uid": "2cb15eb2b295ee3c33fab1530e18a924",
"css": "bitcoin",
"code": 59395,
"src": "fontawesome"
},
{
"uid": "0f6a2573a7b6df911ed199bb63717e27",
"css": "github-circled",
"code": 59393,
"src": "fontawesome"
},
{
"uid": "627abcdb627cb1789e009c08e2678ef9",
"css": "twitter",
"code": 59392,
"src": "fontawesome"
},
{
"uid": "fccd3ea0efb711b849045bee686b1ceb",
"css": "spinner",
"code": 59398,
"src": "mfglabs"
},
{
"uid": "c71d7db10ede1349b3a8ae0293b1dbf8",
"css": "flattr",
"code": 59394,
"src": "zocial"
}
]
}
+19 -4
View File
@@ -27,6 +27,7 @@ sub startup {
https => 0,
default_delay => 0,
max_delay => 0,
token_length => 24,
}
});
@@ -117,7 +118,8 @@ sub startup {
counter => 0,
enabled => 1,
delete_at_first_view => 0,
delete_at_day => 0
delete_at_day => 0,
mod_token => $c->shortener($c->config->{token_length})
);
LutimModel->commit;
}
@@ -243,6 +245,15 @@ sub startup {
}
);
$self->helper(
delete_image => sub {
my $c = shift;
my $image = shift;
unlink $image->path();
$image->update(enabled => 0);
}
);
$self->hook(
before_dispatch => sub {
my $c = shift;
@@ -280,9 +291,9 @@ sub startup {
}
);
$self->asset('index.css' => 'css/bootstrap.min.css', 'css/fontello.css', 'css/animation.css', 'css/uploader.css', 'css/hennypenny.css', 'css/lutim.css');
$self->asset('stats.css' => 'css/bootstrap.min.css', 'css/fontello.css', 'css/animation.css', 'css/morris-0.4.3.min.css', 'css/hennypenny.css', 'css/lutim.css');
$self->asset('about.css' => 'css/bootstrap.min.css', 'css/fontello.css', 'css/animation.css', 'css/hennypenny.css', 'css/lutim.css');
$self->asset('index.css' => 'css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/animation.css', 'css/uploader.css', 'css/hennypenny.css', 'css/lutim.css');
$self->asset('stats.css' => 'css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/animation.css', 'css/morris-0.4.3.min.css', 'css/hennypenny.css', 'css/lutim.css');
$self->asset('about.css' => 'css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/animation.css', 'css/hennypenny.css', 'css/lutim.css');
$self->asset('index.js' => 'js/jquery-2.1.0.min.js', 'js/bootstrap.min.js', 'js/lutim.js', 'js/dmuploader.min.js');
$self->asset('stats.js' => 'js/jquery-2.1.0.min.js', 'js/bootstrap.min.js', 'js/lutim.js', 'js/raphael-min.js', 'js/morris-0.4.3.min.js', 'js/stats.js');
@@ -316,6 +327,10 @@ sub startup {
to('Controller#add')->
name('add');
$r->get('/d/:short/:token')->
to('Controller#delete')->
name('delete');
$r->get('/:short')->
to('Controller#short')->
name('short');
+52 -13
View File
@@ -46,6 +46,41 @@ sub stats {
);
}
sub delete {
my $c = shift;
my $short = $c->param('short');
my $token = $c->param('token');
my @images = LutimModel::Lutim->select('WHERE short = ? AND path IS NOT NULL', $short);
if (scalar(@images)) {
my $image = $images[0];
my $msg;
if ($image->mod_token() ne $token) {
$msg = $c->l('invalid_token');
} elsif ($image->enabled() == 0) {
$msg = $c->l('already_deleted', $image->filename);
} else {
$c->app->log->info('[DELETION] someone made '.$image->filename.' removed with token method (path: '.$image->path.')');
$c->delete_image($image);
$c->flash(
success => $c->l('image_deleted', $image->filename)
);
return $c->redirect_to('/');
}
$c->flash(
msg => $msg
);
return $c->redirect_to('/');
} else {
$c->app->log->info('[UNSUCCESSFUL] someone tried to delete '.$short.' but it does\'nt exist.');
# Image never existed
$c->render_not_found;
}
}
sub add {
my $c = shift;
my $upload = $c->param('file');
@@ -133,7 +168,7 @@ sub add {
my $ip = $c->ip;
my ($msg, $short, $thumb);
my ($msg, $short, $real_short, $token, $thumb);
# Check file type
if (index($mediatype, 'image/') >= 0) {
# Create directory if needed
@@ -190,8 +225,10 @@ sub add {
$c->app->log->info('[CREATION] '.$ip.' pushed '.$filename.' (path: '.$path.')');
# Give url to user
$short = $records[0]->short;
$short .= '/'.$key if (defined($key));
$short = $records[0]->short;
$real_short = $short;
$token = $records[0]->mod_token;
$short .= '/'.$key if (defined($key));
} else {
# Houston, we have a problem
$msg = $c->l('no_more_short', $c->config->{contact});
@@ -205,9 +242,11 @@ sub add {
if (defined($c->param('format')) && $c->param('format') eq 'json') {
if (defined($short)) {
$msg = {
filename => $upload->filename,
short => $short,
thumb => $thumb
filename => $upload->filename,
short => $short,
real_short => $real_short,
token => $token,
thumb => $thumb
};
} else {
$msg = {
@@ -227,9 +266,11 @@ sub add {
$c->flash(filename => $upload->filename);
return $c->redirect_to('/');
} else {
$c->stash(short => $short) if (defined($short));
$c->stash(thumb => $thumb);
$c->stash(filename => $upload->filename);
$c->stash(short => $short) if (defined($short));
$c->stash(real_short => $real_short);
$c->stash(token => $token);
$c->stash(thumb => $thumb);
$c->stash(filename => $upload->filename);
return $c->render(
template => 'index',
max_file_size => $c->req->max_message_size
@@ -270,8 +311,7 @@ sub short {
$c->app->log->info('[DELETION] someone tried to view '.$images[0]->filename.' but it has been removed by expiration (path: '.$images[0]->path.')');
# Delete image
unlink $images[0]->path();
$images[0]->update(enabled => 0);
$c->delete_image($images[0]);
# Warn user
$c->flash(
@@ -318,8 +358,7 @@ sub short {
$c->app->log->info('[DELETION] someone made '.$images[0]->filename.' removed (path: '.$images[0]->path.')');
# Delete image
unlink $images[0]->path();
$images[0]->update(enabled => 0);
$c->delete_image($images[0]);
}
});
}
+5 -1
View File
@@ -43,6 +43,7 @@ our %Lexicon = (
'view-link' => 'View link',
'download-link' => 'Download link',
'twitter-link' => 'Link for put in a tweet',
'delete-link' => 'Deletion link',
'some-bad' => 'Something bad happened',
'delete-first' => 'Delete at first view?',
'delete-day' => 'Delete after 24 hours?',
@@ -52,7 +53,7 @@ our %Lexicon = (
'drag-n-drop' => 'Drag & drop images here',
'or' => '-or-',
'file-browser' => 'Click to open the file browser',
'image_not_found' => 'Unable to find the image',
'image_not_found' => 'Unable to find the image: it has been deleted.',
'no_more_short' => 'There is no more available URL. Retry or contact the administrator. [_1]',
'no_valid_file' => 'The file [_1] is not an image.',
'file_too_big' => 'The file exceed the size limit ([_1])',
@@ -77,6 +78,9 @@ our %Lexicon = (
'max_delay' => 'Warning! The maximum time limit for an image is [_1] day(s), even if you choose "no time limit".',
'crypt_image' => 'Encrypt the image (Lutim does not keep the key).',
'always_encrypt' => 'The images are encrypted on the server (Lutim does not keep the key).',
'image_deleted' => 'The image [_1] has been successfully deleted',
'invalid_token' => 'The delete token is invalid.',
'already_deleted' => 'The image [_1] has already been deleted.',
);
1;
+5 -1
View File
@@ -43,6 +43,7 @@ our %Lexicon = (
'view-link' => 'Lien d\'affichage',
'download-link' => 'Lien de téléchargement',
'twitter-link' => 'Lien pour mettre dans un tweet',
'delete-link' => 'Lien de suppression',
'some-bad' => 'Un problème est survenu',
'delete-first' => 'Supprimer au premier accès ?',
'delete-day' => 'Supprimer après 24 heures ?',
@@ -52,7 +53,7 @@ our %Lexicon = (
'drag-n-drop' => 'Déposez vos images ici',
'or' => '-ou-',
'file-browser' => 'Cliquez pour utiliser le navigateur de fichier',
'image_not_found' => 'Impossible de trouver l\'image',
'image_not_found' => 'Impossible de trouver l\'image : elle a été supprimée.',
'no_more_short' => 'Il n\'y a plus d\'URL disponible. Veuillez réessayer ou contactez l\'administrateur. [_1].',
'no_valid_file' => 'Le fichier [_1] n\'est pas une image.',
'file_too_big' => 'Le fichier dépasse la limite de taille ([_1])',
@@ -77,6 +78,9 @@ our %Lexicon = (
'max_delay' => 'Attention ! Le délai maximal de rétention d\'une image est de [_1] jour(s), même si vous choisissez « pas de limitation de durée ».',
'crypt_image' => 'Chiffrer l\'image (Lutim ne stocke pas la clé).',
'always_encrypt' => 'Les images sont chiffrées sur le serveur (Lutim ne stocke pas la clé).',
'image_deleted' => 'L\'image [_1] a été supprimée avec succès.',
'invalid_token' => 'Le jeton de suppression est invalide.',
'already_deleted' => 'L\'image [_1] a déjà été supprimée.',
);
1;
+1 -1
View File
@@ -20,7 +20,7 @@ use ORLite {
created_at INTEGER,
created_by TEXT,
last_access_at INTEGER,
last_access_by INTEGER)'
mod_token TEXT)'
);
return 1;
}
+2 -4
View File
@@ -13,8 +13,7 @@ sub run {
my @images = LutimModel::Lutim->select('WHERE enabled = 1 AND (delete_at_day * 86400) < (? - created_at) AND delete_at_day != 0', $time);
for my $image (@images) {
$image->update(enabled => 0);
unlink $image->path();
$c->app->delete_image($image);
}
my $config = $c->app->plugin('Config');
@@ -24,8 +23,7 @@ sub run {
@images = LutimModel::Lutim->select('WHERE enabled = 1 AND last_access_at < ?', $time);
for my $image (@images) {
$image->update(enabled => 0);
unlink $image->path();
$c->app->delete_image($image);
}
}
}
+4
View File
@@ -96,6 +96,10 @@
# optional, default is 0
#always_encrypt => 0,
# length of the image's delete token
# optional, default is 24
#token_length => 24,
##########################
# Lutim cron jobs settings
##########################
+8 -7
View File
@@ -1,8 +1,9 @@
.icon-eye:before { content: '\e806'; } /* '' */
.icon-download:before { content: '\e804'; } /* '' */
.icon-bitcoin:before { content: '\e802'; } /* '' */
.icon-spinner:before { content: '\e805'; } /* '' */
.icon-github-circled:before { content: '\e800'; } /* '' */
.icon-touiteur:before { content: '\e801'; } /* '' */
.icon-flattr:before { content: '\e803'; } /* '' */
.icon-twitter:before { content: '\e800'; } /* '' */
.icon-github-circled:before { content: '\e801'; } /* '' */
.icon-flattr:before { content: '\e802'; } /* '' */
.icon-bitcoin:before { content: '\e803'; } /* '' */
.icon-trash:before { content: '\e804'; } /* '' */
.icon-download:before { content: '\e805'; } /* '' */
.icon-spinner:before { content: '\e806'; } /* '' */
.icon-eye:before { content: '\e807'; } /* '' */
+14 -13
View File
File diff suppressed because one or more lines are too long
+8 -7
View File
@@ -1,8 +1,9 @@
.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); }
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe804;&nbsp;'); }
.icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe805;&nbsp;'); }
.icon-github-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe800;&nbsp;'); }
.icon-touiteur { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.icon-flattr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
.icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe800;&nbsp;'); }
.icon-github-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.icon-flattr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
.icon-trash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe804;&nbsp;'); }
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe805;&nbsp;'); }
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); }
.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe807;&nbsp;'); }
+8 -7
View File
@@ -10,10 +10,11 @@
/* font-size: 120%; */
}
.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); }
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe804;&nbsp;'); }
.icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe805;&nbsp;'); }
.icon-github-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe800;&nbsp;'); }
.icon-touiteur { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.icon-flattr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
.icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe800;&nbsp;'); }
.icon-github-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe801;&nbsp;'); }
.icon-flattr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe802;&nbsp;'); }
.icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe803;&nbsp;'); }
.icon-trash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe804;&nbsp;'); }
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe805;&nbsp;'); }
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe806;&nbsp;'); }
.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '&#xe807;&nbsp;'); }
+14 -13
View File
@@ -1,10 +1,10 @@
@font-face {
font-family: 'fontello';
src: url('../font/fontello.eot?69050751');
src: url('../font/fontello.eot?69050751#iefix') format('embedded-opentype'),
url('../font/fontello.woff?69050751') format('woff'),
url('../font/fontello.ttf?69050751') format('truetype'),
url('../font/fontello.svg?69050751#fontello') format('svg');
src: url('../font/fontello.eot?47445522');
src: url('../font/fontello.eot?47445522#iefix') format('embedded-opentype'),
url('../font/fontello.woff?47445522') format('woff'),
url('../font/fontello.ttf?47445522') format('truetype'),
url('../font/fontello.svg?47445522#fontello') format('svg');
font-weight: normal;
font-style: normal;
}
@@ -14,7 +14,7 @@
@media screen and (-webkit-min-device-pixel-ratio:0) {
@font-face {
font-family: 'fontello';
src: url('../font/fontello.svg?69050751#fontello') format('svg');
src: url('../font/fontello.svg?47445522#fontello') format('svg');
}
}
*/
@@ -50,10 +50,11 @@
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
}
.icon-eye:before { content: '\e806'; } /* '' */
.icon-download:before { content: '\e804'; } /* '' */
.icon-bitcoin:before { content: '\e802'; } /* '' */
.icon-spinner:before { content: '\e805'; } /* '' */
.icon-github-circled:before { content: '\e800'; } /* '' */
.icon-touiteur:before { content: '\e801'; } /* '' */
.icon-flattr:before { content: '\e803'; } /* '' */
.icon-twitter:before { content: '\e800'; } /* '' */
.icon-github-circled:before { content: '\e801'; } /* '' */
.icon-flattr:before { content: '\e802'; } /* '' */
.icon-bitcoin:before { content: '\e803'; } /* '' */
.icon-trash:before { content: '\e804'; } /* '' */
.icon-download:before { content: '\e805'; } /* '' */
.icon-spinner:before { content: '\e806'; } /* '' */
.icon-eye:before { content: '\e807'; } /* '' */
Binary file not shown.
+8 -7
View File
@@ -6,13 +6,14 @@
<font id="fontello" horiz-adv-x="1000" >
<font-face font-family="fontello" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="850" descent="-150" />
<missing-glyph horiz-adv-x="1000" />
<glyph glyph-name="eye" unicode="&#xe806;" d="m929 314q-85 132-213 197q34-58 34-125q0-104-73-177t-177-73t-177 73t-73 177q0 67 34 125q-128-65-213-197q75-114 187-182t242-68t242 68t187 182z m-402 215q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-12 8-19t19-8t19 8t8 19q0 48 34 82t82 34q11 0 19 8t8 19z m473-215q0-19-11-38q-78-129-210-206t-279-77t-279 77t-210 206q-11 19-11 38t11 39q78 128 210 205t279 78t279-78t210-205q11-20 11-39z" horiz-adv-x="1000" />
<glyph glyph-name="download" unicode="&#xe804;" d="m714 100q0 15-10 25t-25 11t-26-11t-10-25t10-25t26-11t25 11t10 25z m143 0q0 15-10 25t-26 11t-25-11t-10-25t10-25t25-11t26 11t10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-40l-250-250q-10-10-25-10t-25 10l-250 250q-17 17-8 40q10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
<glyph glyph-name="bitcoin" unicode="&#xe802;" d="m651 493q10-102-73-144q65-16 98-58t25-119q-4-40-18-70t-36-49t-54-33t-68-19t-81-9v-142h-86v140q-45 0-68 1v-141h-86v142q-10 0-30 1t-31 0h-112l18 102h62q27 0 32 28v225h9q-4 0-9 0v160q-7 38-50 38h-62v92l119-1q35 0 54 1v141h86v-138q45 1 68 1v137h86v-141q44-4 78-13t63-25t46-43t20-64z m-120-304q0 20-8 35t-21 26t-32 17t-36 10t-42 5t-38 2t-36 0t-27-1v-189q5 0 21 0t27 0t29 1t33 2t32 5t31 8t26 11t22 17t14 22t5 29z m-39 265q0 19-7 33t-17 23t-27 16t-31 9t-34 5t-33 1t-30 0t-22-1v-171q3 0 20 0t26 0t27 1t31 3t29 6t27 10t21 15t15 22t5 28z" horiz-adv-x="714.3" />
<glyph glyph-name="spinner" unicode="&#xe805;" d="m277 100q0-33-24-57t-57-23q-33 0-56 23t-24 57t24 57t56 23q33 0 57-23t24-57z m241-107q0-30-21-51t-51-21t-50 21t-21 51t21 50t50 21t51-21t21-50z m-339 357q0-37-27-63t-63-26t-63 26t-26 63t26 63t63 26t63-26t27-63z m580-250q0-26-18-44t-45-18t-44 18t-18 44t18 44t44 19t45-19t18-44z m-464 500q0-41-29-69t-70-29t-69 29t-29 69t29 69t69 29t70-29t29-69z m259 107q0-45-32-76t-76-31t-75 31t-32 76t32 76t75 31t76-31t32-76z m303-357q0-22-15-38t-38-16t-38 16t-16 38t16 38t38 16t38-16t15-38z m-116 250q0-18-13-32t-32-13t-31 13t-13 32t13 31t31 14t32-14t13-31z" horiz-adv-x="875" />
<glyph glyph-name="github-circled" unicode="&#xe800;" d="m857 350q0-140-82-252t-211-155q-15-3-22 4t-7 17v118q0 54-29 79q32 3 57 10t53 22t45 37t30 58t11 84q0 68-44 115q21 51-5 114q-15 5-45-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22t-48 7q-24-63-4-114q-44-47-44-115q0-47 12-83t29-59t45-37t52-22t57-10q-22-20-27-58q-12-5-25-8t-32-3t-36 12t-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7t5-8t7-6l4-3q12-6 24-21t18-29l5-13q8-21 25-34t37-17t39-4t31 2l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156t216 58t215-58t156-156t57-215z" horiz-adv-x="857.1" />
<glyph glyph-name="touiteur" unicode="&#xe801;" d="m904 622q-37-54-90-93q0-8 0-23q0-73-21-145t-64-139t-103-117t-144-82t-181-30q-151 0-276 81q19-3 43-3q126 0 224 77q-59 2-105 36t-64 89q19-2 34-2q24 0 48 6q-63 13-104 62t-41 115v2q38-21 82-23q-37 25-59 64t-22 86q0 49 25 91q68-83 164-133t208-55q-5 21-5 41q0 75 53 127t127 53q79 0 132-57q61 12 114 44q-20-64-79-100q52 6 104 28z" horiz-adv-x="928.6" />
<glyph glyph-name="flattr" unicode="&#xe803;" d="m180 424l0-210l-180-180l0 414q0 302 278 302l442 0l-312-310q-6-6-10-6q-8 0-12 10l0 128q-98 0-112-2q-94-16-94-146z m440 64l180 180l0-414q0-304-278-304l-440 0l312 312q2 6 8 6q8 0 12-10l0-128q98 0 112 2q94 16 94 146l0 210z" horiz-adv-x="800" />
<glyph glyph-name="twitter" unicode="&#xe800;" d="m904 622q-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81 19-3 43-3 126 0 224 77-59 2-105 36t-64 89q19-2 34-2 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 68-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q79 0 132-57 61 12 114 44-20-64-79-100 52 6 104 28z" horiz-adv-x="928.6" />
<glyph glyph-name="github-circled" unicode="&#xe801;" d="m857 350q0-140-82-252t-211-155q-15-3-22 4t-7 17v118q0 54-29 79 32 3 57 10t53 22 45 37 30 58 11 84q0 68-44 115 21 51-5 114-15 5-45-6t-51-25l-21-13q-52 15-107 15t-108-15q-8 6-23 15t-47 22-48 7q-24-63-4-114-44-47-44-115 0-47 12-83t29-59 45-37 52-22 57-10q-22-20-27-58-12-5-25-8t-32-3-36 12-31 35q-11 18-27 29t-28 14l-11 1q-12 0-16-2t-3-7 5-8 7-6l4-3q12-6 24-21t18-29l5-13q8-21 25-34t37-17 39-4 31 2l13 3q0-22 0-50t1-30q0-10-8-17t-22-4q-129 43-211 155t-82 252q0 117 58 215t155 156 216 58 215-58 156-156 57-215z" horiz-adv-x="857.1" />
<glyph glyph-name="flattr" unicode="&#xe802;" d="m0-37l0 514q0 179 85 278t259 99l548 0q-5-5-52-53t-100-101-109-109-95-93-42-37q-15 0-15 16l0 156-48 0q-59 0-94-6t-63-26-39-57-12-96l0-262z m67-117q5 5 53 53t100 101 109 110 95 93 41 36q15 0 15-16l0-156 48 0q116 0 162 36t45 149l0 262 224 223 0-514q0-179-84-278t-260-99l-548 0z" horiz-adv-x="959" />
<glyph glyph-name="bitcoin" unicode="&#xe803;" d="m651 493q10-102-73-144 65-16 98-58t25-119q-4-40-18-70t-36-49-54-33-68-19-81-9v-142h-86v140q-45 0-68 1v-141h-86v142q-10 0-30 1t-31 0h-112l18 102h62q27 0 32 28v225h9q-4 0-9 0v160q-7 38-50 38h-62v92l119-1q35 0 54 1v141h86v-138q45 1 68 1v137h86v-141q44-4 78-13t63-25 46-43 20-64z m-120-304q0 20-8 35t-21 26-32 17-36 10-42 5-38 2-36 0-27-1v-189q5 0 21 0t27 0 29 1 33 2 32 5 31 8 26 11 22 17 14 22 5 29z m-39 265q0 19-7 33t-17 23-27 16-31 9-34 5-33 1-30 0-22-1v-171q3 0 20 0t26 0 27 1 31 3 29 6 27 10 21 15 15 22 5 28z" horiz-adv-x="714.3" />
<glyph glyph-name="trash" unicode="&#xe804;" d="m286 439v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m143 0v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m142 0v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q7 0 12-5t5-13z m72-404v529h-500v-529q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22z m-375 601h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q22 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
<glyph glyph-name="download" unicode="&#xe805;" d="m714 100q0 15-10 25t-25 11-26-11-10-25 10-25 26-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-40l-250-250q-10-10-25-10t-25 10l-250 250q-17 17-8 40 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
<glyph glyph-name="spinner" unicode="&#xe806;" d="m469 614v204q129 0 237-61t169-170 62-237h-204q0 72-36 133t-95 96-133 35z" horiz-adv-x="937.5" />
<glyph glyph-name="eye" unicode="&#xe807;" d="m929 314q-85 132-213 197 34-58 34-125 0-104-73-177t-177-73-177 73-73 177q0 67 34 125-128-65-213-197 75-114 187-182t242-68 242 68 187 182z m-402 215q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-12 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m473-215q0-19-11-38-78-129-210-206t-279-77-279 77-210 206q-11 19-11 38t11 39q78 128 210 205t279 78 279-78 210-205q11-20 11-39z" horiz-adv-x="1000" />
</font>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.
Binary file not shown.
+21 -7
View File
@@ -11,15 +11,25 @@
<div>
<strong><%= stash('filename') %></strong>
<ul class="list-unstyled">
<li><i class="icon icon-eye" title="<%=l 'view-link' %>"></i> <%= link_to url_for('/')->to_abs().stash('short') => begin %><%= url_for('/')->to_abs().stash('short') %><%= end %></li>
<li><i class="icon icon-download" title="<%=l 'download-link' %>"></i> <%= link_to url_for('/')->to_abs().stash('short').'?dl' => begin %><%= url_for('/')->to_abs().stash('short').'?dl' %><%= end %></li>
<li><i class="icon icon-touiteur" title="<%=l 'twitter-link' %>"></i> <%= link_to url_for('/')->to_abs().stash('short').'?t' => begin %><%= url_for('/')->to_abs().stash('short').'?t' %><%= end %></li>
% my $url = url_for('/')->to_abs().stash('short');
% my $delete_url = url_for('delete', {short => stash('real_short'), token => stash('token')})->to_abs();
<li><i class="icon icon-eye" title =" <%= l 'view-link' %>"></i> <%= link_to $url => begin %> <%= $url %> <%= end %></li>
<li><i class="icon icon-download" title =" <%= l 'download-link' %>"></i> <%= link_to $url.'?dl' => begin %> <%= $url.'?dl' %> <%= end %></li>
<li><i class="icon icon-twitter" title =" <%= l 'twitter-link' %>"></i> <%= link_to $url.'?t' => begin %> <%= $url.'?t' %> <%= end %></li>
<li><i class="icon icon-trash" title =" <%= l 'delete-link' %>"></i> <%= link_to $delete_url => begin %> <%= $delete_url %> <%= end %></li>
</ul>
</div>
</div>
% }
% if (defined(flash('success'))) {
<div class="alert alert-success">
<button type="button" class="close jsonly" data-dismiss="alert" aria-hidden="true">&times;</button>
<%= flash('success') %>
</div>
% }
% if (defined(flash('msg'))) {
<div class="alert alert-danger">
<button type="button" class="close jsonly" data-dismiss="alert" aria-hidden="true">&times;</button>
<strong><%=l 'some-bad' %></strong><br>
<%= flash('filename') %> <%= flash('msg') %>
</div>
@@ -129,8 +139,10 @@
<!-- /D&D Zone -->
%= javascript begin
function link(url, dl) {
if (dl !== '') {
function link(url, dl, token) {
if (token !== undefined) {
url = 'd/'+url+'/'+token;
} else if (dl !== '') {
url = url+'?'+dl;
}
return '<a href="<%== url_for('index')->to_abs() %>'+url+'"><%== url_for('index')->to_abs() %>'+url+'</a>';
@@ -145,10 +157,12 @@
+'</strong>'
+'<ul class="list-unstyled"><li><i class="icon icon-eye" title="<%=l 'view-link' %>"></i>&nbsp;'
+link(msg.short, '')
+'</a></li><li><i class="icon icon-download" title="<%=l 'download-link' %>"></i>&nbsp;'
+'</li><li><i class="icon icon-download" title="<%=l 'download-link' %>"></i>&nbsp;'
+link(msg.short, 'dl')
+'</a></li><li><i class="icon icon-touiteur" title="<%=l 'twitter-link' %>"></i>&nbsp;'
+'</li><li><i class="icon icon-twitter" title="<%=l 'twitter-link' %>"></i>&nbsp;'
+link(msg.short, 't')
+'</li><li><i class="icon icon-trash" title="<%=l 'delete-link' %>"></i>&nbsp;'
+link(msg.real_short, '', msg.token)
+'</li></ul></div>';
} else {
return '<div class="alert alert-danger"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button><strong><%=l 'some-bad' %></strong><br>'