diff --git a/Lstu b/Lstu deleted file mode 100755 index 508ae8879b949be2e7c8654fd8522f7f1afb6bb1..0000000000000000000000000000000000000000 --- a/Lstu +++ /dev/null @@ -1,429 +0,0 @@ -#!/usr/bin/env perl -package Model; - -# Create database -use ORLite { - file => 'lstu.db', - unicode => 1, - create => sub { - my $dbh = shift; - $dbh->do( - 'CREATE TABLE lstu ( - short TEXT PRIMARY KEY, - url TEXT, - counter INTEGER, - timestamp INTEGER)' - ); - return 1; - } -}; - -package Lstu; -use Mojolicious::Lite; -use Mojolicious::Plugin::DefaultHelpers; -use Data::Validate::URI qw(is_uri); - -my $config = plugin 'Config'; - -# Default values -$config->{provisionning} = 100 unless (defined($config->{provisionning})); -$config->{provis_step} = 5 unless (defined($config->{provis_step})); -$config->{length} = 8 unless (defined($config->{length})); -$config->{secret} = 'hfudsifdsih' unless (defined($config->{secret})); - -app->secret($config->{secret}); - -app->helper( - provisionning => sub { - my $c = shift; - - # Create some short patterns for provisionning - if (Model::Lstu->count('WHERE url IS NULL') < $c->config->{provisionning}) { - for (my $i = 0; $i < $c->config->{provis_step}; $i++) { - my $short; - do { - $short= $c->shortener($c->config->{length}); - } while (Model::Lstu->count('WHERE short = ?', $short)); - - Model::Lstu->create( - short => $short - ); - } - } - } -); - -app->helper( - shortener => sub { - my $c = shift; - my $length = shift; - - my @chars = ('a'..'z','A'..'Z','0'..'9'); - my $result = ''; - foreach (1..$length) { - $result .= $chars[rand scalar(@chars)]; - } - return $result; - } -); - -# For the first launch (after, this isn't really useful) -app->provisionning(); - -get '/' => sub { - my $c = shift; - - $c->render(template => 'index'); - - # Check provisionning - $c->on(finish => sub { - shift->provisionning(); - }); -} => 'index'; - -get '/:short' => sub { - my $c = shift; - my $short = $c->param('short'); - - my @urls = Model::Lstu->select('WHERE short = ?', $short); - if (scalar(@urls)) { - $c->res->code(301); - $c->redirect_to($urls[0]->url); - - # Update counter and check provisionning - $c->on(finish => sub { - my $counter = $urls[0]->counter + 1; - $urls[0]->update (counter => $counter); - - shift->provisionning(); - }); - } else { - $c->flash( - msg => $c->url_for('/')->to_abs.$short.' not found.' - ); - $c->redirect_to('/'); - } -} => 'short'; - -my $add = sub { - my $c = shift; - my $url = $c->param('lsturl'); - - if (is_uri($url)) { - my $short; - - my @keys = $c->param; - my @params; - foreach my $key (sort @keys) { - push @params, $key.'='.$c->param($key) unless ($key eq 'lsturl'); - } - $url .= '?'.join('&', @params) if (scalar(@params)); - - my @records = Model::Lstu->select('WHERE url = ?', $url); - - if (scalar(@records)) { - $c->flash( - short => $records[0]->short, - url => $url - ); - } else { - @records = Model::Lstu->select('WHERE url IS NULL LIMIT 1'); - if (scalar(@records)) { - $records[0]->update( - url => $url, - counter => 0, - timestamp => time() - ); - - $c->flash( - short => $records[0]->short, - url => $url - ); - } else { - $c->flash( - msg => 'No shortened URL available. Please retry or contact the administrator at '.$c->config->{contact} - ); - } - } - } else { - $c->flash( - msg => $url.' is not a valid URL' - ); - } - $c->redirect_to('/'); - - # Check provisionning - $c->on(finish => sub { - shift->provisionning(); - }); -}; - -post '/a/' => $add => 'add' ; - -get '/a/*lsturl' => $add => 'addurl'; - -return app->start; - -1; -__DATA__ - -@@ index.html.ep -% layout 'default'; -% title 'Lstu'; -

Let's Shorten That Url

-

© 2013 <%= link_to 'http://www.fiat-tux.fr' => begin %>Luc Didry<% end %> — License : <%= link_to 'http://www.wtfpl.net/' => begin %>WTFPL<% end %> — <%= link_to 'https://github.com/ldidry/lstu' => begin %>About<% end %>

-
-
- - -
- <%= submit_button 'Go', class => 'btn btn-default btn-primary' %> -
- -% if (defined(flash('short')) && defined(flash('url'))) { -

- <%= link_to flash('url') => begin %><%== flash('url') %><%= end %> => - <%= link_to url_for('/')->to_abs.flash('short') => begin %><%= url_for('/')->to_abs.flash('short') %><%= end %> -

-% } -% if (defined(flash('msg'))) { -

<%== flash('msg') %>

-% } - -@@ layouts/default.html.ep - - - - <%= title %> - - %= stylesheet begin - /*! - * Bootstrap v3.0.0 - * - * Copyright 2013 Twitter, Inc - * Licensed under the Apache License v2.0 - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Designed and built with all the love in the world @twitter by @mdo and @fat. - */ - article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;} - audio,canvas,video{display:inline-block;} - audio:not([controls]){display:none;height:0;} - [hidden]{display:none;} - html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;} - body{margin:0;} - a:focus{outline:thin dotted;} - a:active,a:hover{outline:0;} - h1{font-size:2em;margin:0.67em 0;} - abbr[title]{border-bottom:1px dotted;} - b,strong{font-weight:bold;} - dfn{font-style:italic;} - hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;} - mark{background:#ff0;color:#000;} - code,kbd,pre,samp{font-family:monospace, serif;font-size:1em;} - pre{white-space:pre-wrap;} - q{quotes:"\201C" "\201D" "\2018" "\2019";} - small{font-size:80%;} - sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;} - sup{top:-0.5em;} - sub{bottom:-0.25em;} - img{border:0;} - svg:not(:root){overflow:hidden;} - figure{margin:0;} - fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;} - legend{border:0;padding:0;} - button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;} - button,input{line-height:normal;} - button,select{text-transform:none;} - button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;} - button[disabled],html input[disabled]{cursor:default;} - input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;} - input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;} - input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;} - button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;} - textarea{overflow:auto;vertical-align:top;} - table{border-collapse:collapse;border-spacing:0;} - *,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} - html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);} - body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333333;background-color:#ffffff;} - input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;} - button,input,select[multiple],textarea{background-image:none;} - a{color:#428bca;text-decoration:none;}a:hover,a:focus{color:#2a6496;text-decoration:underline;} - a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} - img{vertical-align:middle;} - .img-responsive{display:block;max-width:100%;height:auto;} - .img-rounded{border-radius:6px;} - .img-thumbnail{padding:4px;line-height:1.428571429;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;display:inline-block;max-width:100%;height:auto;} - .img-circle{border-radius:50%;} - hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee;} - .sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);border:0;} - p{margin:0 0 10px;} - .lead{margin-bottom:20px;font-size:16.099999999999998px;font-weight:200;line-height:1.4;}@media (min-width:768px){.lead{font-size:21px;}} - small{font-size:85%;} - cite{font-style:normal;} - .text-muted{color:#999999;} - .text-primary{color:#428bca;} - .text-warning{color:#c09853;} - .text-danger{color:#b94a48;} - .text-success{color:#468847;} - .text-info{color:#3a87ad;} - .text-left{text-align:left;} - .text-right{text-align:right;} - .text-center{text-align:center;} - h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small{font-weight:normal;line-height:1;color:#999999;} - h1,h2,h3{margin-top:20px;margin-bottom:10px;} - h4,h5,h6{margin-top:10px;margin-bottom:10px;} - h1,.h1{font-size:36px;} - h2,.h2{font-size:30px;} - h3,.h3{font-size:24px;} - h4,.h4{font-size:18px;} - h5,.h5{font-size:14px;} - h6,.h6{font-size:12px;} - h1 small,.h1 small{font-size:24px;} - h2 small,.h2 small{font-size:18px;} - h3 small,.h3 small,h4 small,.h4 small{font-size:14px;} - .page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee;} - ul,ol{margin-top:0;margin-bottom:10px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:0;} - .list-unstyled{padding-left:0;list-style:none;} - .list-inline{padding-left:0;list-style:none;}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px;} - dl{margin-bottom:20px;} - dt,dd{line-height:1.428571429;} - dt{font-weight:bold;} - dd{margin-left:0;} - @media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;} .dl-horizontal dd{margin-left:180px;}.dl-horizontal dd:before,.dl-horizontal dd:after{content:" ";display:table;} .dl-horizontal dd:after{clear:both;}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999;} - abbr.initialism{font-size:90%;text-transform:uppercase;} - blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eeeeee;}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25;} - blockquote p:last-child{margin-bottom:0;} - blockquote small{display:block;line-height:1.428571429;color:#999999;}blockquote small:before{content:'\2014 \00A0';} - blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;} - blockquote.pull-right small:before{content:'';} - blockquote.pull-right small:after{content:'\00A0 \2014';} - q:before,q:after,blockquote:before,blockquote:after{content:"";} - address{display:block;margin-bottom:20px;font-style:normal;line-height:1.428571429;} - .container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px;}.container:before,.container:after{content:" ";display:table;} - .container:after{clear:both;} - .row{margin-left:-15px;margin-right:-15px;}.row:before,.row:after{content:" ";display:table;} - .row:after{clear:both;} - .col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px;} - .col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left;} - .col-xs-1{width:8.333333333333332%;} - .col-xs-2{width:16.666666666666664%;} - .col-xs-3{width:25%;} - .col-xs-4{width:33.33333333333333%;} - .col-xs-5{width:41.66666666666667%;} - .col-xs-6{width:50%;} - .col-xs-7{width:58.333333333333336%;} - .col-xs-8{width:66.66666666666666%;} - .col-xs-9{width:75%;} - .col-xs-10{width:83.33333333333334%;} - .col-xs-11{width:91.66666666666666%;} - .col-xs-12{width:100%;} - @media (min-width:768px){.container{max-width:750px;} .col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11{float:left;} .col-sm-1{width:8.333333333333332%;} .col-sm-2{width:16.666666666666664%;} .col-sm-3{width:25%;} .col-sm-4{width:33.33333333333333%;} .col-sm-5{width:41.66666666666667%;} .col-sm-6{width:50%;} .col-sm-7{width:58.333333333333336%;} .col-sm-8{width:66.66666666666666%;} .col-sm-9{width:75%;} .col-sm-10{width:83.33333333333334%;} .col-sm-11{width:91.66666666666666%;} .col-sm-12{width:100%;} .col-sm-push-1{left:8.333333333333332%;} .col-sm-push-2{left:16.666666666666664%;} .col-sm-push-3{left:25%;} .col-sm-push-4{left:33.33333333333333%;} .col-sm-push-5{left:41.66666666666667%;} .col-sm-push-6{left:50%;} .col-sm-push-7{left:58.333333333333336%;} .col-sm-push-8{left:66.66666666666666%;} .col-sm-push-9{left:75%;} .col-sm-push-10{left:83.33333333333334%;} .col-sm-push-11{left:91.66666666666666%;} .col-sm-pull-1{right:8.333333333333332%;} .col-sm-pull-2{right:16.666666666666664%;} .col-sm-pull-3{right:25%;} .col-sm-pull-4{right:33.33333333333333%;} .col-sm-pull-5{right:41.66666666666667%;} .col-sm-pull-6{right:50%;} .col-sm-pull-7{right:58.333333333333336%;} .col-sm-pull-8{right:66.66666666666666%;} .col-sm-pull-9{right:75%;} .col-sm-pull-10{right:83.33333333333334%;} .col-sm-pull-11{right:91.66666666666666%;} .col-sm-offset-1{margin-left:8.333333333333332%;} .col-sm-offset-2{margin-left:16.666666666666664%;} .col-sm-offset-3{margin-left:25%;} .col-sm-offset-4{margin-left:33.33333333333333%;} .col-sm-offset-5{margin-left:41.66666666666667%;} .col-sm-offset-6{margin-left:50%;} .col-sm-offset-7{margin-left:58.333333333333336%;} .col-sm-offset-8{margin-left:66.66666666666666%;} .col-sm-offset-9{margin-left:75%;} .col-sm-offset-10{margin-left:83.33333333333334%;} .col-sm-offset-11{margin-left:91.66666666666666%;}}@media (min-width:992px){.container{max-width:970px;} .col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11{float:left;} .col-md-1{width:8.333333333333332%;} .col-md-2{width:16.666666666666664%;} .col-md-3{width:25%;} .col-md-4{width:33.33333333333333%;} .col-md-5{width:41.66666666666667%;} .col-md-6{width:50%;} .col-md-7{width:58.333333333333336%;} .col-md-8{width:66.66666666666666%;} .col-md-9{width:75%;} .col-md-10{width:83.33333333333334%;} .col-md-11{width:91.66666666666666%;} .col-md-12{width:100%;} .col-md-push-0{left:auto;} .col-md-push-1{left:8.333333333333332%;} .col-md-push-2{left:16.666666666666664%;} .col-md-push-3{left:25%;} .col-md-push-4{left:33.33333333333333%;} .col-md-push-5{left:41.66666666666667%;} .col-md-push-6{left:50%;} .col-md-push-7{left:58.333333333333336%;} .col-md-push-8{left:66.66666666666666%;} .col-md-push-9{left:75%;} .col-md-push-10{left:83.33333333333334%;} .col-md-push-11{left:91.66666666666666%;} .col-md-pull-0{right:auto;} .col-md-pull-1{right:8.333333333333332%;} .col-md-pull-2{right:16.666666666666664%;} .col-md-pull-3{right:25%;} .col-md-pull-4{right:33.33333333333333%;} .col-md-pull-5{right:41.66666666666667%;} .col-md-pull-6{right:50%;} .col-md-pull-7{right:58.333333333333336%;} .col-md-pull-8{right:66.66666666666666%;} .col-md-pull-9{right:75%;} .col-md-pull-10{right:83.33333333333334%;} .col-md-pull-11{right:91.66666666666666%;} .col-md-offset-0{margin-left:0;} .col-md-offset-1{margin-left:8.333333333333332%;} .col-md-offset-2{margin-left:16.666666666666664%;} .col-md-offset-3{margin-left:25%;} .col-md-offset-4{margin-left:33.33333333333333%;} .col-md-offset-5{margin-left:41.66666666666667%;} .col-md-offset-6{margin-left:50%;} .col-md-offset-7{margin-left:58.333333333333336%;} .col-md-offset-8{margin-left:66.66666666666666%;} .col-md-offset-9{margin-left:75%;} .col-md-offset-10{margin-left:83.33333333333334%;} .col-md-offset-11{margin-left:91.66666666666666%;}}@media (min-width:1200px){.container{max-width:1170px;} .col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11{float:left;} .col-lg-1{width:8.333333333333332%;} .col-lg-2{width:16.666666666666664%;} .col-lg-3{width:25%;} .col-lg-4{width:33.33333333333333%;} .col-lg-5{width:41.66666666666667%;} .col-lg-6{width:50%;} .col-lg-7{width:58.333333333333336%;} .col-lg-8{width:66.66666666666666%;} .col-lg-9{width:75%;} .col-lg-10{width:83.33333333333334%;} .col-lg-11{width:91.66666666666666%;} .col-lg-12{width:100%;} .col-lg-push-0{left:auto;} .col-lg-push-1{left:8.333333333333332%;} .col-lg-push-2{left:16.666666666666664%;} .col-lg-push-3{left:25%;} .col-lg-push-4{left:33.33333333333333%;} .col-lg-push-5{left:41.66666666666667%;} .col-lg-push-6{left:50%;} .col-lg-push-7{left:58.333333333333336%;} .col-lg-push-8{left:66.66666666666666%;} .col-lg-push-9{left:75%;} .col-lg-push-10{left:83.33333333333334%;} .col-lg-push-11{left:91.66666666666666%;} .col-lg-pull-0{right:auto;} .col-lg-pull-1{right:8.333333333333332%;} .col-lg-pull-2{right:16.666666666666664%;} .col-lg-pull-3{right:25%;} .col-lg-pull-4{right:33.33333333333333%;} .col-lg-pull-5{right:41.66666666666667%;} .col-lg-pull-6{right:50%;} .col-lg-pull-7{right:58.333333333333336%;} .col-lg-pull-8{right:66.66666666666666%;} .col-lg-pull-9{right:75%;} .col-lg-pull-10{right:83.33333333333334%;} .col-lg-pull-11{right:91.66666666666666%;} .col-lg-offset-0{margin-left:0;} .col-lg-offset-1{margin-left:8.333333333333332%;} .col-lg-offset-2{margin-left:16.666666666666664%;} .col-lg-offset-3{margin-left:25%;} .col-lg-offset-4{margin-left:33.33333333333333%;} .col-lg-offset-5{margin-left:41.66666666666667%;} .col-lg-offset-6{margin-left:50%;} .col-lg-offset-7{margin-left:58.333333333333336%;} .col-lg-offset-8{margin-left:66.66666666666666%;} .col-lg-offset-9{margin-left:75%;} .col-lg-offset-10{margin-left:83.33333333333334%;} .col-lg-offset-11{margin-left:91.66666666666666%;}}fieldset{padding:0;margin:0;border:0;} - legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333333;border:0;border-bottom:1px solid #e5e5e5;} - label{display:inline-block;margin-bottom:5px;font-weight:bold;} - input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} - input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal;} - input[type="file"]{display:block;} - select[multiple],select[size]{height:auto;} - select optgroup{font-size:inherit;font-style:inherit;font-family:inherit;} - input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} - input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto;} - .form-control:-moz-placeholder{color:#999999;} - .form-control::-moz-placeholder{color:#999999;} - .form-control:-ms-input-placeholder{color:#999999;} - .form-control::-webkit-input-placeholder{color:#999999;} - .form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555555;vertical-align:middle;background-color:#ffffff;border:1px solid #cccccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);} - .form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eeeeee;} - textarea.form-control{height:auto;} - .form-group{margin-bottom:15px;} - .radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px;vertical-align:middle;}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer;} - .radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px;} - .radio+.radio,.checkbox+.checkbox{margin-top:-5px;} - .radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer;} - .radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px;} - input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed;} - .input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;}select.input-sm{height:30px;line-height:30px;} - textarea.input-sm{height:auto;} - .input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px;}select.input-lg{height:45px;line-height:45px;} - textarea.input-lg{height:auto;} - .has-warning .help-block,.has-warning .control-label{color:#c09853;} - .has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;} - .has-warning .input-group-addon{color:#c09853;border-color:#c09853;background-color:#fcf8e3;} - .has-error .help-block,.has-error .control-label{color:#b94a48;} - .has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;} - .has-error .input-group-addon{color:#b94a48;border-color:#b94a48;background-color:#f2dede;} - .has-success .help-block,.has-success .control-label{color:#468847;} - .has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;} - .has-success .input-group-addon{color:#468847;border-color:#468847;background-color:#dff0d8;} - .form-control-static{margin-bottom:0;padding-top:7px;} - .help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373;} - @media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle;} .form-inline .form-control{display:inline-block;} .form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;} .form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0;}} - .form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px;} - .form-horizontal .form-group{margin-left:-15px;margin-right:-15px;}.form-horizontal .form-group:before,.form-horizontal .form-group:after{content:" ";display:table;} - .form-horizontal .form-group:after{clear:both;} - @media (min-width:768px){.form-horizontal .control-label{text-align:right;}} - .btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:4px;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} - .btn:hover,.btn:focus{color:#333333;text-decoration:none;} - .btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);} - .btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;} - .btn-default{color:#333333;background-color:#ffffff;border-color:#cccccc;}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333333;background-color:#ebebeb;border-color:#adadad;} - .btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none;} - .btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#ffffff;border-color:#cccccc;} - .btn-primary{color:#ffffff;background-color:#428bca;border-color:#357ebd;}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#ffffff;background-color:#3276b1;border-color:#285e8e;} - .btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none;} - .btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd;} - .btn-warning{color:#ffffff;background-color:#f0ad4e;border-color:#eea236;}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#ffffff;background-color:#ed9c28;border-color:#d58512;} - .btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none;} - .btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236;} - .btn-danger{color:#ffffff;background-color:#d9534f;border-color:#d43f3a;}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#ffffff;background-color:#d2322d;border-color:#ac2925;} - .btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none;} - .btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a;} - .btn-success{color:#ffffff;background-color:#5cb85c;border-color:#4cae4c;}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#ffffff;background-color:#47a447;border-color:#398439;} - .btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none;} - .btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c;} - .btn-info{color:#ffffff;background-color:#5bc0de;border-color:#46b8da;}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#ffffff;background-color:#39b3d7;border-color:#269abc;} - .btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none;} - .btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da;} - .btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0;}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none;} - .btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent;} - .btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent;} - .btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none;} - .btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px;} - .btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;} - .btn-xs{padding:1px 5px;} - .btn-block{display:block;width:100%;padding-left:0;padding-right:0;} - .btn-block+.btn-block{margin-top:5px;} - input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;} - .alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px;}.alert h4{margin-top:0;color:inherit;} - .alert .alert-link{font-weight:bold;} - .alert>p,.alert>ul{margin-bottom:0;} - .alert>p+p{margin-top:5px;} - .alert-dismissable{padding-right:35px;}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit;} - .alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847;}.alert-success hr{border-top-color:#c9e2b3;} - .alert-success .alert-link{color:#356635;} - .alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad;}.alert-info hr{border-top-color:#a6e1ec;} - .alert-info .alert-link{color:#2d6987;} - .alert-warning{background-color:#fcf8e3;border-color:#fbeed5;color:#c09853;}.alert-warning hr{border-top-color:#f8e5be;} - .alert-warning .alert-link{color:#a47e3c;} - .alert-danger{background-color:#f2dede;border-color:#eed3d7;color:#b94a48;}.alert-danger hr{border-top-color:#e6c1c7;} - .alert-danger .alert-link{color:#953b39;} - % end - %= stylesheet begin - body { - padding-top: 40px; - padding-bottom: 40px; - background-color: #eee; - } - - .container { - padding: 15px; - margin: 0 auto; - } - % end - - -
- <%= content %> -
- - diff --git a/cpanfile b/cpanfile index 1381734c42fa5063bed4f4863e894655d842787d..4b7e58244122bed891cb8e76ca43f35a42a1bd1e 100644 --- a/cpanfile +++ b/cpanfile @@ -1,3 +1,4 @@ requires 'Mojolicious'; requires 'ORLite'; requires 'Data::Validate::URI'; +requires 'Mojolicious::Plugin::I18N'; diff --git a/cpanfile.snapshot b/cpanfile.snapshot index 3cfec3f29307da96d21eda9d5d98859bc76057ce..5d55a9ada7316e593aa72ecdda79ccbf03a503fe 100644 --- a/cpanfile.snapshot +++ b/cpanfile.snapshot @@ -264,6 +264,16 @@ DISTRIBUTIONS ojo undef requirements: ExtUtils::MakeMaker 0 + Mojolicious-Plugin-I18N-1.0 + pathname: S/SH/SHARIFULN/Mojolicious-Plugin-I18N-1.0.tar.gz + provides: + Mojolicious::Plugin::I18N 1.0 + requirements: + I18N::LangTags 0.35 + Module::Build 0.36 + Mojolicious 3 + Test::More 0 + perl 5.010001 Net-Domain-TLD-1.70 pathname: A/AL/ALEXP/Net-Domain-TLD-1.70.tar.gz provides: diff --git a/lib/Lstu.pm b/lib/Lstu.pm new file mode 100644 index 0000000000000000000000000000000000000000..1e5c052d07d83d75894b4f15a27fe75f46546b45 --- /dev/null +++ b/lib/Lstu.pm @@ -0,0 +1,159 @@ +package Lstu; +use Mojo::Base 'Mojolicious'; +use LstuModel; +use Data::Validate::URI qw(is_uri); + +# This method will run once at server start +sub startup { + my $self = shift; + + my $config = $self->plugin('Config'); + + # Default values + $config->{provisionning} = 100 unless (defined($config->{provisionning})); + $config->{provis_step} = 5 unless (defined($config->{provis_step})); + $config->{length} = 8 unless (defined($config->{length})); + $config->{secret} = 'hfudsifdsih' unless (defined($config->{secret})); + + $self->plugin('I18N'); + + $self->secret($config->{secret}); + + $self->helper( + provisionning => sub { + my $c = shift; + + # Create some short patterns for provisionning + if (LstuModel::Lstu->count('WHERE url IS NULL') < $c->config->{provisionning}) { + for (my $i = 0; $i < $c->config->{provis_step}; $i++) { + my $short; + do { + $short= $c->shortener($c->config->{length}); + } while (LstuModel::Lstu->count('WHERE short = ?', $short)); + + LstuModel::Lstu->create( + short => $short + ); + } + } + } + ); + + $self->helper( + shortener => sub { + my $c = shift; + my $length = shift; + + my @chars = ('a'..'z','A'..'Z','0'..'9'); + my $result = ''; + foreach (1..$length) { + $result .= $chars[rand scalar(@chars)]; + } + return $result; + } + ); + + # For the first launch (after, this isn't really useful) + $self->provisionning(); + + # Router + my $r = $self->routes; + + # Normal route to controller + $r->get('/' => sub { + my $c = shift; + + $c->render(template => 'index'); + + # Check provisionning + $c->on(finish => sub { + shift->provisionning(); + }); + })->name('index'); + + $r->get('/:short' => sub { + my $c = shift; + my $short = $c->param('short'); + + my @urls = LstuModel::Lstu->select('WHERE short = ?', $short); + if (scalar(@urls)) { + $c->res->code(301); + $c->redirect_to($urls[0]->url); + + # Update counter and check provisionning + $c->on(finish => sub { + my $counter = $urls[0]->counter + 1; + $urls[0]->update (counter => $counter); + + shift->provisionning(); + }); + } else { + $c->flash( + msg => $c->l('url_not_found', $c->url_for('/')->to_abs.$short) + ); + $c->redirect_to('/'); + } + })->name('short'); + + my $add = sub { + my $c = shift; + my $url = $c->param('lsturl'); + + if (is_uri($url)) { + my $short; + + my @keys = $c->param; + my @params; + foreach my $key (sort @keys) { + push @params, $key.'='.$c->param($key) unless ($key eq 'lsturl'); + } + $url .= '?'.join('&', @params) if (scalar(@params)); + + my @records = LstuModel::Lstu->select('WHERE url = ?', $url); + + if (scalar(@records)) { + # Already got this URL + $c->flash( + short => $records[0]->short, + url => $url + ); + } else { + @records = LstuModel::Lstu->select('WHERE url IS NULL LIMIT 1'); + if (scalar(@records)) { + $records[0]->update( + url => $url, + counter => 0, + timestamp => time() + ); + + $c->flash( + short => $records[0]->short, + url => $url + ); + } else { + # Houston, we have a problem + $c->flash( + msg => $c->l('no_more_short', $c->config->{contact}, $url) + ); + } + } + } else { + $c->app->log->debug($c->l('no_valid_url', $url)); + $c->flash( + msg => $c->l('no_valid_url', $url) + ); + } + $c->redirect_to('/'); + + # Check provisionning + $c->on(finish => sub { + shift->provisionning(); + }); + }; + + $r->post('/a/' => $add)->name('add'); + + $r->get('/a/*lsturl' => $add)->name('addurl'); +} + +1; diff --git a/lib/Lstu/I18N/en.pm b/lib/Lstu/I18N/en.pm new file mode 100644 index 0000000000000000000000000000000000000000..534759cfc716a6d2d6eae1bb2101d781454d7860 --- /dev/null +++ b/lib/Lstu/I18N/en.pm @@ -0,0 +1,14 @@ +package Lstu::I18N::en; +use Mojo::Base 'Lstu::I18N'; + +our %Lexicon = ( + 'about' => 'About', + 'go' => 'Go !', + 'license' => 'License:', + 'no_more_short' => 'No shortened URL available. Please retry or contact the administrator at [_1]. Your URL to shorten: [_2]', + 'no_valid_url' => '[_1] is not a valid URL.', + 'url_not_found' => 'The shortened URL [_1] doesn\'t exist.', + 'url_to_shorten' => 'URL to shorten', +); + +1; diff --git a/lib/Lstu/I18N/fr.pm b/lib/Lstu/I18N/fr.pm new file mode 100644 index 0000000000000000000000000000000000000000..2b8ba49500fd1b2a59502a90392f2c90f305f017 --- /dev/null +++ b/lib/Lstu/I18N/fr.pm @@ -0,0 +1,14 @@ +package Lstu::I18N::fr; +use Mojo::Base 'Lstu::I18N'; + +our %Lexicon = ( + 'about' => 'À propos', + 'go' => 'Allons-y !', + 'license' => 'Licence : ', + 'no_more_short' => 'Il n\'y a plus d\'URL raccourcie disponible. Veuillez réessayer ou contactez l\'administrateur sur [_1]. Rappel de l\'URL à raccourcir : [_2]', + 'no_valid_url' => '[_1] n\'est pas une URL valide.', + 'url_not_found' => 'L\'URL raccourcie [_1] n\'existe pas.', + 'url_to_shorten' => 'URL à raccourcir', +); + +1; diff --git a/lib/LstuModel.pm b/lib/LstuModel.pm new file mode 100644 index 0000000000000000000000000000000000000000..2cc651d1dae82ee590b0866a0908557a8721c927 --- /dev/null +++ b/lib/LstuModel.pm @@ -0,0 +1,20 @@ +package LstuModel; + +# Create database +use ORLite { + file => 'lstu.db', + unicode => 1, + create => sub { + my $dbh = shift; + $dbh->do( + 'CREATE TABLE lstu ( + short TEXT PRIMARY KEY, + url TEXT, + counter INTEGER, + timestamp INTEGER)' + ); + return 1; + } +}; + +1; diff --git a/Lstu.conf b/lstu.conf similarity index 100% rename from Lstu.conf rename to lstu.conf diff --git a/public/css/bootstrap.min.css b/public/css/bootstrap.min.css new file mode 100644 index 0000000000000000000000000000000000000000..f9ee36daefc4ae90136a7758ebfc5a8ea1f725af --- /dev/null +++ b/public/css/bootstrap.min.css @@ -0,0 +1,210 @@ +/*! +* Bootstrap v3.0.0 +* +* Copyright 2013 Twitter, Inc +* Licensed under the Apache License v2.0 +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Designed and built with all the love in the world @twitter by @mdo and @fat. +*/ +article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;} +audio,canvas,video{display:inline-block;} +audio:not([controls]){display:none;height:0;} +[hidden]{display:none;} +html{font-family:sans-serif;-webkit-text-size-adjust:100%;-ms-text-size-adjust:100%;} +body{margin:0;} +a:focus{outline:thin dotted;} +a:active,a:hover{outline:0;} +h1{font-size:2em;margin:0.67em 0;} +abbr[title]{border-bottom:1px dotted;} +b,strong{font-weight:bold;} +dfn{font-style:italic;} +hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;} +mark{background:#ff0;color:#000;} +code,kbd,pre,samp{font-family:monospace, serif;font-size:1em;} +pre{white-space:pre-wrap;} +q{quotes:"\201C" "\201D" "\2018" "\2019";} +small{font-size:80%;} +sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;} +sup{top:-0.5em;} +sub{bottom:-0.25em;} +img{border:0;} +svg:not(:root){overflow:hidden;} +figure{margin:0;} +fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;} +legend{border:0;padding:0;} +button,input,select,textarea{font-family:inherit;font-size:100%;margin:0;} +button,input{line-height:normal;} +button,select{text-transform:none;} +button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;} +button[disabled],html input[disabled]{cursor:default;} +input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;} +input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box;} +input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;} +button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;} +textarea{overflow:auto;vertical-align:top;} +table{border-collapse:collapse;border-spacing:0;} +*,*:before,*:after{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} +html{font-size:62.5%;-webkit-tap-highlight-color:rgba(0, 0, 0, 0);} +body{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-size:14px;line-height:1.428571429;color:#333333;background-color:#ffffff;} +input,button,select,textarea{font-family:inherit;font-size:inherit;line-height:inherit;} +button,input,select[multiple],textarea{background-image:none;} +a{color:#428bca;text-decoration:none;}a:hover,a:focus{color:#2a6496;text-decoration:underline;} +a:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} +img{vertical-align:middle;} +.img-responsive{display:block;max-width:100%;height:auto;} +.img-rounded{border-radius:6px;} +.img-thumbnail{padding:4px;line-height:1.428571429;background-color:#ffffff;border:1px solid #dddddd;border-radius:4px;-webkit-transition:all 0.2s ease-in-out;transition:all 0.2s ease-in-out;display:inline-block;max-width:100%;height:auto;} +.img-circle{border-radius:50%;} +hr{margin-top:20px;margin-bottom:20px;border:0;border-top:1px solid #eeeeee;} +.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);border:0;} +p{margin:0 0 10px;} +.lead{margin-bottom:20px;font-size:16.099999999999998px;font-weight:200;line-height:1.4;}@media (min-width:768px){.lead{font-size:21px;}} +small{font-size:85%;} +cite{font-style:normal;} +.text-muted{color:#999999;} +.text-primary{color:#428bca;} +.text-warning{color:#c09853;} +.text-danger{color:#b94a48;} +.text-success{color:#468847;} +.text-info{color:#3a87ad;} +.text-left{text-align:left;} +.text-right{text-align:right;} +.text-center{text-align:center;} +h1,h2,h3,h4,h5,h6,.h1,.h2,.h3,.h4,.h5,.h6{font-family:"Helvetica Neue",Helvetica,Arial,sans-serif;font-weight:500;line-height:1.1;}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small,.h1 small,.h2 small,.h3 small,.h4 small,.h5 small,.h6 small{font-weight:normal;line-height:1;color:#999999;} +h1,h2,h3{margin-top:20px;margin-bottom:10px;} +h4,h5,h6{margin-top:10px;margin-bottom:10px;} +h1,.h1{font-size:36px;} +h2,.h2{font-size:30px;} +h3,.h3{font-size:24px;} +h4,.h4{font-size:18px;} +h5,.h5{font-size:14px;} +h6,.h6{font-size:12px;} +h1 small,.h1 small{font-size:24px;} +h2 small,.h2 small{font-size:18px;} +h3 small,.h3 small,h4 small,.h4 small{font-size:14px;} +.page-header{padding-bottom:9px;margin:40px 0 20px;border-bottom:1px solid #eeeeee;} +ul,ol{margin-top:0;margin-bottom:10px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:0;} +.list-unstyled{padding-left:0;list-style:none;} +.list-inline{padding-left:0;list-style:none;}.list-inline>li{display:inline-block;padding-left:5px;padding-right:5px;} +dl{margin-bottom:20px;} +dt,dd{line-height:1.428571429;} +dt{font-weight:bold;} +dd{margin-left:0;} +@media (min-width:768px){.dl-horizontal dt{float:left;width:160px;clear:left;text-align:right;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;} .dl-horizontal dd{margin-left:180px;}.dl-horizontal dd:before,.dl-horizontal dd:after{content:" ";display:table;} .dl-horizontal dd:after{clear:both;}}abbr[title],abbr[data-original-title]{cursor:help;border-bottom:1px dotted #999999;} +abbr.initialism{font-size:90%;text-transform:uppercase;} +blockquote{padding:10px 20px;margin:0 0 20px;border-left:5px solid #eeeeee;}blockquote p{font-size:17.5px;font-weight:300;line-height:1.25;} +blockquote p:last-child{margin-bottom:0;} +blockquote small{display:block;line-height:1.428571429;color:#999999;}blockquote small:before{content:'\2014 \00A0';} +blockquote.pull-right{padding-right:15px;padding-left:0;border-right:5px solid #eeeeee;border-left:0;}blockquote.pull-right p,blockquote.pull-right small{text-align:right;} +blockquote.pull-right small:before{content:'';} +blockquote.pull-right small:after{content:'\00A0 \2014';} +q:before,q:after,blockquote:before,blockquote:after{content:"";} +address{display:block;margin-bottom:20px;font-style:normal;line-height:1.428571429;} +.container{margin-right:auto;margin-left:auto;padding-left:15px;padding-right:15px;}.container:before,.container:after{content:" ";display:table;} +.container:after{clear:both;} +.row{margin-left:-15px;margin-right:-15px;}.row:before,.row:after{content:" ";display:table;} +.row:after{clear:both;} +.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11,.col-xs-12,.col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11,.col-sm-12,.col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11,.col-md-12,.col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11,.col-lg-12{position:relative;min-height:1px;padding-left:15px;padding-right:15px;} +.col-xs-1,.col-xs-2,.col-xs-3,.col-xs-4,.col-xs-5,.col-xs-6,.col-xs-7,.col-xs-8,.col-xs-9,.col-xs-10,.col-xs-11{float:left;} +.col-xs-1{width:8.333333333333332%;} +.col-xs-2{width:16.666666666666664%;} +.col-xs-3{width:25%;} +.col-xs-4{width:33.33333333333333%;} +.col-xs-5{width:41.66666666666667%;} +.col-xs-6{width:50%;} +.col-xs-7{width:58.333333333333336%;} +.col-xs-8{width:66.66666666666666%;} +.col-xs-9{width:75%;} +.col-xs-10{width:83.33333333333334%;} +.col-xs-11{width:91.66666666666666%;} +.col-xs-12{width:100%;} +@media (min-width:768px){.container{max-width:750px;} .col-sm-1,.col-sm-2,.col-sm-3,.col-sm-4,.col-sm-5,.col-sm-6,.col-sm-7,.col-sm-8,.col-sm-9,.col-sm-10,.col-sm-11{float:left;} .col-sm-1{width:8.333333333333332%;} .col-sm-2{width:16.666666666666664%;} .col-sm-3{width:25%;} .col-sm-4{width:33.33333333333333%;} .col-sm-5{width:41.66666666666667%;} .col-sm-6{width:50%;} .col-sm-7{width:58.333333333333336%;} .col-sm-8{width:66.66666666666666%;} .col-sm-9{width:75%;} .col-sm-10{width:83.33333333333334%;} .col-sm-11{width:91.66666666666666%;} .col-sm-12{width:100%;} .col-sm-push-1{left:8.333333333333332%;} .col-sm-push-2{left:16.666666666666664%;} .col-sm-push-3{left:25%;} .col-sm-push-4{left:33.33333333333333%;} .col-sm-push-5{left:41.66666666666667%;} .col-sm-push-6{left:50%;} .col-sm-push-7{left:58.333333333333336%;} .col-sm-push-8{left:66.66666666666666%;} .col-sm-push-9{left:75%;} .col-sm-push-10{left:83.33333333333334%;} .col-sm-push-11{left:91.66666666666666%;} .col-sm-pull-1{right:8.333333333333332%;} .col-sm-pull-2{right:16.666666666666664%;} .col-sm-pull-3{right:25%;} .col-sm-pull-4{right:33.33333333333333%;} .col-sm-pull-5{right:41.66666666666667%;} .col-sm-pull-6{right:50%;} .col-sm-pull-7{right:58.333333333333336%;} .col-sm-pull-8{right:66.66666666666666%;} .col-sm-pull-9{right:75%;} .col-sm-pull-10{right:83.33333333333334%;} .col-sm-pull-11{right:91.66666666666666%;} .col-sm-offset-1{margin-left:8.333333333333332%;} .col-sm-offset-2{margin-left:16.666666666666664%;} .col-sm-offset-3{margin-left:25%;} .col-sm-offset-4{margin-left:33.33333333333333%;} .col-sm-offset-5{margin-left:41.66666666666667%;} .col-sm-offset-6{margin-left:50%;} .col-sm-offset-7{margin-left:58.333333333333336%;} .col-sm-offset-8{margin-left:66.66666666666666%;} .col-sm-offset-9{margin-left:75%;} .col-sm-offset-10{margin-left:83.33333333333334%;} .col-sm-offset-11{margin-left:91.66666666666666%;}}@media (min-width:992px){.container{max-width:970px;} .col-md-1,.col-md-2,.col-md-3,.col-md-4,.col-md-5,.col-md-6,.col-md-7,.col-md-8,.col-md-9,.col-md-10,.col-md-11{float:left;} .col-md-1{width:8.333333333333332%;} .col-md-2{width:16.666666666666664%;} .col-md-3{width:25%;} .col-md-4{width:33.33333333333333%;} .col-md-5{width:41.66666666666667%;} .col-md-6{width:50%;} .col-md-7{width:58.333333333333336%;} .col-md-8{width:66.66666666666666%;} .col-md-9{width:75%;} .col-md-10{width:83.33333333333334%;} .col-md-11{width:91.66666666666666%;} .col-md-12{width:100%;} .col-md-push-0{left:auto;} .col-md-push-1{left:8.333333333333332%;} .col-md-push-2{left:16.666666666666664%;} .col-md-push-3{left:25%;} .col-md-push-4{left:33.33333333333333%;} .col-md-push-5{left:41.66666666666667%;} .col-md-push-6{left:50%;} .col-md-push-7{left:58.333333333333336%;} .col-md-push-8{left:66.66666666666666%;} .col-md-push-9{left:75%;} .col-md-push-10{left:83.33333333333334%;} .col-md-push-11{left:91.66666666666666%;} .col-md-pull-0{right:auto;} .col-md-pull-1{right:8.333333333333332%;} .col-md-pull-2{right:16.666666666666664%;} .col-md-pull-3{right:25%;} .col-md-pull-4{right:33.33333333333333%;} .col-md-pull-5{right:41.66666666666667%;} .col-md-pull-6{right:50%;} .col-md-pull-7{right:58.333333333333336%;} .col-md-pull-8{right:66.66666666666666%;} .col-md-pull-9{right:75%;} .col-md-pull-10{right:83.33333333333334%;} .col-md-pull-11{right:91.66666666666666%;} .col-md-offset-0{margin-left:0;} .col-md-offset-1{margin-left:8.333333333333332%;} .col-md-offset-2{margin-left:16.666666666666664%;} .col-md-offset-3{margin-left:25%;} .col-md-offset-4{margin-left:33.33333333333333%;} .col-md-offset-5{margin-left:41.66666666666667%;} .col-md-offset-6{margin-left:50%;} .col-md-offset-7{margin-left:58.333333333333336%;} .col-md-offset-8{margin-left:66.66666666666666%;} .col-md-offset-9{margin-left:75%;} .col-md-offset-10{margin-left:83.33333333333334%;} .col-md-offset-11{margin-left:91.66666666666666%;}}@media (min-width:1200px){.container{max-width:1170px;} .col-lg-1,.col-lg-2,.col-lg-3,.col-lg-4,.col-lg-5,.col-lg-6,.col-lg-7,.col-lg-8,.col-lg-9,.col-lg-10,.col-lg-11{float:left;} .col-lg-1{width:8.333333333333332%;} .col-lg-2{width:16.666666666666664%;} .col-lg-3{width:25%;} .col-lg-4{width:33.33333333333333%;} .col-lg-5{width:41.66666666666667%;} .col-lg-6{width:50%;} .col-lg-7{width:58.333333333333336%;} .col-lg-8{width:66.66666666666666%;} .col-lg-9{width:75%;} .col-lg-10{width:83.33333333333334%;} .col-lg-11{width:91.66666666666666%;} .col-lg-12{width:100%;} .col-lg-push-0{left:auto;} .col-lg-push-1{left:8.333333333333332%;} .col-lg-push-2{left:16.666666666666664%;} .col-lg-push-3{left:25%;} .col-lg-push-4{left:33.33333333333333%;} .col-lg-push-5{left:41.66666666666667%;} .col-lg-push-6{left:50%;} .col-lg-push-7{left:58.333333333333336%;} .col-lg-push-8{left:66.66666666666666%;} .col-lg-push-9{left:75%;} .col-lg-push-10{left:83.33333333333334%;} .col-lg-push-11{left:91.66666666666666%;} .col-lg-pull-0{right:auto;} .col-lg-pull-1{right:8.333333333333332%;} .col-lg-pull-2{right:16.666666666666664%;} .col-lg-pull-3{right:25%;} .col-lg-pull-4{right:33.33333333333333%;} .col-lg-pull-5{right:41.66666666666667%;} .col-lg-pull-6{right:50%;} .col-lg-pull-7{right:58.333333333333336%;} .col-lg-pull-8{right:66.66666666666666%;} .col-lg-pull-9{right:75%;} .col-lg-pull-10{right:83.33333333333334%;} .col-lg-pull-11{right:91.66666666666666%;} .col-lg-offset-0{margin-left:0;} .col-lg-offset-1{margin-left:8.333333333333332%;} .col-lg-offset-2{margin-left:16.666666666666664%;} .col-lg-offset-3{margin-left:25%;} .col-lg-offset-4{margin-left:33.33333333333333%;} .col-lg-offset-5{margin-left:41.66666666666667%;} .col-lg-offset-6{margin-left:50%;} .col-lg-offset-7{margin-left:58.333333333333336%;} .col-lg-offset-8{margin-left:66.66666666666666%;} .col-lg-offset-9{margin-left:75%;} .col-lg-offset-10{margin-left:83.33333333333334%;} .col-lg-offset-11{margin-left:91.66666666666666%;}}fieldset{padding:0;margin:0;border:0;} +legend{display:block;width:100%;padding:0;margin-bottom:20px;font-size:21px;line-height:inherit;color:#333333;border:0;border-bottom:1px solid #e5e5e5;} +label{display:inline-block;margin-bottom:5px;font-weight:bold;} +input[type="search"]{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;} +input[type="radio"],input[type="checkbox"]{margin:4px 0 0;margin-top:1px \9;line-height:normal;} +input[type="file"]{display:block;} +select[multiple],select[size]{height:auto;} +select optgroup{font-size:inherit;font-style:inherit;font-family:inherit;} +input[type="file"]:focus,input[type="radio"]:focus,input[type="checkbox"]:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} +input[type="number"]::-webkit-outer-spin-button,input[type="number"]::-webkit-inner-spin-button{height:auto;} +.form-control:-moz-placeholder{color:#999999;} +.form-control::-moz-placeholder{color:#999999;} +.form-control:-ms-input-placeholder{color:#999999;} +.form-control::-webkit-input-placeholder{color:#999999;} +.form-control{display:block;width:100%;height:34px;padding:6px 12px;font-size:14px;line-height:1.428571429;color:#555555;vertical-align:middle;background-color:#ffffff;border:1px solid #cccccc;border-radius:4px;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);} +.form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eeeeee;} +textarea.form-control{height:auto;} +.form-group{margin-bottom:15px;} +.radio,.checkbox{display:block;min-height:20px;margin-top:10px;margin-bottom:10px;padding-left:20px;vertical-align:middle;}.radio label,.checkbox label{display:inline;margin-bottom:0;font-weight:normal;cursor:pointer;} +.radio input[type="radio"],.radio-inline input[type="radio"],.checkbox input[type="checkbox"],.checkbox-inline input[type="checkbox"]{float:left;margin-left:-20px;} +.radio+.radio,.checkbox+.checkbox{margin-top:-5px;} +.radio-inline,.checkbox-inline{display:inline-block;padding-left:20px;margin-bottom:0;vertical-align:middle;font-weight:normal;cursor:pointer;} +.radio-inline+.radio-inline,.checkbox-inline+.checkbox-inline{margin-top:0;margin-left:10px;} +input[type="radio"][disabled],input[type="checkbox"][disabled],.radio[disabled],.radio-inline[disabled],.checkbox[disabled],.checkbox-inline[disabled],fieldset[disabled] input[type="radio"],fieldset[disabled] input[type="checkbox"],fieldset[disabled] .radio,fieldset[disabled] .radio-inline,fieldset[disabled] .checkbox,fieldset[disabled] .checkbox-inline{cursor:not-allowed;} +.input-sm{height:30px;padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;}select.input-sm{height:30px;line-height:30px;} +textarea.input-sm{height:auto;} +.input-lg{height:45px;padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px;}select.input-lg{height:45px;line-height:45px;} +textarea.input-lg{height:auto;} +.has-warning .help-block,.has-warning .control-label{color:#c09853;} +.has-warning .form-control{border-color:#c09853;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-warning .form-control:focus{border-color:#a47e3c;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #dbc59e;} +.has-warning .input-group-addon{color:#c09853;border-color:#c09853;background-color:#fcf8e3;} +.has-error .help-block,.has-error .control-label{color:#b94a48;} +.has-error .form-control{border-color:#b94a48;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-error .form-control:focus{border-color:#953b39;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #d59392;} +.has-error .input-group-addon{color:#b94a48;border-color:#b94a48;background-color:#f2dede;} +.has-success .help-block,.has-success .control-label{color:#468847;} +.has-success .form-control{border-color:#468847;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075);}.has-success .form-control:focus{border-color:#356635;-webkit-box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;box-shadow:inset 0 1px 1px rgba(0, 0, 0, 0.075),0 0 6px #7aba7b;} +.has-success .input-group-addon{color:#468847;border-color:#468847;background-color:#dff0d8;} +.form-control-static{margin-bottom:0;padding-top:7px;} +.help-block{display:block;margin-top:5px;margin-bottom:10px;color:#737373;} +@media (min-width:768px){.form-inline .form-group{display:inline-block;margin-bottom:0;vertical-align:middle;} .form-inline .form-control{display:inline-block;} .form-inline .radio,.form-inline .checkbox{display:inline-block;margin-top:0;margin-bottom:0;padding-left:0;} .form-inline .radio input[type="radio"],.form-inline .checkbox input[type="checkbox"]{float:none;margin-left:0;}} +.form-horizontal .control-label,.form-horizontal .radio,.form-horizontal .checkbox,.form-horizontal .radio-inline,.form-horizontal .checkbox-inline{margin-top:0;margin-bottom:0;padding-top:7px;} +.form-horizontal .form-group{margin-left:-15px;margin-right:-15px;}.form-horizontal .form-group:before,.form-horizontal .form-group:after{content:" ";display:table;} +.form-horizontal .form-group:after{clear:both;} +@media (min-width:768px){.form-horizontal .control-label{text-align:right;}} +.btn{display:inline-block;padding:6px 12px;margin-bottom:0;font-size:14px;font-weight:normal;line-height:1.428571429;text-align:center;vertical-align:middle;cursor:pointer;border:1px solid transparent;border-radius:4px;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none;}.btn:focus{outline:thin dotted #333;outline:5px auto -webkit-focus-ring-color;outline-offset:-2px;} +.btn:hover,.btn:focus{color:#333333;text-decoration:none;} +.btn:active,.btn.active{outline:0;background-image:none;-webkit-box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);box-shadow:inset 0 3px 5px rgba(0, 0, 0, 0.125);} +.btn.disabled,.btn[disabled],fieldset[disabled] .btn{cursor:not-allowed;pointer-events:none;opacity:0.65;filter:alpha(opacity=65);-webkit-box-shadow:none;box-shadow:none;} +.btn-default{color:#333333;background-color:#ffffff;border-color:#cccccc;}.btn-default:hover,.btn-default:focus,.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{color:#333333;background-color:#ebebeb;border-color:#adadad;} +.btn-default:active,.btn-default.active,.open .dropdown-toggle.btn-default{background-image:none;} +.btn-default.disabled,.btn-default[disabled],fieldset[disabled] .btn-default,.btn-default.disabled:hover,.btn-default[disabled]:hover,fieldset[disabled] .btn-default:hover,.btn-default.disabled:focus,.btn-default[disabled]:focus,fieldset[disabled] .btn-default:focus,.btn-default.disabled:active,.btn-default[disabled]:active,fieldset[disabled] .btn-default:active,.btn-default.disabled.active,.btn-default[disabled].active,fieldset[disabled] .btn-default.active{background-color:#ffffff;border-color:#cccccc;} +.btn-primary{color:#ffffff;background-color:#428bca;border-color:#357ebd;}.btn-primary:hover,.btn-primary:focus,.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{color:#ffffff;background-color:#3276b1;border-color:#285e8e;} +.btn-primary:active,.btn-primary.active,.open .dropdown-toggle.btn-primary{background-image:none;} +.btn-primary.disabled,.btn-primary[disabled],fieldset[disabled] .btn-primary,.btn-primary.disabled:hover,.btn-primary[disabled]:hover,fieldset[disabled] .btn-primary:hover,.btn-primary.disabled:focus,.btn-primary[disabled]:focus,fieldset[disabled] .btn-primary:focus,.btn-primary.disabled:active,.btn-primary[disabled]:active,fieldset[disabled] .btn-primary:active,.btn-primary.disabled.active,.btn-primary[disabled].active,fieldset[disabled] .btn-primary.active{background-color:#428bca;border-color:#357ebd;} +.btn-warning{color:#ffffff;background-color:#f0ad4e;border-color:#eea236;}.btn-warning:hover,.btn-warning:focus,.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{color:#ffffff;background-color:#ed9c28;border-color:#d58512;} +.btn-warning:active,.btn-warning.active,.open .dropdown-toggle.btn-warning{background-image:none;} +.btn-warning.disabled,.btn-warning[disabled],fieldset[disabled] .btn-warning,.btn-warning.disabled:hover,.btn-warning[disabled]:hover,fieldset[disabled] .btn-warning:hover,.btn-warning.disabled:focus,.btn-warning[disabled]:focus,fieldset[disabled] .btn-warning:focus,.btn-warning.disabled:active,.btn-warning[disabled]:active,fieldset[disabled] .btn-warning:active,.btn-warning.disabled.active,.btn-warning[disabled].active,fieldset[disabled] .btn-warning.active{background-color:#f0ad4e;border-color:#eea236;} +.btn-danger{color:#ffffff;background-color:#d9534f;border-color:#d43f3a;}.btn-danger:hover,.btn-danger:focus,.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{color:#ffffff;background-color:#d2322d;border-color:#ac2925;} +.btn-danger:active,.btn-danger.active,.open .dropdown-toggle.btn-danger{background-image:none;} +.btn-danger.disabled,.btn-danger[disabled],fieldset[disabled] .btn-danger,.btn-danger.disabled:hover,.btn-danger[disabled]:hover,fieldset[disabled] .btn-danger:hover,.btn-danger.disabled:focus,.btn-danger[disabled]:focus,fieldset[disabled] .btn-danger:focus,.btn-danger.disabled:active,.btn-danger[disabled]:active,fieldset[disabled] .btn-danger:active,.btn-danger.disabled.active,.btn-danger[disabled].active,fieldset[disabled] .btn-danger.active{background-color:#d9534f;border-color:#d43f3a;} +.btn-success{color:#ffffff;background-color:#5cb85c;border-color:#4cae4c;}.btn-success:hover,.btn-success:focus,.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{color:#ffffff;background-color:#47a447;border-color:#398439;} +.btn-success:active,.btn-success.active,.open .dropdown-toggle.btn-success{background-image:none;} +.btn-success.disabled,.btn-success[disabled],fieldset[disabled] .btn-success,.btn-success.disabled:hover,.btn-success[disabled]:hover,fieldset[disabled] .btn-success:hover,.btn-success.disabled:focus,.btn-success[disabled]:focus,fieldset[disabled] .btn-success:focus,.btn-success.disabled:active,.btn-success[disabled]:active,fieldset[disabled] .btn-success:active,.btn-success.disabled.active,.btn-success[disabled].active,fieldset[disabled] .btn-success.active{background-color:#5cb85c;border-color:#4cae4c;} +.btn-info{color:#ffffff;background-color:#5bc0de;border-color:#46b8da;}.btn-info:hover,.btn-info:focus,.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{color:#ffffff;background-color:#39b3d7;border-color:#269abc;} +.btn-info:active,.btn-info.active,.open .dropdown-toggle.btn-info{background-image:none;} +.btn-info.disabled,.btn-info[disabled],fieldset[disabled] .btn-info,.btn-info.disabled:hover,.btn-info[disabled]:hover,fieldset[disabled] .btn-info:hover,.btn-info.disabled:focus,.btn-info[disabled]:focus,fieldset[disabled] .btn-info:focus,.btn-info.disabled:active,.btn-info[disabled]:active,fieldset[disabled] .btn-info:active,.btn-info.disabled.active,.btn-info[disabled].active,fieldset[disabled] .btn-info.active{background-color:#5bc0de;border-color:#46b8da;} +.btn-link{color:#428bca;font-weight:normal;cursor:pointer;border-radius:0;}.btn-link,.btn-link:active,.btn-link[disabled],fieldset[disabled] .btn-link{background-color:transparent;-webkit-box-shadow:none;box-shadow:none;} +.btn-link,.btn-link:hover,.btn-link:focus,.btn-link:active{border-color:transparent;} +.btn-link:hover,.btn-link:focus{color:#2a6496;text-decoration:underline;background-color:transparent;} +.btn-link[disabled]:hover,fieldset[disabled] .btn-link:hover,.btn-link[disabled]:focus,fieldset[disabled] .btn-link:focus{color:#999999;text-decoration:none;} +.btn-lg{padding:10px 16px;font-size:18px;line-height:1.33;border-radius:6px;} +.btn-sm,.btn-xs{padding:5px 10px;font-size:12px;line-height:1.5;border-radius:3px;} +.btn-xs{padding:1px 5px;} +.btn-block{display:block;width:100%;padding-left:0;padding-right:0;} +.btn-block+.btn-block{margin-top:5px;} +input[type="submit"].btn-block,input[type="reset"].btn-block,input[type="button"].btn-block{width:100%;} +.alert{padding:15px;margin-bottom:20px;border:1px solid transparent;border-radius:4px;}.alert h4{margin-top:0;color:inherit;} +.alert .alert-link{font-weight:bold;} +.alert>p,.alert>ul{margin-bottom:0;} +.alert>p+p{margin-top:5px;} +.alert-dismissable{padding-right:35px;}.alert-dismissable .close{position:relative;top:-2px;right:-21px;color:inherit;} +.alert-success{background-color:#dff0d8;border-color:#d6e9c6;color:#468847;}.alert-success hr{border-top-color:#c9e2b3;} +.alert-success .alert-link{color:#356635;} +.alert-info{background-color:#d9edf7;border-color:#bce8f1;color:#3a87ad;}.alert-info hr{border-top-color:#a6e1ec;} +.alert-info .alert-link{color:#2d6987;} +.alert-warning{background-color:#fcf8e3;border-color:#fbeed5;color:#c09853;}.alert-warning hr{border-top-color:#f8e5be;} +.alert-warning .alert-link{color:#a47e3c;} +.alert-danger{background-color:#f2dede;border-color:#eed3d7;color:#b94a48;}.alert-danger hr{border-top-color:#e6c1c7;} +.alert-danger .alert-link{color:#953b39;} diff --git a/script/lstu b/script/lstu new file mode 100755 index 0000000000000000000000000000000000000000..ae62e29bfa3f5235715357470f8c06916f43472f --- /dev/null +++ b/script/lstu @@ -0,0 +1,11 @@ +#!/usr/bin/env perl + +use strict; +use warnings; + +use FindBin; +BEGIN { unshift @INC, "$FindBin::Bin/../lib" } + +# Start command line interface for application +require Mojolicious::Commands; +Mojolicious::Commands->start_app('Lstu'); diff --git a/templates/index.html.ep b/templates/index.html.ep new file mode 100644 index 0000000000000000000000000000000000000000..b6fc72acba898e9e2356f4a550b281fc2b06906f --- /dev/null +++ b/templates/index.html.ep @@ -0,0 +1,28 @@ +% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab: +% layout 'default'; +% title 'Lstu'; +

Let's Shorten That Url

+

+ © 2013 <%= link_to 'http://www.fiat-tux.fr' => begin %>Luc Didry<% end %> — + <%=l 'license' %> <%= link_to 'http://www.wtfpl.net/' => begin %>WTFPL<% end %> — + <%= link_to 'https://github.com/ldidry/lstu' => begin %><%=l 'about' %><% end %> + +

+
+
+ + +
+ <%= submit_button l('go'), class => 'btn btn-default btn-primary' %> +
+ +% if (defined(flash('short')) && defined(flash('url'))) { +

+ <%= link_to flash('url') => begin %><%== flash('url') %><%= end %> => + <%= link_to url_for('/')->to_abs.flash('short') => begin %><%= url_for('/')->to_abs.flash('short') %><%= end %> +

+% } +% if (defined(flash('msg'))) { +

<%== flash('msg') %>

+% } + diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep new file mode 100644 index 0000000000000000000000000000000000000000..aa16de1a5e8ca23d225869771817be749d0b566f --- /dev/null +++ b/templates/layouts/default.html.ep @@ -0,0 +1,26 @@ +% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab: + + + + <%= title %> + + %= stylesheet 'css/bootstrap.min.css', media => 'screen' + %= stylesheet begin + body { + padding-top: 40px; + padding-bottom: 40px; + background-color: #eee; + } + + .container { + padding: 15px; + margin: 0 auto; + } + % end + + +
+ <%= content %> +
+ +