mirror of
https://framagit.org/fiat-tux/hat-softwares/lutim.git
synced 2026-08-05 08:22:49 +02:00
Functional :)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
log/*
|
||||
lutim.conf
|
||||
lutim.db
|
||||
local/*
|
||||
files/*
|
||||
@@ -0,0 +1,380 @@
|
||||
{
|
||||
"vars": {
|
||||
"@gray-darker": "lighten(#000, 13.5%)",
|
||||
"@gray-dark": "lighten(#000, 20%)",
|
||||
"@gray": "lighten(#000, 33.5%)",
|
||||
"@gray-light": "lighten(#000, 60%)",
|
||||
"@gray-lighter": "lighten(#000, 93.5%)",
|
||||
"@brand-primary": "#428bca",
|
||||
"@brand-success": "#5cb85c",
|
||||
"@brand-info": "#5bc0de",
|
||||
"@brand-warning": "#f0ad4e",
|
||||
"@brand-danger": "#d9534f",
|
||||
"@body-bg": "#fff",
|
||||
"@text-color": "@gray-dark",
|
||||
"@link-color": "@brand-primary",
|
||||
"@link-hover-color": "darken(@link-color, 15%)",
|
||||
"@font-family-sans-serif": "\"Helvetica Neue\", Helvetica, Arial, sans-serif",
|
||||
"@font-family-serif": "Georgia, \"Times New Roman\", Times, serif",
|
||||
"@font-family-monospace": "Menlo, Monaco, Consolas, \"Courier New\", monospace",
|
||||
"@font-family-base": "@font-family-sans-serif",
|
||||
"@font-size-base": "14px",
|
||||
"@font-size-large": "ceil((@font-size-base * 1.25))",
|
||||
"@font-size-small": "ceil((@font-size-base * 0.85))",
|
||||
"@font-size-h1": "floor((@font-size-base * 2.6))",
|
||||
"@font-size-h2": "floor((@font-size-base * 2.15))",
|
||||
"@font-size-h3": "ceil((@font-size-base * 1.7))",
|
||||
"@font-size-h4": "ceil((@font-size-base * 1.25))",
|
||||
"@font-size-h5": "@font-size-base",
|
||||
"@font-size-h6": "ceil((@font-size-base * 0.85))",
|
||||
"@line-height-base": "1.428571429",
|
||||
"@line-height-computed": "floor((@font-size-base * @line-height-base))",
|
||||
"@headings-font-family": "inherit",
|
||||
"@headings-font-weight": "500",
|
||||
"@headings-line-height": "1.1",
|
||||
"@headings-color": "inherit",
|
||||
"@padding-base-vertical": "6px",
|
||||
"@padding-base-horizontal": "12px",
|
||||
"@padding-large-vertical": "10px",
|
||||
"@padding-large-horizontal": "16px",
|
||||
"@padding-small-vertical": "5px",
|
||||
"@padding-small-horizontal": "10px",
|
||||
"@padding-xs-vertical": "1px",
|
||||
"@padding-xs-horizontal": "5px",
|
||||
"@line-height-large": "1.33",
|
||||
"@line-height-small": "1.5",
|
||||
"@border-radius-base": "4px",
|
||||
"@border-radius-large": "6px",
|
||||
"@border-radius-small": "3px",
|
||||
"@component-active-color": "#fff",
|
||||
"@component-active-bg": "@brand-primary",
|
||||
"@caret-width-base": "4px",
|
||||
"@caret-width-large": "5px",
|
||||
"@table-cell-padding": "8px",
|
||||
"@table-condensed-cell-padding": "5px",
|
||||
"@table-bg": "transparent",
|
||||
"@table-bg-accent": "#f9f9f9",
|
||||
"@table-bg-hover": "#f5f5f5",
|
||||
"@table-bg-active": "@table-bg-hover",
|
||||
"@table-border-color": "#ddd",
|
||||
"@btn-font-weight": "normal",
|
||||
"@btn-default-color": "#333",
|
||||
"@btn-default-bg": "#fff",
|
||||
"@btn-default-border": "#ccc",
|
||||
"@btn-primary-color": "#fff",
|
||||
"@btn-primary-bg": "@brand-primary",
|
||||
"@btn-primary-border": "darken(@btn-primary-bg, 5%)",
|
||||
"@btn-success-color": "#fff",
|
||||
"@btn-success-bg": "@brand-success",
|
||||
"@btn-success-border": "darken(@btn-success-bg, 5%)",
|
||||
"@btn-info-color": "#fff",
|
||||
"@btn-info-bg": "@brand-info",
|
||||
"@btn-info-border": "darken(@btn-info-bg, 5%)",
|
||||
"@btn-warning-color": "#fff",
|
||||
"@btn-warning-bg": "@brand-warning",
|
||||
"@btn-warning-border": "darken(@btn-warning-bg, 5%)",
|
||||
"@btn-danger-color": "#fff",
|
||||
"@btn-danger-bg": "@brand-danger",
|
||||
"@btn-danger-border": "darken(@btn-danger-bg, 5%)",
|
||||
"@btn-link-disabled-color": "@gray-light",
|
||||
"@input-bg": "#fff",
|
||||
"@input-bg-disabled": "@gray-lighter",
|
||||
"@input-color": "@gray",
|
||||
"@input-border": "#ccc",
|
||||
"@input-border-radius": "@border-radius-base",
|
||||
"@input-border-focus": "#66afe9",
|
||||
"@input-color-placeholder": "@gray-light",
|
||||
"@input-height-base": "(@line-height-computed + (@padding-base-vertical * 2) + 2)",
|
||||
"@input-height-large": "(ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2)",
|
||||
"@input-height-small": "(floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2)",
|
||||
"@legend-color": "@gray-dark",
|
||||
"@legend-border-color": "#e5e5e5",
|
||||
"@input-group-addon-bg": "@gray-lighter",
|
||||
"@input-group-addon-border-color": "@input-border",
|
||||
"@dropdown-bg": "#fff",
|
||||
"@dropdown-border": "rgba(0,0,0,.15)",
|
||||
"@dropdown-fallback-border": "#ccc",
|
||||
"@dropdown-divider-bg": "#e5e5e5",
|
||||
"@dropdown-link-color": "@gray-dark",
|
||||
"@dropdown-link-hover-color": "darken(@gray-dark, 5%)",
|
||||
"@dropdown-link-hover-bg": "#f5f5f5",
|
||||
"@dropdown-link-active-color": "@component-active-color",
|
||||
"@dropdown-link-active-bg": "@component-active-bg",
|
||||
"@dropdown-link-disabled-color": "@gray-light",
|
||||
"@dropdown-header-color": "@gray-light",
|
||||
"@dropdown-caret-color": "#000",
|
||||
"@screen-xs": "480px",
|
||||
"@screen-xs-min": "@screen-xs",
|
||||
"@screen-phone": "@screen-xs-min",
|
||||
"@screen-sm": "768px",
|
||||
"@screen-sm-min": "@screen-sm",
|
||||
"@screen-tablet": "@screen-sm-min",
|
||||
"@screen-md": "992px",
|
||||
"@screen-md-min": "@screen-md",
|
||||
"@screen-desktop": "@screen-md-min",
|
||||
"@screen-lg": "1200px",
|
||||
"@screen-lg-min": "@screen-lg",
|
||||
"@screen-lg-desktop": "@screen-lg-min",
|
||||
"@screen-xs-max": "(@screen-sm-min - 1)",
|
||||
"@screen-sm-max": "(@screen-md-min - 1)",
|
||||
"@screen-md-max": "(@screen-lg-min - 1)",
|
||||
"@grid-columns": "12",
|
||||
"@grid-gutter-width": "30px",
|
||||
"@grid-float-breakpoint": "@screen-sm-min",
|
||||
"@grid-float-breakpoint-max": "(@grid-float-breakpoint - 1)",
|
||||
"@container-tablet": "((720px + @grid-gutter-width))",
|
||||
"@container-sm": "@container-tablet",
|
||||
"@container-desktop": "((940px + @grid-gutter-width))",
|
||||
"@container-md": "@container-desktop",
|
||||
"@container-large-desktop": "((1140px + @grid-gutter-width))",
|
||||
"@container-lg": "@container-large-desktop",
|
||||
"@navbar-height": "50px",
|
||||
"@navbar-margin-bottom": "@line-height-computed",
|
||||
"@navbar-border-radius": "@border-radius-base",
|
||||
"@navbar-padding-horizontal": "floor((@grid-gutter-width / 2))",
|
||||
"@navbar-padding-vertical": "((@navbar-height - @line-height-computed) / 2)",
|
||||
"@navbar-collapse-max-height": "340px",
|
||||
"@navbar-default-color": "#777",
|
||||
"@navbar-default-bg": "#f8f8f8",
|
||||
"@navbar-default-border": "darken(@navbar-default-bg, 6.5%)",
|
||||
"@navbar-default-link-color": "#777",
|
||||
"@navbar-default-link-hover-color": "#333",
|
||||
"@navbar-default-link-hover-bg": "transparent",
|
||||
"@navbar-default-link-active-color": "#555",
|
||||
"@navbar-default-link-active-bg": "darken(@navbar-default-bg, 6.5%)",
|
||||
"@navbar-default-link-disabled-color": "#ccc",
|
||||
"@navbar-default-link-disabled-bg": "transparent",
|
||||
"@navbar-default-brand-color": "@navbar-default-link-color",
|
||||
"@navbar-default-brand-hover-color": "darken(@navbar-default-brand-color, 10%)",
|
||||
"@navbar-default-brand-hover-bg": "transparent",
|
||||
"@navbar-default-toggle-hover-bg": "#ddd",
|
||||
"@navbar-default-toggle-icon-bar-bg": "#888",
|
||||
"@navbar-default-toggle-border-color": "#ddd",
|
||||
"@navbar-inverse-color": "@gray-light",
|
||||
"@navbar-inverse-bg": "#222",
|
||||
"@navbar-inverse-border": "darken(@navbar-inverse-bg, 10%)",
|
||||
"@navbar-inverse-link-color": "@gray-light",
|
||||
"@navbar-inverse-link-hover-color": "#fff",
|
||||
"@navbar-inverse-link-hover-bg": "transparent",
|
||||
"@navbar-inverse-link-active-color": "@navbar-inverse-link-hover-color",
|
||||
"@navbar-inverse-link-active-bg": "darken(@navbar-inverse-bg, 10%)",
|
||||
"@navbar-inverse-link-disabled-color": "#444",
|
||||
"@navbar-inverse-link-disabled-bg": "transparent",
|
||||
"@navbar-inverse-brand-color": "@navbar-inverse-link-color",
|
||||
"@navbar-inverse-brand-hover-color": "#fff",
|
||||
"@navbar-inverse-brand-hover-bg": "transparent",
|
||||
"@navbar-inverse-toggle-hover-bg": "#333",
|
||||
"@navbar-inverse-toggle-icon-bar-bg": "#fff",
|
||||
"@navbar-inverse-toggle-border-color": "#333",
|
||||
"@nav-link-padding": "10px 15px",
|
||||
"@nav-link-hover-bg": "@gray-lighter",
|
||||
"@nav-disabled-link-color": "@gray-light",
|
||||
"@nav-disabled-link-hover-color": "@gray-light",
|
||||
"@nav-open-link-hover-color": "#fff",
|
||||
"@nav-tabs-border-color": "#ddd",
|
||||
"@nav-tabs-link-hover-border-color": "@gray-lighter",
|
||||
"@nav-tabs-active-link-hover-bg": "@body-bg",
|
||||
"@nav-tabs-active-link-hover-color": "@gray",
|
||||
"@nav-tabs-active-link-hover-border-color": "#ddd",
|
||||
"@nav-tabs-justified-link-border-color": "#ddd",
|
||||
"@nav-tabs-justified-active-link-border-color": "@body-bg",
|
||||
"@nav-pills-border-radius": "@border-radius-base",
|
||||
"@nav-pills-active-link-hover-bg": "@component-active-bg",
|
||||
"@nav-pills-active-link-hover-color": "@component-active-color",
|
||||
"@pagination-color": "@link-color",
|
||||
"@pagination-bg": "#fff",
|
||||
"@pagination-border": "#ddd",
|
||||
"@pagination-hover-color": "@link-hover-color",
|
||||
"@pagination-hover-bg": "@gray-lighter",
|
||||
"@pagination-hover-border": "#ddd",
|
||||
"@pagination-active-color": "#fff",
|
||||
"@pagination-active-bg": "@brand-primary",
|
||||
"@pagination-active-border": "@brand-primary",
|
||||
"@pagination-disabled-color": "@gray-light",
|
||||
"@pagination-disabled-bg": "#fff",
|
||||
"@pagination-disabled-border": "#ddd",
|
||||
"@pager-bg": "@pagination-bg",
|
||||
"@pager-border": "@pagination-border",
|
||||
"@pager-border-radius": "15px",
|
||||
"@pager-hover-bg": "@pagination-hover-bg",
|
||||
"@pager-active-bg": "@pagination-active-bg",
|
||||
"@pager-active-color": "@pagination-active-color",
|
||||
"@pager-disabled-color": "@pagination-disabled-color",
|
||||
"@jumbotron-padding": "30px",
|
||||
"@jumbotron-color": "inherit",
|
||||
"@jumbotron-bg": "@gray-lighter",
|
||||
"@jumbotron-heading-color": "inherit",
|
||||
"@jumbotron-font-size": "ceil((@font-size-base * 1.5))",
|
||||
"@state-success-text": "#3c763d",
|
||||
"@state-success-bg": "#dff0d8",
|
||||
"@state-success-border": "darken(spin(@state-success-bg, -10), 5%)",
|
||||
"@state-info-text": "#31708f",
|
||||
"@state-info-bg": "#d9edf7",
|
||||
"@state-info-border": "darken(spin(@state-info-bg, -10), 7%)",
|
||||
"@state-warning-text": "#8a6d3b",
|
||||
"@state-warning-bg": "#fcf8e3",
|
||||
"@state-warning-border": "darken(spin(@state-warning-bg, -10), 5%)",
|
||||
"@state-danger-text": "#a94442",
|
||||
"@state-danger-bg": "#f2dede",
|
||||
"@state-danger-border": "darken(spin(@state-danger-bg, -10), 5%)",
|
||||
"@tooltip-max-width": "200px",
|
||||
"@tooltip-color": "#fff",
|
||||
"@tooltip-bg": "#000",
|
||||
"@tooltip-opacity": ".9",
|
||||
"@tooltip-arrow-width": "5px",
|
||||
"@tooltip-arrow-color": "@tooltip-bg",
|
||||
"@popover-bg": "#fff",
|
||||
"@popover-max-width": "276px",
|
||||
"@popover-border-color": "rgba(0,0,0,.2)",
|
||||
"@popover-fallback-border-color": "#ccc",
|
||||
"@popover-title-bg": "darken(@popover-bg, 3%)",
|
||||
"@popover-arrow-width": "10px",
|
||||
"@popover-arrow-color": "#fff",
|
||||
"@popover-arrow-outer-width": "(@popover-arrow-width + 1)",
|
||||
"@popover-arrow-outer-color": "fadein(@popover-border-color, 5%)",
|
||||
"@popover-arrow-outer-fallback-color": "darken(@popover-fallback-border-color, 20%)",
|
||||
"@label-default-bg": "@gray-light",
|
||||
"@label-primary-bg": "@brand-primary",
|
||||
"@label-success-bg": "@brand-success",
|
||||
"@label-info-bg": "@brand-info",
|
||||
"@label-warning-bg": "@brand-warning",
|
||||
"@label-danger-bg": "@brand-danger",
|
||||
"@label-color": "#fff",
|
||||
"@label-link-hover-color": "#fff",
|
||||
"@modal-inner-padding": "20px",
|
||||
"@modal-title-padding": "15px",
|
||||
"@modal-title-line-height": "@line-height-base",
|
||||
"@modal-content-bg": "#fff",
|
||||
"@modal-content-border-color": "rgba(0,0,0,.2)",
|
||||
"@modal-content-fallback-border-color": "#999",
|
||||
"@modal-backdrop-bg": "#000",
|
||||
"@modal-backdrop-opacity": ".5",
|
||||
"@modal-header-border-color": "#e5e5e5",
|
||||
"@modal-footer-border-color": "@modal-header-border-color",
|
||||
"@modal-lg": "900px",
|
||||
"@modal-md": "600px",
|
||||
"@modal-sm": "300px",
|
||||
"@alert-padding": "15px",
|
||||
"@alert-border-radius": "@border-radius-base",
|
||||
"@alert-link-font-weight": "bold",
|
||||
"@alert-success-bg": "@state-success-bg",
|
||||
"@alert-success-text": "@state-success-text",
|
||||
"@alert-success-border": "@state-success-border",
|
||||
"@alert-info-bg": "@state-info-bg",
|
||||
"@alert-info-text": "@state-info-text",
|
||||
"@alert-info-border": "@state-info-border",
|
||||
"@alert-warning-bg": "@state-warning-bg",
|
||||
"@alert-warning-text": "@state-warning-text",
|
||||
"@alert-warning-border": "@state-warning-border",
|
||||
"@alert-danger-bg": "@state-danger-bg",
|
||||
"@alert-danger-text": "@state-danger-text",
|
||||
"@alert-danger-border": "@state-danger-border",
|
||||
"@progress-bg": "#f5f5f5",
|
||||
"@progress-bar-color": "#fff",
|
||||
"@progress-bar-bg": "@brand-primary",
|
||||
"@progress-bar-success-bg": "@brand-success",
|
||||
"@progress-bar-warning-bg": "@brand-warning",
|
||||
"@progress-bar-danger-bg": "@brand-danger",
|
||||
"@progress-bar-info-bg": "@brand-info",
|
||||
"@list-group-bg": "#fff",
|
||||
"@list-group-border": "#ddd",
|
||||
"@list-group-border-radius": "@border-radius-base",
|
||||
"@list-group-hover-bg": "#f5f5f5",
|
||||
"@list-group-active-color": "@component-active-color",
|
||||
"@list-group-active-bg": "@component-active-bg",
|
||||
"@list-group-active-border": "@list-group-active-bg",
|
||||
"@list-group-active-text-color": "lighten(@list-group-active-bg, 40%)",
|
||||
"@list-group-link-color": "#555",
|
||||
"@list-group-link-heading-color": "#333",
|
||||
"@panel-bg": "#fff",
|
||||
"@panel-body-padding": "15px",
|
||||
"@panel-border-radius": "@border-radius-base",
|
||||
"@panel-inner-border": "#ddd",
|
||||
"@panel-footer-bg": "#f5f5f5",
|
||||
"@panel-default-text": "@gray-dark",
|
||||
"@panel-default-border": "#ddd",
|
||||
"@panel-default-heading-bg": "#f5f5f5",
|
||||
"@panel-primary-text": "#fff",
|
||||
"@panel-primary-border": "@brand-primary",
|
||||
"@panel-primary-heading-bg": "@brand-primary",
|
||||
"@panel-success-text": "@state-success-text",
|
||||
"@panel-success-border": "@state-success-border",
|
||||
"@panel-success-heading-bg": "@state-success-bg",
|
||||
"@panel-info-text": "@state-info-text",
|
||||
"@panel-info-border": "@state-info-border",
|
||||
"@panel-info-heading-bg": "@state-info-bg",
|
||||
"@panel-warning-text": "@state-warning-text",
|
||||
"@panel-warning-border": "@state-warning-border",
|
||||
"@panel-warning-heading-bg": "@state-warning-bg",
|
||||
"@panel-danger-text": "@state-danger-text",
|
||||
"@panel-danger-border": "@state-danger-border",
|
||||
"@panel-danger-heading-bg": "@state-danger-bg",
|
||||
"@thumbnail-padding": "4px",
|
||||
"@thumbnail-bg": "@body-bg",
|
||||
"@thumbnail-border": "#ddd",
|
||||
"@thumbnail-border-radius": "@border-radius-base",
|
||||
"@thumbnail-caption-color": "@text-color",
|
||||
"@thumbnail-caption-padding": "9px",
|
||||
"@well-bg": "#f5f5f5",
|
||||
"@well-border": "darken(@well-bg, 7%)",
|
||||
"@badge-color": "#fff",
|
||||
"@badge-link-hover-color": "#fff",
|
||||
"@badge-bg": "@gray-light",
|
||||
"@badge-active-color": "@link-color",
|
||||
"@badge-active-bg": "#fff",
|
||||
"@badge-font-weight": "bold",
|
||||
"@badge-border-radius": "10px",
|
||||
"@breadcrumb-padding-vertical": "8px",
|
||||
"@breadcrumb-padding-horizontal": "15px",
|
||||
"@breadcrumb-bg": "#f5f5f5",
|
||||
"@breadcrumb-color": "#ccc",
|
||||
"@breadcrumb-active-color": "@gray-light",
|
||||
"@breadcrumb-separator": "\"/\"",
|
||||
"@carousel-text-shadow": "0 1px 2px rgba(0,0,0,.6)",
|
||||
"@carousel-control-color": "#fff",
|
||||
"@carousel-control-width": "15%",
|
||||
"@carousel-control-opacity": ".5",
|
||||
"@carousel-control-font-size": "20px",
|
||||
"@carousel-indicator-active-bg": "#fff",
|
||||
"@carousel-indicator-border-color": "#fff",
|
||||
"@carousel-caption-color": "#fff",
|
||||
"@close-font-weight": "bold",
|
||||
"@close-color": "#000",
|
||||
"@close-text-shadow": "0 1px 0 #fff",
|
||||
"@code-color": "#c7254e",
|
||||
"@code-bg": "#f9f2f4",
|
||||
"@kbd-color": "#fff",
|
||||
"@kbd-bg": "#333",
|
||||
"@pre-bg": "#f5f5f5",
|
||||
"@pre-color": "@gray-dark",
|
||||
"@pre-border-color": "#ccc",
|
||||
"@pre-scrollable-max-height": "340px",
|
||||
"@text-muted": "@gray-light",
|
||||
"@abbr-border-color": "@gray-light",
|
||||
"@headings-small-color": "@gray-light",
|
||||
"@blockquote-small-color": "@gray-light",
|
||||
"@blockquote-font-size": "(@font-size-base * 1.25)",
|
||||
"@blockquote-border-color": "@gray-lighter",
|
||||
"@page-header-border-color": "@gray-lighter",
|
||||
"@hr-border": "@gray-lighter",
|
||||
"@component-offset-horizontal": "180px"
|
||||
},
|
||||
"css": [
|
||||
"print.less",
|
||||
"type.less",
|
||||
"forms.less",
|
||||
"buttons.less",
|
||||
"input-groups.less",
|
||||
"alerts.less",
|
||||
"close.less",
|
||||
"component-animations.less",
|
||||
"modals.less",
|
||||
"utilities.less",
|
||||
"responsive-utilities.less"
|
||||
],
|
||||
"js": [
|
||||
"alert.js",
|
||||
"modal.js",
|
||||
"transition.js"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
requires 'Mojolicious';
|
||||
requires 'Data::Validate::URI';
|
||||
requires 'Mojolicious::Plugin::I18N';
|
||||
requires 'ORLite';
|
||||
requires 'MIME::Types';
|
||||
@@ -0,0 +1,416 @@
|
||||
# carton snapshot format: version 1.0
|
||||
DISTRIBUTIONS
|
||||
DBD-SQLite-1.40
|
||||
pathname: I/IS/ISHIGAKI/DBD-SQLite-1.40.tar.gz
|
||||
provides:
|
||||
DBD::SQLite 1.40
|
||||
DBD::SQLite::_WriteOnceHash 1.40
|
||||
DBD::SQLite::db 1.40
|
||||
DBD::SQLite::dr 1.40
|
||||
requirements:
|
||||
DBI 1.57
|
||||
ExtUtils::MakeMaker 6.48
|
||||
File::Spec 0.82
|
||||
Test::Builder 0.86
|
||||
Test::More 0.47
|
||||
Tie::Hash 0
|
||||
perl 5.006
|
||||
DBI-1.631
|
||||
pathname: T/TI/TIMB/DBI-1.631.tar.gz
|
||||
provides:
|
||||
Bundle::DBI 12.008696
|
||||
DBD::DBM 0.08
|
||||
DBD::DBM::Statement 0.08
|
||||
DBD::DBM::Table 0.08
|
||||
DBD::DBM::db 0.08
|
||||
DBD::DBM::dr 0.08
|
||||
DBD::DBM::st 0.08
|
||||
DBD::ExampleP 12.014311
|
||||
DBD::ExampleP::db 12.014311
|
||||
DBD::ExampleP::dr 12.014311
|
||||
DBD::ExampleP::st 12.014311
|
||||
DBD::File 0.42
|
||||
DBD::File::DataSource::File 0.42
|
||||
DBD::File::DataSource::Stream 0.42
|
||||
DBD::File::Statement 0.42
|
||||
DBD::File::Table 0.42
|
||||
DBD::File::TableSource::FileSystem 0.42
|
||||
DBD::File::db 0.42
|
||||
DBD::File::dr 0.42
|
||||
DBD::File::st 0.42
|
||||
DBD::Gofer 0.015327
|
||||
DBD::Gofer::Policy::Base 0.010088
|
||||
DBD::Gofer::Policy::classic 0.010088
|
||||
DBD::Gofer::Policy::pedantic 0.010088
|
||||
DBD::Gofer::Policy::rush 0.010088
|
||||
DBD::Gofer::Transport::Base 0.014121
|
||||
DBD::Gofer::Transport::corostream undef
|
||||
DBD::Gofer::Transport::null 0.010088
|
||||
DBD::Gofer::Transport::pipeone 0.010088
|
||||
DBD::Gofer::Transport::stream 0.014599
|
||||
DBD::Gofer::db 0.015327
|
||||
DBD::Gofer::dr 0.015327
|
||||
DBD::Gofer::st 0.015327
|
||||
DBD::NullP 12.014715
|
||||
DBD::NullP::db 12.014715
|
||||
DBD::NullP::dr 12.014715
|
||||
DBD::NullP::st 12.014715
|
||||
DBD::Proxy 0.2004
|
||||
DBD::Proxy::RPC::PlClient 0.2004
|
||||
DBD::Proxy::db 0.2004
|
||||
DBD::Proxy::dr 0.2004
|
||||
DBD::Proxy::st 0.2004
|
||||
DBD::Sponge 12.010003
|
||||
DBD::Sponge::db 12.010003
|
||||
DBD::Sponge::dr 12.010003
|
||||
DBD::Sponge::st 12.010003
|
||||
DBDI 12.015129
|
||||
DBI 1.631
|
||||
DBI::Const::GetInfo::ANSI 2.008697
|
||||
DBI::Const::GetInfo::ODBC 2.011374
|
||||
DBI::Const::GetInfoReturn 2.008697
|
||||
DBI::Const::GetInfoType 2.008697
|
||||
DBI::DBD 12.015129
|
||||
DBI::DBD::Metadata 2.014214
|
||||
DBI::DBD::SqlEngine 0.06
|
||||
DBI::DBD::SqlEngine::DataSource 0.06
|
||||
DBI::DBD::SqlEngine::Statement 0.06
|
||||
DBI::DBD::SqlEngine::Table 0.06
|
||||
DBI::DBD::SqlEngine::TableSource 0.06
|
||||
DBI::DBD::SqlEngine::TieMeta 0.06
|
||||
DBI::DBD::SqlEngine::TieTables 0.06
|
||||
DBI::DBD::SqlEngine::db 0.06
|
||||
DBI::DBD::SqlEngine::dr 0.06
|
||||
DBI::DBD::SqlEngine::st 0.06
|
||||
DBI::FAQ 1.014935
|
||||
DBI::Gofer::Execute 0.014283
|
||||
DBI::Gofer::Request 0.012537
|
||||
DBI::Gofer::Response 0.011566
|
||||
DBI::Gofer::Serializer::Base 0.009950
|
||||
DBI::Gofer::Serializer::DataDumper 0.009950
|
||||
DBI::Gofer::Serializer::Storable 0.015586
|
||||
DBI::Gofer::Transport::Base 0.012537
|
||||
DBI::Gofer::Transport::pipeone 0.012537
|
||||
DBI::Gofer::Transport::stream 0.012537
|
||||
DBI::Profile 2.015065
|
||||
DBI::ProfileData 2.010008
|
||||
DBI::ProfileDumper 2.015325
|
||||
DBI::ProfileDumper::Apache 2.014121
|
||||
DBI::ProfileSubs 0.009396
|
||||
DBI::ProxyServer 0.3005
|
||||
DBI::ProxyServer::db 0.3005
|
||||
DBI::ProxyServer::dr 0.3005
|
||||
DBI::ProxyServer::st 0.3005
|
||||
DBI::SQL::Nano 1.015544
|
||||
DBI::SQL::Nano::Statement_ 1.015544
|
||||
DBI::SQL::Nano::Table_ 1.015544
|
||||
DBI::Util::CacheMemory 0.010315
|
||||
DBI::Util::_accessor 0.009479
|
||||
DBI::common 1.631
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 6.48
|
||||
Test::Simple 0.90
|
||||
perl 5.008
|
||||
Data-Validate-Domain-0.10
|
||||
pathname: N/NE/NEELY/Data-Validate-Domain-0.10.tar.gz
|
||||
provides:
|
||||
Data::Validate::Domain 0.10
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Net::Domain::TLD 1.62
|
||||
Test::More 0
|
||||
Data-Validate-IP-0.22
|
||||
pathname: D/DR/DROLSKY/Data-Validate-IP-0.22.tar.gz
|
||||
provides:
|
||||
Data::Validate::IP 0.22
|
||||
requirements:
|
||||
Exporter 0
|
||||
ExtUtils::MakeMaker 6.30
|
||||
NetAddr::IP 4
|
||||
Scalar::Util 0
|
||||
strict 0
|
||||
warnings 0
|
||||
Data-Validate-URI-0.06
|
||||
pathname: S/SO/SONNEN/Data-Validate-URI-0.06.tar.gz
|
||||
provides:
|
||||
Data::Validate::URI 0.06
|
||||
requirements:
|
||||
Data::Validate::Domain 0
|
||||
Data::Validate::IP 0
|
||||
ExtUtils::MakeMaker 0
|
||||
File-Remove-1.52
|
||||
pathname: A/AD/ADAMK/File-Remove-1.52.tar.gz
|
||||
provides:
|
||||
File::Remove 1.52
|
||||
requirements:
|
||||
Cwd 3.29
|
||||
ExtUtils::MakeMaker 6.36
|
||||
File::Spec 3.29
|
||||
Test::More 0.42
|
||||
perl 5.00503
|
||||
IPC-Run3-0.046
|
||||
pathname: R/RJ/RJBS/IPC-Run3-0.046.tar.gz
|
||||
provides:
|
||||
IPC::Run3 0.046
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Test::More 0.31
|
||||
Time::HiRes 0
|
||||
MIME-Types-2.04
|
||||
pathname: M/MA/MARKOV/MIME-Types-2.04.tar.gz
|
||||
provides:
|
||||
MIME::Type 2.04
|
||||
MIME::Types 2.04
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
File::Basename 0
|
||||
File::Spec 0
|
||||
Test::More 0.47
|
||||
Module-Build-0.4205
|
||||
pathname: L/LE/LEONT/Module-Build-0.4205.tar.gz
|
||||
provides:
|
||||
Module::Build 0.4205
|
||||
Module::Build::Base 0.4205
|
||||
Module::Build::Compat 0.4205
|
||||
Module::Build::Config 0.4205
|
||||
Module::Build::Cookbook 0.4205
|
||||
Module::Build::Dumper 0.4205
|
||||
Module::Build::ModuleInfo 0.4205
|
||||
Module::Build::Notes 0.4205
|
||||
Module::Build::PPMMaker 0.4205
|
||||
Module::Build::Platform::Default 0.4205
|
||||
Module::Build::Platform::MacOS 0.4205
|
||||
Module::Build::Platform::Unix 0.4205
|
||||
Module::Build::Platform::VMS 0.4205
|
||||
Module::Build::Platform::VOS 0.4205
|
||||
Module::Build::Platform::Windows 0.4205
|
||||
Module::Build::Platform::aix 0.4205
|
||||
Module::Build::Platform::cygwin 0.4205
|
||||
Module::Build::Platform::darwin 0.4205
|
||||
Module::Build::Platform::os2 0.4205
|
||||
Module::Build::PodParser 0.4205
|
||||
Module::Build::Version 0.87
|
||||
Module::Build::YAML 1.41
|
||||
inc::latest 0.4205
|
||||
inc::latest::private 0.4205
|
||||
requirements:
|
||||
CPAN::Meta 2.110420
|
||||
CPAN::Meta::YAML 0.003
|
||||
Cwd 0
|
||||
Data::Dumper 0
|
||||
ExtUtils::CBuilder 0.27
|
||||
ExtUtils::Install 0
|
||||
ExtUtils::Manifest 0
|
||||
ExtUtils::Mkbootstrap 0
|
||||
ExtUtils::ParseXS 2.21
|
||||
File::Basename 0
|
||||
File::Compare 0
|
||||
File::Copy 0
|
||||
File::Find 0
|
||||
File::Path 0
|
||||
File::Spec 0.82
|
||||
File::Temp 0.15
|
||||
Getopt::Long 0
|
||||
Module::Metadata 1.000002
|
||||
Parse::CPAN::Meta 1.4401
|
||||
Perl::OSType 1
|
||||
Pod::Man 2.17
|
||||
Test::Harness 3.16
|
||||
Test::More 0.49
|
||||
Text::Abbrev 0
|
||||
Text::ParseWords 0
|
||||
perl 5.006001
|
||||
version 0.87
|
||||
Mojolicious-4.79
|
||||
pathname: S/SR/SRI/Mojolicious-4.79.tar.gz
|
||||
provides:
|
||||
Mojo undef
|
||||
Mojo::Asset undef
|
||||
Mojo::Asset::File undef
|
||||
Mojo::Asset::Memory undef
|
||||
Mojo::Base undef
|
||||
Mojo::ByteStream undef
|
||||
Mojo::Cache undef
|
||||
Mojo::Collection undef
|
||||
Mojo::Content undef
|
||||
Mojo::Content::MultiPart undef
|
||||
Mojo::Content::Single undef
|
||||
Mojo::Cookie undef
|
||||
Mojo::Cookie::Request undef
|
||||
Mojo::Cookie::Response undef
|
||||
Mojo::DOM undef
|
||||
Mojo::DOM::CSS undef
|
||||
Mojo::DOM::HTML undef
|
||||
Mojo::DOM::Node undef
|
||||
Mojo::Date undef
|
||||
Mojo::EventEmitter undef
|
||||
Mojo::Exception undef
|
||||
Mojo::Headers undef
|
||||
Mojo::HelloWorld undef
|
||||
Mojo::Home undef
|
||||
Mojo::IOLoop undef
|
||||
Mojo::IOLoop::Client undef
|
||||
Mojo::IOLoop::Delay undef
|
||||
Mojo::IOLoop::Server undef
|
||||
Mojo::IOLoop::Stream undef
|
||||
Mojo::JSON undef
|
||||
Mojo::JSON::Pointer undef
|
||||
Mojo::JSON::_Bool undef
|
||||
Mojo::Loader undef
|
||||
Mojo::Log undef
|
||||
Mojo::Message undef
|
||||
Mojo::Message::Request undef
|
||||
Mojo::Message::Response undef
|
||||
Mojo::Parameters undef
|
||||
Mojo::Path undef
|
||||
Mojo::Reactor undef
|
||||
Mojo::Reactor::EV undef
|
||||
Mojo::Reactor::Poll undef
|
||||
Mojo::Server undef
|
||||
Mojo::Server::CGI undef
|
||||
Mojo::Server::Daemon undef
|
||||
Mojo::Server::Hypnotoad undef
|
||||
Mojo::Server::Morbo undef
|
||||
Mojo::Server::PSGI undef
|
||||
Mojo::Server::PSGI::_IO undef
|
||||
Mojo::Server::Prefork undef
|
||||
Mojo::Template undef
|
||||
Mojo::Transaction undef
|
||||
Mojo::Transaction::HTTP undef
|
||||
Mojo::Transaction::WebSocket undef
|
||||
Mojo::URL undef
|
||||
Mojo::Upload undef
|
||||
Mojo::UserAgent undef
|
||||
Mojo::UserAgent::CookieJar undef
|
||||
Mojo::UserAgent::Proxy undef
|
||||
Mojo::UserAgent::Server undef
|
||||
Mojo::UserAgent::Transactor undef
|
||||
Mojo::Util undef
|
||||
Mojolicious 4.79
|
||||
Mojolicious::Command undef
|
||||
Mojolicious::Command::cgi undef
|
||||
Mojolicious::Command::cpanify undef
|
||||
Mojolicious::Command::daemon undef
|
||||
Mojolicious::Command::eval undef
|
||||
Mojolicious::Command::generate undef
|
||||
Mojolicious::Command::generate::app undef
|
||||
Mojolicious::Command::generate::lite_app undef
|
||||
Mojolicious::Command::generate::makefile undef
|
||||
Mojolicious::Command::generate::plugin 0.01
|
||||
Mojolicious::Command::get undef
|
||||
Mojolicious::Command::inflate undef
|
||||
Mojolicious::Command::prefork undef
|
||||
Mojolicious::Command::psgi undef
|
||||
Mojolicious::Command::routes undef
|
||||
Mojolicious::Command::test undef
|
||||
Mojolicious::Command::version undef
|
||||
Mojolicious::Commands undef
|
||||
Mojolicious::Controller undef
|
||||
Mojolicious::Lite undef
|
||||
Mojolicious::Plugin undef
|
||||
Mojolicious::Plugin::Charset undef
|
||||
Mojolicious::Plugin::Config undef
|
||||
Mojolicious::Plugin::Config::Sandbox undef
|
||||
Mojolicious::Plugin::DefaultHelpers undef
|
||||
Mojolicious::Plugin::EPLRenderer undef
|
||||
Mojolicious::Plugin::EPRenderer undef
|
||||
Mojolicious::Plugin::HeaderCondition undef
|
||||
Mojolicious::Plugin::JSONConfig undef
|
||||
Mojolicious::Plugin::Mount undef
|
||||
Mojolicious::Plugin::PODRenderer undef
|
||||
Mojolicious::Plugin::TagHelpers undef
|
||||
Mojolicious::Plugins undef
|
||||
Mojolicious::Renderer undef
|
||||
Mojolicious::Routes undef
|
||||
Mojolicious::Routes::Match undef
|
||||
Mojolicious::Routes::Pattern undef
|
||||
Mojolicious::Routes::Route undef
|
||||
Mojolicious::Sessions undef
|
||||
Mojolicious::Static undef
|
||||
Mojolicious::Types undef
|
||||
Mojolicious::Validator undef
|
||||
Mojolicious::Validator::Validation undef
|
||||
Test::Mojo undef
|
||||
ojo undef
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Mojolicious-Plugin-I18N-1.21
|
||||
pathname: S/SH/SHARIFULN/Mojolicious-Plugin-I18N-1.21.tar.gz
|
||||
provides:
|
||||
Mojolicious::Plugin::I18N 1.21
|
||||
requirements:
|
||||
I18N::LangTags 0.35
|
||||
Module::Build 0.42
|
||||
Mojolicious 4
|
||||
Test::More 0
|
||||
perl 5.010001
|
||||
Net-Domain-TLD-1.70
|
||||
pathname: A/AL/ALEXP/Net-Domain-TLD-1.70.tar.gz
|
||||
provides:
|
||||
Net::Domain::TLD 1.70
|
||||
requirements:
|
||||
Carp 0
|
||||
ExtUtils::MakeMaker 0
|
||||
Storable 0
|
||||
NetAddr-IP-4.072
|
||||
pathname: M/MI/MIKER/NetAddr-IP-4.072.tar.gz
|
||||
provides:
|
||||
NetAddr::IP 4.072
|
||||
NetAddr::IP::InetBase 0.08
|
||||
NetAddr::IP::Lite 1.52
|
||||
NetAddr::IP::Util 1.51
|
||||
NetAddr::IP::UtilPP 1.09
|
||||
NetAddr::IP::UtilPolluted 1.51
|
||||
NetAddr::IP::Util_IS 1
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 0
|
||||
Test::More 0
|
||||
ORLite-1.98
|
||||
pathname: A/AD/ADAMK/ORLite-1.98.tar.gz
|
||||
provides:
|
||||
ORLite 1.98
|
||||
requirements:
|
||||
DBD::SQLite 1.27
|
||||
DBI 1.607
|
||||
ExtUtils::MakeMaker 6.59
|
||||
File::Path 2.08
|
||||
File::Remove 1.40
|
||||
File::Spec 0.80
|
||||
File::Temp 0.20
|
||||
Params::Util 1.00
|
||||
Test::More 0.47
|
||||
Test::Script 1.06
|
||||
perl 5.006
|
||||
Params-Util-1.07
|
||||
pathname: A/AD/ADAMK/Params-Util-1.07.tar.gz
|
||||
provides:
|
||||
Params::Util 1.07
|
||||
requirements:
|
||||
ExtUtils::CBuilder 0.27
|
||||
ExtUtils::MakeMaker 6.52
|
||||
File::Spec 0.80
|
||||
Scalar::Util 1.18
|
||||
Test::More 0.42
|
||||
perl 5.00503
|
||||
Probe-Perl-0.03
|
||||
pathname: K/KW/KWILLIAMS/Probe-Perl-0.03.tar.gz
|
||||
provides:
|
||||
Probe::Perl 0.03
|
||||
requirements:
|
||||
Config 0
|
||||
ExtUtils::MakeMaker 6.30
|
||||
File::Spec 0
|
||||
strict 0
|
||||
Test-Script-1.07
|
||||
pathname: A/AD/ADAMK/Test-Script-1.07.tar.gz
|
||||
provides:
|
||||
Test::Script 1.07
|
||||
requirements:
|
||||
ExtUtils::MakeMaker 6.42
|
||||
File::Spec 0.80
|
||||
IPC::Run3 0.034
|
||||
Probe::Perl 0.01
|
||||
Test::Builder 0.32
|
||||
Test::Builder::Tester 1.02
|
||||
Test::More 0.62
|
||||
blib 0
|
||||
+248
-7
@@ -1,18 +1,259 @@
|
||||
package Lutim;
|
||||
use Mojo::Base 'Mojolicious';
|
||||
use LutimModel;
|
||||
use MIME::Types 'by_suffix';
|
||||
use Mojo::Util qw(quote);
|
||||
use Mojo::JSON;;
|
||||
use Digest::file qw(digest_file_hex);
|
||||
|
||||
# This method will run once at server start
|
||||
sub startup {
|
||||
my $self = shift;
|
||||
my $self = shift;
|
||||
|
||||
# Documentation browser under "/perldoc"
|
||||
$self->plugin('PODRenderer');
|
||||
$self->plugin('I18N');
|
||||
|
||||
# Router
|
||||
my $r = $self->routes;
|
||||
my $config = $self->plugin('Config');
|
||||
|
||||
# Normal route to controller
|
||||
$r->get('/')->to('example#welcome');
|
||||
# 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}));
|
||||
|
||||
$self->secrets($config->{secrets});
|
||||
|
||||
$self->helper(
|
||||
render_file => sub {
|
||||
my $c = shift;
|
||||
my ($filename, $path, $mediatype, $dl) = @_;
|
||||
|
||||
$filename = quote($filename);
|
||||
|
||||
my $asset;
|
||||
unless ( -f $path && -r _ ) {
|
||||
$c->app->log->error("Cannot read file [$path]. error [$!]");
|
||||
$c->flash(
|
||||
msg => $c->l('image_not_found')
|
||||
);
|
||||
return 500;
|
||||
}
|
||||
$asset = Mojo::Asset::File->new(path => $path);
|
||||
my $headers = Mojo::Headers->new();
|
||||
$headers->add('Content-Type' => $mediatype.';name='.$filename);
|
||||
$headers->add('Content-Disposition' => $dl.';filename='.$filename);
|
||||
$headers->add('Content-Length' => $asset->size);
|
||||
$c->res->content->headers($headers);
|
||||
$c->res->content->asset($asset);
|
||||
return $c->rendered(200);
|
||||
}
|
||||
);
|
||||
|
||||
$self->helper(
|
||||
provisionning => sub {
|
||||
my $c = shift;
|
||||
|
||||
# Create some short patterns for provisionning
|
||||
if (LutimModel::Lutim->count('WHERE path IS NULL') < $c->config->{provisionning}) {
|
||||
for (my $i = 0; $i < $c->config->{provis_step}; $i++) {
|
||||
if (LutimModel->begin) {
|
||||
my $short;
|
||||
do {
|
||||
$short= $c->shortener($c->config->{length});
|
||||
} while (LutimModel::Lutim->count('WHERE short = ?', $short));
|
||||
|
||||
LutimModel::Lutim->create(
|
||||
short => $short,
|
||||
counter => 0,
|
||||
enabled => 1,
|
||||
delete_at_first_view => 0,
|
||||
delete_at_day => 0
|
||||
);
|
||||
LutimModel->commit;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$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;
|
||||
}
|
||||
);
|
||||
|
||||
$self->defaults(layout => 'default');
|
||||
|
||||
$self->provisionning();
|
||||
|
||||
# Router
|
||||
my $r = $self->routes;
|
||||
|
||||
$r->get('/' => sub {
|
||||
my $c = shift;
|
||||
|
||||
$c->render( template => 'index');
|
||||
|
||||
# Check provisionning
|
||||
$c->on(finish => sub {
|
||||
shift->provisionning();
|
||||
}
|
||||
);
|
||||
}
|
||||
)->name('index');
|
||||
|
||||
$r->post('/' => sub {
|
||||
my $c = shift;
|
||||
my $upload = $c->param('file');
|
||||
|
||||
my ($mediatype, $encoding) = by_suffix $upload->filename;
|
||||
|
||||
my ($msg, $short);
|
||||
# Check file type
|
||||
if (index($mediatype, 'image') >= 0) {
|
||||
# Create directory if needed
|
||||
mkdir('files', 0700) unless (-d 'files');
|
||||
|
||||
if(LutimModel->begin) {
|
||||
my @records = LutimModel::Lutim->select('WHERE path IS NULL LIMIT 1');
|
||||
if (scalar(@records)) {
|
||||
# Save file and create record
|
||||
my $filename = $upload->filename;
|
||||
my $ext = ($filename =~ m/([^.]+)$/)[0];
|
||||
my $path = 'files/'.$records[0]->short.'.'.$ext;
|
||||
$upload->move_to($path);
|
||||
$records[0]->update(
|
||||
path => $path,
|
||||
filename => $filename,
|
||||
mediatype => $mediatype,
|
||||
footprint => digest_file_hex($path, 'SHA-512'),
|
||||
enabled => 1,
|
||||
delete_at_day => ($c->param('delete-day')) ? 1 : 0,
|
||||
delete_at_first_view => ($c->param('first-view')) ? 1 : 0,
|
||||
created_at => time(),
|
||||
created_by => $c->tx->remote_address
|
||||
);
|
||||
|
||||
# Log image creation
|
||||
$c->app->log->info('[CREATION] '.$c->tx->remote_address.' pushed '.$filename.' (path: '.$path.')');
|
||||
|
||||
# Give url to user
|
||||
$short = $records[0]->short;
|
||||
} else {
|
||||
# Houston, we have a problem
|
||||
$msg = $c->l('no_more_short', $c->config->{contact});
|
||||
}
|
||||
}
|
||||
LutimModel->commit;
|
||||
} else {
|
||||
$msg = $c->l('no_valid_file', $upload->filename);
|
||||
}
|
||||
|
||||
# Check provisionning
|
||||
$c->on(finish => sub {
|
||||
shift->provisionning();
|
||||
}
|
||||
);
|
||||
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
if (defined($short)) {
|
||||
$msg = {
|
||||
filename => $upload->filename,
|
||||
short => $short
|
||||
};
|
||||
} else {
|
||||
$msg = {
|
||||
filename => $upload->filename,
|
||||
msg => $msg
|
||||
};
|
||||
}
|
||||
$c->render(
|
||||
json => {
|
||||
success => (defined($short)) ? Mojo::JSON->true : Mojo::JSON->false,
|
||||
msg => $msg
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->flash(msg => $msg) if (defined($msg));
|
||||
$c->flash(short => $short) if (defined($short));
|
||||
$c->flash(filename => $upload->filename);
|
||||
$c->redirect_to('/');
|
||||
}
|
||||
}
|
||||
)->name('add');
|
||||
|
||||
$r->get('/:short' => sub {
|
||||
my $c = shift;
|
||||
my $short = $c->param('short');
|
||||
my $dl = (defined($c->param('dl'))) ? 'attachment' : 'inline';
|
||||
|
||||
my @images = LutimModel::Lutim->select('WHERE short = ? AND ENABLED = 1 AND path IS NOT NULL', $short);
|
||||
|
||||
if (scalar(@images)) {
|
||||
if($images[0]->delete_at_day && $images[0]->created_at + 86400 <= time()) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] '.$c->tx->remote_address.' 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);
|
||||
|
||||
# Warn user
|
||||
$c->flash(
|
||||
msg => $c->l('image_not_found')
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
if($c->render_file($images[0]->filename, $images[0]->path, $images[0]->mediatype, $dl) != 500) {
|
||||
# Update counter and check provisionning
|
||||
$c->on(finish => sub {
|
||||
# Log access
|
||||
$c->app->log->info('[VIEW] '.$c->tx->remote_address.' viewed '.$images[0]->filename.' (path: '.$images[0]->path.')');
|
||||
|
||||
# Update record
|
||||
my $counter = $images[0]->counter + 1;
|
||||
$images[0]->update(counter => $counter);
|
||||
|
||||
$images[0]->update(last_access_at => time());
|
||||
$images[0]->update(last_access_by => $c->tx->remote_address);
|
||||
|
||||
# Delete image if needed
|
||||
if ($images[0]->delete_at_first_view) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] '.$c->tx->remote_address.' made '.$images[0]->filename.' removed (path: '.$images[0]->path.')');
|
||||
|
||||
# Delete image
|
||||
unlink $images[0]->path();
|
||||
$images[0]->update(enabled => 0);
|
||||
}
|
||||
|
||||
shift->provisionning();
|
||||
});
|
||||
}
|
||||
} else {
|
||||
@images = LutimModel::Lutim->select('WHERE short = ? AND ENABLED = 0 AND path IS NOT NULL', $short);
|
||||
|
||||
if (scalar(@images)) {
|
||||
# Log access try
|
||||
$c->app->log->info('[NOT FOUND] '.$c->tx->remote_address.' tried to view '.$short.' but it does\'nt exist.');
|
||||
|
||||
# Warn user
|
||||
$c->flash(
|
||||
msg => $c->l('image_not_found')
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
} else {
|
||||
# Image never existed
|
||||
$c->render_not_found;
|
||||
}
|
||||
}
|
||||
})->name('short');
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package Lutim::Example;
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
|
||||
# This action will render a template
|
||||
sub welcome {
|
||||
my $self = shift;
|
||||
|
||||
# Render template "example/welcome.html.ep" with message
|
||||
$self->render(msg => 'Welcome to the Mojolicious real-time web framework!');
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,48 @@
|
||||
package Lutim::I18N::en;
|
||||
use Mojo::Base 'Lutim::I18N';
|
||||
|
||||
my $inf_body = <<EOF;
|
||||
<h4>What is LUTIm?</h4>
|
||||
<p>LUTIm is a free (as in free beer) and anonymous image hosting service. It's also the name of the free (as in free speech) software which provides this service.</p>
|
||||
<p>The images you post on LUTIm can be stored indefinitely or be deleted at first view or after 24 hours.</p>
|
||||
<h4>How does it work?</h4>
|
||||
<p>Drag and drop an image in the appropriate area or use the traditional way to send files and LUTIm will provide you two URLs. One to view the image, the other to directly download it.</p>
|
||||
<p>You can, optionally, request that the image(s) posted on LUTIm to be deleted at first view (or download) or after 24 hours.</p>
|
||||
<h4>Is it really free (as in free beer)?</h4>
|
||||
<p>Yes, it is! On the other side, if you want to support the developer, you can do it via <a href="https://flattr.com/submit/auto?user_id=_SKy_&url=[_1]&title=LUTIm&category=software">Flattr</a> or with <a href="bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim">BitCoin</a>.</p>
|
||||
<h4>Is it really anonymous?</h4>
|
||||
<p>Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send or view an image. Don't panic, it is the case of all sites on which you go!</p>
|
||||
<p>The log files containing the IP address of image viewers are retained for one year while the IP addresse of the image's sender, as the address of the last viewer are permanently retained.</p>
|
||||
<p>If the files are deleted if you ask it while posting it, their SHA512 footprint are retained.</p>
|
||||
<h4>How to report an image?</h4>
|
||||
<p>Please contact the administrator: [_2]</p>
|
||||
<h4>How do you pronounce LUTIm?</h4>
|
||||
<p>Juste like you pronounce the french word <a href="https://fr.wikipedia.org/wiki/Lutin">lutin</a> (/ly.tɛ̃/).</p>
|
||||
<h4>What about the software which provides the service?</h4>
|
||||
<p>The LUTIm software is a <a href="http://en.wikipedia.org/wiki/Free_software">free software</a>, which allows you to download and install it on you own server. Have a look at the <a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL</a> to see what you can do.</p>
|
||||
<p>For more details, see the <a href="https://github.com/ldidry/lutim">Github</a> page of the project.</p>
|
||||
EOF
|
||||
|
||||
our %Lexicon = (
|
||||
'license' => 'License:',
|
||||
'fork-me' => 'Fork me on Github !',
|
||||
'share-twitter' => 'Share on Twitter',
|
||||
'informations' => 'Informations',
|
||||
'informations-body' => $inf_body,
|
||||
'view-link' => 'View link:',
|
||||
'download-link' => 'Download link:',
|
||||
'some-bad' => 'Something bad happened',
|
||||
'delete-first' => 'Delete at first view?',
|
||||
'delete-day' => 'Delete after 24 hours?',
|
||||
'upload_image' => 'Send an image',
|
||||
'image-only' => 'Only images are allowed',
|
||||
'go' => 'Let\'s go!',
|
||||
'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',
|
||||
'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.',
|
||||
);
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,48 @@
|
||||
package Lutim::I18N::fr;
|
||||
use Mojo::Base 'Lutim::I18N';
|
||||
|
||||
my $inf_body = <<EOF;
|
||||
<h4>Qu’est-ce que LUTIm ?</h4>
|
||||
<p>LUTIm est un service gratuit et anonyme d’hébergement d’images. Il s’agit aussi du nom du logiciel (libre) qui fournit ce service.</p>
|
||||
<p>Les images déposées sur LUTIm peuvent être stockées indéfiniment, ou s’effacer dès le premier affichage ou au bout de 24h.</p>
|
||||
<h4>Comment ça marche ?</h4>
|
||||
<p>Faites glisser des images dans la zone prévue à cette effet ou sélectionnez un fichier de façon classique et LUTIm vous fournira deux URLs en retour. Une pour afficher l’image, l’autre pour la télécharger directement.</p>
|
||||
<p>Vous pouvez, de façon optionnelle, demander à ce que la ou les images déposées sur LUTIm soient supprimées après leur premier affichage (ou téléchargement) ou au bout de 24 heures.</p>
|
||||
<h4>C’est vraiment gratuit ?</h4>
|
||||
<p>Oui, ça l’est ! Par contre, si vous avez envie de soutenir le développeur, vous pouvez faire un microdon avec <a href="https://flattr.com/submit/auto?user_id=_SKy_&url=[_1]&title=LUTIm&category=software">Flattr</a> ou en <a href="bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim">BitCoin</a>.</p>
|
||||
<h4>C’est vraiment anonyme ?</h4>
|
||||
<p>Oui, ça l’est ! Par contre, pour des raisons légales, votre adresse IP sera enregistrée lorsque vous enverrez ou consulterez une image.Ne vous affolez pas, c’est de toute façon le cas sur tous les sites sur lesquels vous surfez !</p>
|
||||
<p>Les journaux systèmes contenant l’adresse IP des visiteurs d’une image sont conservés un an, tandis que l’IP de la personne ayant déposé l’image et celle du dernier visiteur de l’image sont stockées de manière définitive.</p>
|
||||
<p>Si les fichiers sont bien supprimés si vous en avez exprimé le choix, leur empreinte SHA512 est toutefois conservée.</p>
|
||||
<h4>Comment peut-on faire pour signaler une image ?</h4>
|
||||
<p>Veuillez contacter l’administrateur : [_2]</p>
|
||||
<h4>Comment doit-on prononcer LUTIm ?</h4>
|
||||
<p>Comme on prononce <a href="https://fr.wikipedia.org/wiki/Lutin">lutin</a> !</p>
|
||||
<h4>Et à propos du logiciel qui fournit le service ?</h4>
|
||||
<p>Le logiciel LUTIm est un <a href="https://fr.wikipedia.org/wiki/Logiciel_libre">logiciel libre</a>, ce qui vous permet de le télécharger et de l’installer sur votre propre serveur. Jetez un coup d’œil à l’<a href="https://www.gnu.org/licenses/agpl-3.0.html">AGPL</a> pour voir quels sont vos droits.</p>
|
||||
<p>Pour plus de détails, consultez la page <a href="https://github.com/ldidry/lutim">Github</a> du projet.</p>
|
||||
EOF
|
||||
|
||||
our %Lexicon = (
|
||||
'license' => 'Licence :',
|
||||
'fork-me' => 'Fork me on Github',
|
||||
'share-twitter' => 'Partager sur Twitter',
|
||||
'informations' => 'Informations',
|
||||
'informations-body' => $inf_body,
|
||||
'view-link' => 'Lien d\'affichage :',
|
||||
'download-link' => 'Lien de téléchargement :',
|
||||
'some-bad' => 'Un problème est survenu',
|
||||
'delete-first' => 'Supprimer au premier accès ?',
|
||||
'delete-day' => 'Supprimer après 24 heures ?',
|
||||
'upload_image' => 'Envoyez une image',
|
||||
'image-only' => 'Seules les images sont acceptées',
|
||||
'go' => 'Allons-y !',
|
||||
'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',
|
||||
'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.'
|
||||
);
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,29 @@
|
||||
package LutimModel;
|
||||
|
||||
# Create database
|
||||
use ORLite {
|
||||
file => 'lutim.db',
|
||||
unicode => 1,
|
||||
create => sub {
|
||||
my $dbh = shift;
|
||||
$dbh->do(
|
||||
'CREATE TABLE lutim (
|
||||
short TEXT PRIMARY KEY,
|
||||
path TEXT,
|
||||
footprint TEXT,
|
||||
enabled INTEGER,
|
||||
mediatype TEXT,
|
||||
filename TEXT,
|
||||
counter INTEGER,
|
||||
delete_at_first_view INTEGER,
|
||||
delete_at_day INTEGER,
|
||||
created_at INTEGER,
|
||||
created_by TEXT,
|
||||
last_access_at INTEGER,
|
||||
last_access_by INTEGER)'
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
@@ -0,0 +1,14 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
{
|
||||
hypnotoad => {
|
||||
listen => ['http://127.0.0.1:8080'],
|
||||
user => 'www-data',
|
||||
group => 'www-data'
|
||||
},
|
||||
contact => 'John Doe, admin[at]example.com',
|
||||
secrets => ['fdjsofjoihrei'], # please provide a random string
|
||||
piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1', #optional, only the piwik image tracker is allowed, no javascript
|
||||
length => 8, # optional
|
||||
provis_step => 5, # optional
|
||||
provisionning => 100 # optional
|
||||
};
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Animation example, for spinners
|
||||
*/
|
||||
.animate-spin {
|
||||
-moz-animation: spin 2s infinite linear;
|
||||
-o-animation: spin 2s infinite linear;
|
||||
-webkit-animation: spin 2s infinite linear;
|
||||
animation: spin 2s infinite linear;
|
||||
display: inline-block;
|
||||
}
|
||||
@-moz-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-webkit-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-o-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@-ms-keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
@keyframes spin {
|
||||
0% {
|
||||
-moz-transform: rotate(0deg);
|
||||
-o-transform: rotate(0deg);
|
||||
-webkit-transform: rotate(0deg);
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
100% {
|
||||
-moz-transform: rotate(359deg);
|
||||
-o-transform: rotate(359deg);
|
||||
-webkit-transform: rotate(359deg);
|
||||
transform: rotate(359deg);
|
||||
}
|
||||
}
|
||||
Vendored
+2624
File diff suppressed because it is too large
Load Diff
Vendored
+7
File diff suppressed because one or more lines are too long
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
|
||||
.icon-bitcoin:before { content: '\e802'; } /* '' */
|
||||
.icon-github-circled:before { content: '\e800'; } /* '' */
|
||||
.icon-touiteur:before { content: '\e801'; } /* '' */
|
||||
.icon-flattr:before { content: '\e803'; } /* '' */
|
||||
Vendored
+58
File diff suppressed because one or more lines are too long
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
|
||||
.icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-github-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-touiteur { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-flattr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
Vendored
+16
@@ -0,0 +1,16 @@
|
||||
[class^="icon-"], [class*=" icon-"] {
|
||||
font-family: 'fontello';
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
|
||||
/* fix buttons height */
|
||||
line-height: 1em;
|
||||
|
||||
/* you can be more comfortable with increased icons size */
|
||||
/* font-size: 120%; */
|
||||
}
|
||||
|
||||
.icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-github-circled { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-touiteur { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-flattr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
Vendored
+56
@@ -0,0 +1,56 @@
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.eot?4658339');
|
||||
src: url('../font/fontello.eot?4658339#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff?4658339') format('woff'),
|
||||
url('../font/fontello.ttf?4658339') format('truetype'),
|
||||
url('../font/fontello.svg?4658339#fontello') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
/* Chrome hack: SVG is rendered more smooth in Windozze. 100% magic, uncomment if you need it. */
|
||||
/* Note, that will break hinting! In other OS-es font will be not as sharp as it could be */
|
||||
/*
|
||||
@media screen and (-webkit-min-device-pixel-ratio:0) {
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.svg?4658339#fontello') format('svg');
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
[class^="icon-"]:before, [class*=" icon-"]:before {
|
||||
font-family: "fontello";
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
speak: none;
|
||||
|
||||
display: inline-block;
|
||||
text-decoration: inherit;
|
||||
width: 1em;
|
||||
margin-right: .2em;
|
||||
text-align: center;
|
||||
/* opacity: .8; */
|
||||
|
||||
/* For safety - reset parent styles, that can break glyph codes*/
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
|
||||
/* fix buttons height, for twitter bootstrap */
|
||||
line-height: 1em;
|
||||
|
||||
/* Animation center compensation - margins should be symmetric */
|
||||
/* remove if not needed */
|
||||
margin-left: .2em;
|
||||
|
||||
/* you can be more comfortable with increased icons size */
|
||||
/* font-size: 120%; */
|
||||
|
||||
/* Uncomment for 3D effect */
|
||||
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
|
||||
}
|
||||
|
||||
.icon-bitcoin:before { content: '\e802'; } /* '' */
|
||||
.icon-github-circled:before { content: '\e800'; } /* '' */
|
||||
.icon-touiteur:before { content: '\e801'; } /* '' */
|
||||
.icon-flattr:before { content: '\e803'; } /* '' */
|
||||
@@ -0,0 +1,69 @@
|
||||
.uploader
|
||||
{
|
||||
border: 2px dotted #A5A5C7;
|
||||
width: 100%;
|
||||
color: #92AAB0;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
padding: 30px 0px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 200%;
|
||||
|
||||
cursor: default;
|
||||
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.uploader div.or {
|
||||
font-size: 50%;
|
||||
font-weight: bold;
|
||||
color: #C0C0C0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.uploader div.browser label {
|
||||
background-color: #5a7bc2;
|
||||
padding: 5px 15px;
|
||||
color: white;
|
||||
padding: 6px 0px;
|
||||
font-size: 40%;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
width: 300px;
|
||||
margin: 20px auto 0px auto;
|
||||
|
||||
box-shadow: 2px 2px 2px #888888;
|
||||
}
|
||||
|
||||
.uploader div.browser span {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
|
||||
.uploader div.browser input {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
margin: 0;
|
||||
border: solid transparent;
|
||||
border-width: 0 0 100px 200px;
|
||||
opacity: .0;
|
||||
filter: alpha(opacity= 0);
|
||||
-o-transform: translate(250px,-50px) scale(1);
|
||||
-moz-transform: translate(-300px,0) scale(4);
|
||||
direction: ltr;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.uploader div.browser label:hover {
|
||||
background-color: #427fed;
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Copyright (C) 2014 by original authors @ fontello.com</metadata>
|
||||
<defs>
|
||||
<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="bitcoin" unicode="" 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="github-circled" unicode="" 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="" 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="" 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" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
Binary file not shown.
Binary file not shown.
@@ -1,11 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Welcome to the Mojolicious real-time web framework!</title>
|
||||
</head>
|
||||
<body>
|
||||
<h2>Welcome to the Mojolicious real-time web framework!</h2>
|
||||
This is the static document "public/index.html",
|
||||
<a href="/">click here</a> to get back to the start.
|
||||
</body>
|
||||
</html>
|
||||
Vendored
+489
@@ -0,0 +1,489 @@
|
||||
/* ========================================================================
|
||||
* Bootstrap: alert.js v3.1.0
|
||||
* http://getbootstrap.com/javascript/#alerts
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// ALERT CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var dismiss = '[data-dismiss="alert"]'
|
||||
var Alert = function (el) {
|
||||
$(el).on('click', dismiss, this.close)
|
||||
}
|
||||
|
||||
Alert.prototype.close = function (e) {
|
||||
var $this = $(this)
|
||||
var selector = $this.attr('data-target')
|
||||
|
||||
if (!selector) {
|
||||
selector = $this.attr('href')
|
||||
selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
|
||||
}
|
||||
|
||||
var $parent = $(selector)
|
||||
|
||||
if (e) e.preventDefault()
|
||||
|
||||
if (!$parent.length) {
|
||||
$parent = $this.hasClass('alert') ? $this : $this.parent()
|
||||
}
|
||||
|
||||
$parent.trigger(e = $.Event('close.bs.alert'))
|
||||
|
||||
if (e.isDefaultPrevented()) return
|
||||
|
||||
$parent.removeClass('in')
|
||||
|
||||
function removeElement() {
|
||||
$parent.trigger('closed.bs.alert').remove()
|
||||
}
|
||||
|
||||
$.support.transition && $parent.hasClass('fade') ?
|
||||
$parent
|
||||
.one($.support.transition.end, removeElement)
|
||||
.emulateTransitionEnd(150) :
|
||||
removeElement()
|
||||
}
|
||||
|
||||
|
||||
// ALERT PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
var old = $.fn.alert
|
||||
|
||||
$.fn.alert = function (option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.alert')
|
||||
|
||||
if (!data) $this.data('bs.alert', (data = new Alert(this)))
|
||||
if (typeof option == 'string') data[option].call($this)
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.alert.Constructor = Alert
|
||||
|
||||
|
||||
// ALERT NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.alert.noConflict = function () {
|
||||
$.fn.alert = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// ALERT DATA-API
|
||||
// ==============
|
||||
|
||||
$(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: button.js v3.1.0
|
||||
* http://getbootstrap.com/javascript/#buttons
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// BUTTON PUBLIC CLASS DEFINITION
|
||||
// ==============================
|
||||
|
||||
var Button = function (element, options) {
|
||||
this.$element = $(element)
|
||||
this.options = $.extend({}, Button.DEFAULTS, options)
|
||||
this.isLoading = false
|
||||
}
|
||||
|
||||
Button.DEFAULTS = {
|
||||
loadingText: 'loading...'
|
||||
}
|
||||
|
||||
Button.prototype.setState = function (state) {
|
||||
var d = 'disabled'
|
||||
var $el = this.$element
|
||||
var val = $el.is('input') ? 'val' : 'html'
|
||||
var data = $el.data()
|
||||
|
||||
state = state + 'Text'
|
||||
|
||||
if (!data.resetText) $el.data('resetText', $el[val]())
|
||||
|
||||
$el[val](data[state] || this.options[state])
|
||||
|
||||
// push to event loop to allow forms to submit
|
||||
setTimeout($.proxy(function () {
|
||||
if (state == 'loadingText') {
|
||||
this.isLoading = true
|
||||
$el.addClass(d).attr(d, d)
|
||||
} else if (this.isLoading) {
|
||||
this.isLoading = false
|
||||
$el.removeClass(d).removeAttr(d)
|
||||
}
|
||||
}, this), 0)
|
||||
}
|
||||
|
||||
Button.prototype.toggle = function () {
|
||||
var changed = true
|
||||
var $parent = this.$element.closest('[data-toggle="buttons"]')
|
||||
|
||||
if ($parent.length) {
|
||||
var $input = this.$element.find('input')
|
||||
if ($input.prop('type') == 'radio') {
|
||||
if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
|
||||
else $parent.find('.active').removeClass('active')
|
||||
}
|
||||
if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
|
||||
}
|
||||
|
||||
if (changed) this.$element.toggleClass('active')
|
||||
}
|
||||
|
||||
|
||||
// BUTTON PLUGIN DEFINITION
|
||||
// ========================
|
||||
|
||||
var old = $.fn.button
|
||||
|
||||
$.fn.button = function (option) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.button')
|
||||
var options = typeof option == 'object' && option
|
||||
|
||||
if (!data) $this.data('bs.button', (data = new Button(this, options)))
|
||||
|
||||
if (option == 'toggle') data.toggle()
|
||||
else if (option) data.setState(option)
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.button.Constructor = Button
|
||||
|
||||
|
||||
// BUTTON NO CONFLICT
|
||||
// ==================
|
||||
|
||||
$.fn.button.noConflict = function () {
|
||||
$.fn.button = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// BUTTON DATA-API
|
||||
// ===============
|
||||
|
||||
$(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) {
|
||||
var $btn = $(e.target)
|
||||
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
|
||||
$btn.button('toggle')
|
||||
e.preventDefault()
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: modal.js v3.1.0
|
||||
* http://getbootstrap.com/javascript/#modals
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// MODAL CLASS DEFINITION
|
||||
// ======================
|
||||
|
||||
var Modal = function (element, options) {
|
||||
this.options = options
|
||||
this.$element = $(element)
|
||||
this.$backdrop =
|
||||
this.isShown = null
|
||||
|
||||
if (this.options.remote) {
|
||||
this.$element
|
||||
.find('.modal-content')
|
||||
.load(this.options.remote, $.proxy(function () {
|
||||
this.$element.trigger('loaded.bs.modal')
|
||||
}, this))
|
||||
}
|
||||
}
|
||||
|
||||
Modal.DEFAULTS = {
|
||||
backdrop: true,
|
||||
keyboard: true,
|
||||
show: true
|
||||
}
|
||||
|
||||
Modal.prototype.toggle = function (_relatedTarget) {
|
||||
return this[!this.isShown ? 'show' : 'hide'](_relatedTarget)
|
||||
}
|
||||
|
||||
Modal.prototype.show = function (_relatedTarget) {
|
||||
var that = this
|
||||
var e = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (this.isShown || e.isDefaultPrevented()) return
|
||||
|
||||
this.isShown = true
|
||||
|
||||
this.escape()
|
||||
|
||||
this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
|
||||
|
||||
this.backdrop(function () {
|
||||
var transition = $.support.transition && that.$element.hasClass('fade')
|
||||
|
||||
if (!that.$element.parent().length) {
|
||||
that.$element.appendTo(document.body) // don't move modals dom position
|
||||
}
|
||||
|
||||
that.$element
|
||||
.show()
|
||||
.scrollTop(0)
|
||||
|
||||
if (transition) {
|
||||
that.$element[0].offsetWidth // force reflow
|
||||
}
|
||||
|
||||
that.$element
|
||||
.addClass('in')
|
||||
.attr('aria-hidden', false)
|
||||
|
||||
that.enforceFocus()
|
||||
|
||||
var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
|
||||
|
||||
transition ?
|
||||
that.$element.find('.modal-dialog') // wait for modal to slide in
|
||||
.one($.support.transition.end, function () {
|
||||
that.$element.focus().trigger(e)
|
||||
})
|
||||
.emulateTransitionEnd(300) :
|
||||
that.$element.focus().trigger(e)
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.hide = function (e) {
|
||||
if (e) e.preventDefault()
|
||||
|
||||
e = $.Event('hide.bs.modal')
|
||||
|
||||
this.$element.trigger(e)
|
||||
|
||||
if (!this.isShown || e.isDefaultPrevented()) return
|
||||
|
||||
this.isShown = false
|
||||
|
||||
this.escape()
|
||||
|
||||
$(document).off('focusin.bs.modal')
|
||||
|
||||
this.$element
|
||||
.removeClass('in')
|
||||
.attr('aria-hidden', true)
|
||||
.off('click.dismiss.bs.modal')
|
||||
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
this.$element
|
||||
.one($.support.transition.end, $.proxy(this.hideModal, this))
|
||||
.emulateTransitionEnd(300) :
|
||||
this.hideModal()
|
||||
}
|
||||
|
||||
Modal.prototype.enforceFocus = function () {
|
||||
$(document)
|
||||
.off('focusin.bs.modal') // guard against infinite focus loop
|
||||
.on('focusin.bs.modal', $.proxy(function (e) {
|
||||
if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
|
||||
this.$element.focus()
|
||||
}
|
||||
}, this))
|
||||
}
|
||||
|
||||
Modal.prototype.escape = function () {
|
||||
if (this.isShown && this.options.keyboard) {
|
||||
this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
|
||||
e.which == 27 && this.hide()
|
||||
}, this))
|
||||
} else if (!this.isShown) {
|
||||
this.$element.off('keyup.dismiss.bs.modal')
|
||||
}
|
||||
}
|
||||
|
||||
Modal.prototype.hideModal = function () {
|
||||
var that = this
|
||||
this.$element.hide()
|
||||
this.backdrop(function () {
|
||||
that.removeBackdrop()
|
||||
that.$element.trigger('hidden.bs.modal')
|
||||
})
|
||||
}
|
||||
|
||||
Modal.prototype.removeBackdrop = function () {
|
||||
this.$backdrop && this.$backdrop.remove()
|
||||
this.$backdrop = null
|
||||
}
|
||||
|
||||
Modal.prototype.backdrop = function (callback) {
|
||||
var animate = this.$element.hasClass('fade') ? 'fade' : ''
|
||||
|
||||
if (this.isShown && this.options.backdrop) {
|
||||
var doAnimate = $.support.transition && animate
|
||||
|
||||
this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
|
||||
.appendTo(document.body)
|
||||
|
||||
this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
|
||||
if (e.target !== e.currentTarget) return
|
||||
this.options.backdrop == 'static'
|
||||
? this.$element[0].focus.call(this.$element[0])
|
||||
: this.hide.call(this)
|
||||
}, this))
|
||||
|
||||
if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
|
||||
|
||||
this.$backdrop.addClass('in')
|
||||
|
||||
if (!callback) return
|
||||
|
||||
doAnimate ?
|
||||
this.$backdrop
|
||||
.one($.support.transition.end, callback)
|
||||
.emulateTransitionEnd(150) :
|
||||
callback()
|
||||
|
||||
} else if (!this.isShown && this.$backdrop) {
|
||||
this.$backdrop.removeClass('in')
|
||||
|
||||
$.support.transition && this.$element.hasClass('fade') ?
|
||||
this.$backdrop
|
||||
.one($.support.transition.end, callback)
|
||||
.emulateTransitionEnd(150) :
|
||||
callback()
|
||||
|
||||
} else if (callback) {
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MODAL PLUGIN DEFINITION
|
||||
// =======================
|
||||
|
||||
var old = $.fn.modal
|
||||
|
||||
$.fn.modal = function (option, _relatedTarget) {
|
||||
return this.each(function () {
|
||||
var $this = $(this)
|
||||
var data = $this.data('bs.modal')
|
||||
var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
|
||||
|
||||
if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
|
||||
if (typeof option == 'string') data[option](_relatedTarget)
|
||||
else if (options.show) data.show(_relatedTarget)
|
||||
})
|
||||
}
|
||||
|
||||
$.fn.modal.Constructor = Modal
|
||||
|
||||
|
||||
// MODAL NO CONFLICT
|
||||
// =================
|
||||
|
||||
$.fn.modal.noConflict = function () {
|
||||
$.fn.modal = old
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
// MODAL DATA-API
|
||||
// ==============
|
||||
|
||||
$(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
|
||||
var $this = $(this)
|
||||
var href = $this.attr('href')
|
||||
var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) //strip for ie7
|
||||
var option = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
|
||||
|
||||
if ($this.is('a')) e.preventDefault()
|
||||
|
||||
$target
|
||||
.modal(option, this)
|
||||
.one('hide', function () {
|
||||
$this.is(':visible') && $this.focus()
|
||||
})
|
||||
})
|
||||
|
||||
$(document)
|
||||
.on('show.bs.modal', '.modal', function () { $(document.body).addClass('modal-open') })
|
||||
.on('hidden.bs.modal', '.modal', function () { $(document.body).removeClass('modal-open') })
|
||||
|
||||
}(jQuery);
|
||||
|
||||
/* ========================================================================
|
||||
* Bootstrap: transition.js v3.1.0
|
||||
* http://getbootstrap.com/javascript/#transitions
|
||||
* ========================================================================
|
||||
* Copyright 2011-2014 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
||||
* ======================================================================== */
|
||||
|
||||
|
||||
+function ($) {
|
||||
'use strict';
|
||||
|
||||
// CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
|
||||
// ============================================================
|
||||
|
||||
function transitionEnd() {
|
||||
var el = document.createElement('bootstrap')
|
||||
|
||||
var transEndEventNames = {
|
||||
'WebkitTransition' : 'webkitTransitionEnd',
|
||||
'MozTransition' : 'transitionend',
|
||||
'OTransition' : 'oTransitionEnd otransitionend',
|
||||
'transition' : 'transitionend'
|
||||
}
|
||||
|
||||
for (var name in transEndEventNames) {
|
||||
if (el.style[name] !== undefined) {
|
||||
return { end: transEndEventNames[name] }
|
||||
}
|
||||
}
|
||||
|
||||
return false // explicit for ie8 ( ._.)
|
||||
}
|
||||
|
||||
// http://blog.alexmaccaw.com/css-transitions
|
||||
$.fn.emulateTransitionEnd = function (duration) {
|
||||
var called = false, $el = this
|
||||
$(this).one($.support.transition.end, function () { called = true })
|
||||
var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
|
||||
setTimeout(callback, duration)
|
||||
return this
|
||||
}
|
||||
|
||||
$(function () {
|
||||
$.support.transition = transitionEnd()
|
||||
})
|
||||
|
||||
}(jQuery);
|
||||
Vendored
+7
File diff suppressed because one or more lines are too long
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* dmuploader.js - Jquery File Uploader - 0.1
|
||||
* http://www.daniel.com.uy/projects/jquery-file-uploader/
|
||||
*
|
||||
* Copyright (c) 2013 Daniel Morales
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://www.daniel.com.uy/doc/license/
|
||||
*/
|
||||
|
||||
(function($) {
|
||||
var pluginName = 'dmUploader';
|
||||
|
||||
// These are the plugin defaults values
|
||||
var defaults = {
|
||||
url: document.URL,
|
||||
method: 'POST',
|
||||
extraData: {},
|
||||
maxFileSize: 0,
|
||||
allowedTypes: '*',
|
||||
dataType: null,
|
||||
fileName: 'file',
|
||||
onInit: function(){},
|
||||
onFallbackMode: function() {message},
|
||||
onNewFile: function(id, file){},
|
||||
onBeforeUpload: function(id){},
|
||||
onComplete: function(){},
|
||||
onUploadProgress: function(id, percent){},
|
||||
onUploadSuccess: function(id, data){},
|
||||
onUploadError: function(id, message){},
|
||||
onFileTypeError: function(file){},
|
||||
onFileSizeError: function(file){}
|
||||
};
|
||||
|
||||
var DmUploader = function(element, options)
|
||||
{
|
||||
this.element = $(element);
|
||||
|
||||
this.settings = $.extend({}, defaults, options);
|
||||
|
||||
if(!this.checkBrowser()){
|
||||
return false;
|
||||
}
|
||||
|
||||
this.init();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
DmUploader.prototype.checkBrowser = function()
|
||||
{
|
||||
if(window.FormData === undefined){
|
||||
this.settings.onFallbackMode.call(this.element, 'Browser doesn\'t support From API');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if(this.element.find('input[type=file]').length > 0){
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this.checkEvent('drop', this.element) || !this.checkEvent('dragstart', this.element)){
|
||||
this.settings.onFallbackMode.call(this.element, 'Browser doesn\'t support Ajax Drag and Drop');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
DmUploader.prototype.checkEvent = function(eventName, element)
|
||||
{
|
||||
var element = element || document.createElement('div');
|
||||
var eventName = 'on' + eventName;
|
||||
|
||||
var isSupported = eventName in element;
|
||||
|
||||
if(!isSupported){
|
||||
if(!element.setAttribute){
|
||||
element = document.createElement('div');
|
||||
}
|
||||
if(element.setAttribute && element.removeAttribute){
|
||||
element.setAttribute(eventName, '');
|
||||
isSupported = typeof element[eventName] == 'function';
|
||||
|
||||
if(typeof element[eventName] != 'undefined'){
|
||||
element[eventName] = undefined;
|
||||
}
|
||||
element.removeAttribute(eventName);
|
||||
}
|
||||
}
|
||||
|
||||
element = null;
|
||||
return isSupported;
|
||||
};
|
||||
|
||||
DmUploader.prototype.init = function()
|
||||
{
|
||||
var widget = this;
|
||||
|
||||
widget.queue = new Array();
|
||||
widget.queuePos = -1;
|
||||
widget.queueRunning = false;
|
||||
|
||||
// -- Drag and drop event
|
||||
widget.element.on('drop', function (evt){
|
||||
evt.preventDefault();
|
||||
var files = evt.originalEvent.dataTransfer.files;
|
||||
|
||||
widget.queueFiles(files);
|
||||
});
|
||||
|
||||
//-- Optional File input to make a clickable area
|
||||
widget.element.find('input[type=file]').on('change', function(evt){
|
||||
var files = evt.target.files;
|
||||
|
||||
widget.queueFiles(files);
|
||||
|
||||
$(this).val('');
|
||||
});
|
||||
|
||||
this.settings.onInit.call(this.element);
|
||||
};
|
||||
|
||||
DmUploader.prototype.queueFiles = function(files)
|
||||
{
|
||||
var j = this.queue.length;
|
||||
|
||||
for (var i= 0; i < files.length; i++)
|
||||
{
|
||||
var file = files[i];
|
||||
|
||||
// Check file size
|
||||
if((this.settings.maxFileSize > 0) &&
|
||||
(file.size > this.settings.maxFileSize)){
|
||||
|
||||
this.settings.onFileSizeError.call(this.element, file);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check file type
|
||||
if((this.settings.allowedTypes != '*') &&
|
||||
!file.type.match(this.settings.allowedTypes)){
|
||||
|
||||
this.settings.onFileTypeError.call(this.element, file);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
this.queue.push(file);
|
||||
|
||||
var index = this.queue.length - 1;
|
||||
|
||||
this.settings.onNewFile.call(this.element, index, file);
|
||||
}
|
||||
|
||||
// Only start Queue if we haven't!
|
||||
if(this.queueRunning){
|
||||
return false;
|
||||
}
|
||||
|
||||
// and only if new Failes were succefully added
|
||||
if(this.queue.length == j){
|
||||
return false;
|
||||
}
|
||||
|
||||
this.processQueue();
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
DmUploader.prototype.processQueue = function()
|
||||
{
|
||||
var widget = this;
|
||||
|
||||
widget.queuePos++;
|
||||
|
||||
if(widget.queuePos >= widget.queue.length){
|
||||
// Cleanup
|
||||
|
||||
widget.settings.onComplete.call(widget.element);
|
||||
|
||||
// Wait until new files are droped
|
||||
widget.queuePos = (widget.queue.length - 1);
|
||||
|
||||
widget.queueRunning = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var file = widget.queue[widget.queuePos];
|
||||
|
||||
// Form Data
|
||||
var fd = new FormData();
|
||||
fd.append(widget.settings.fileName, file);
|
||||
|
||||
// Append extra Form Data
|
||||
$.each(widget.settings.extraData, function(exKey, exVal){
|
||||
fd.append(exKey, exVal);
|
||||
});
|
||||
|
||||
widget.settings.onBeforeUpload.call(widget.element, widget.queuePos);
|
||||
|
||||
widget.queueRunning = true;
|
||||
|
||||
// Ajax Submit
|
||||
$.ajax({
|
||||
url: widget.settings.url,
|
||||
type: widget.settings.method,
|
||||
dataType: widget.settings.dataType,
|
||||
data: fd,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
forceSync: false,
|
||||
xhr: function(){
|
||||
var xhrobj = $.ajaxSettings.xhr();
|
||||
if(xhrobj.upload){
|
||||
xhrobj.upload.addEventListener('progress', function(event) {
|
||||
var percent = 0;
|
||||
var position = event.loaded || event.position;
|
||||
var total = event.total || e.totalSize;
|
||||
if(event.lengthComputable){
|
||||
percent = Math.ceil(position / total * 100);
|
||||
}
|
||||
|
||||
widget.settings.onUploadProgress.call(widget.element, widget.queuePos, percent);
|
||||
}, false);
|
||||
}
|
||||
|
||||
return xhrobj;
|
||||
},
|
||||
success: function (data, message, xhr){
|
||||
widget.settings.onUploadSuccess.call(widget.element, widget.queuePos, data);
|
||||
},
|
||||
error: function (xhr, status, errMsg){
|
||||
widget.settings.onUploadError.call(widget.element, widget.queuePos, errMsg);
|
||||
},
|
||||
complete: function(xhr, textStatus){
|
||||
widget.processQueue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
$.fn.dmUploader = function(options){
|
||||
return this.each(function(){
|
||||
if(!$.data(this, pluginName)){
|
||||
$.data(this, pluginName, new DmUploader(this, options));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// -- Disable Document D&D events to prevent opening the file on browser when we drop them
|
||||
$(document).on('dragenter', function (e) { e.stopPropagation(); e.preventDefault(); });
|
||||
$(document).on('dragover', function (e) { e.stopPropagation(); e.preventDefault(); });
|
||||
$(document).on('drop', function (e) { e.stopPropagation(); e.preventDefault(); });
|
||||
})(jQuery);
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
/*
|
||||
* dmuploader.js - Jquery File Uploader - 0.1
|
||||
* http://www.daniel.com.uy/projects/jquery-file-uploader/
|
||||
*
|
||||
* Copyright (c) 2013 Daniel Morales
|
||||
* Dual licensed under the MIT and GPL licenses.
|
||||
* http://www.daniel.com.uy/doc/license/
|
||||
*/
|
||||
(function(c){var b="dmUploader";var d={url:document.URL,method:"POST",extraData:{},maxFileSize:0,allowedTypes:"*",dataType:null,fileName:"file",onInit:function(){},onFallbackMode:function(){message},onNewFile:function(g,f){},onBeforeUpload:function(f){},onComplete:function(){},onUploadProgress:function(g,f){},onUploadSuccess:function(g,f){},onUploadError:function(g,f){},onFileTypeError:function(f){},onFileSizeError:function(f){}};var a=function(g,f){this.element=c(g);this.settings=c.extend({},d,f);if(!this.checkBrowser()){return false}this.init();return true};a.prototype.checkBrowser=function(){if(window.FormData===undefined){this.settings.onFallbackMode.call(this.element,"Browser doesn't support From API");return false}if(this.element.find("input[type=file]").length>0){return true}if(!this.checkEvent("drop",this.element)||!this.checkEvent("dragstart",this.element)){this.settings.onFallbackMode.call(this.element,"Browser doesn't support Ajax Drag and Drop");return false}return true};a.prototype.checkEvent=function(f,h){var h=h||document.createElement("div");var f="on"+f;var g=f in h;if(!g){if(!h.setAttribute){h=document.createElement("div")}if(h.setAttribute&&h.removeAttribute){h.setAttribute(f,"");g=typeof h[f]=="function";if(typeof h[f]!="undefined"){h[f]=undefined}h.removeAttribute(f)}}h=null;return g};a.prototype.init=function(){var f=this;f.queue=new Array();f.queuePos=-1;f.queueRunning=false;f.element.on("drop",function(g){g.preventDefault();var h=g.originalEvent.dataTransfer.files;f.queueFiles(h)});f.element.find("input[type=file]").on("change",function(g){var h=g.target.files;f.queueFiles(h);c(this).val("")});this.settings.onInit.call(this.element)};a.prototype.queueFiles=function(l){var g=this.queue.length;for(var k=0;k<l.length;k++){var h=l[k];if((this.settings.maxFileSize>0)&&(h.size>this.settings.maxFileSize)){this.settings.onFileSizeError.call(this.element,h);continue}if((this.settings.allowedTypes!="*")&&!h.type.match(this.settings.allowedTypes)){this.settings.onFileTypeError.call(this.element,h);continue}this.queue.push(h);var f=this.queue.length-1;this.settings.onNewFile.call(this.element,f,h)}if(this.queueRunning){return false}if(this.queue.length==g){return false}this.processQueue();return true};a.prototype.processQueue=function(){var h=this;h.queuePos++;if(h.queuePos>=h.queue.length){h.settings.onComplete.call(h.element);h.queuePos=(h.queue.length-1);h.queueRunning=false;return}var g=h.queue[h.queuePos];var f=new FormData();f.append(h.settings.fileName,g);c.each(h.settings.extraData,function(i,j){f.append(i,j)});h.settings.onBeforeUpload.call(h.element,h.queuePos);h.queueRunning=true;c.ajax({url:h.settings.url,type:h.settings.method,dataType:h.settings.dataType,data:f,cache:false,contentType:false,processData:false,forceSync:false,xhr:function(){var i=c.ajaxSettings.xhr();if(i.upload){i.upload.addEventListener("progress",function(m){var l=0;var j=m.loaded||m.position;var k=m.total||e.totalSize;if(m.lengthComputable){l=Math.ceil(j/k*100)}h.settings.onUploadProgress.call(h.element,h.queuePos,l)},false)}return i},success:function(j,i,k){h.settings.onUploadSuccess.call(h.element,h.queuePos,j)},error:function(k,i,j){h.settings.onUploadError.call(h.element,h.queuePos,j)},complete:function(i,j){h.processQueue()}})};c.fn.dmUploader=function(f){return this.each(function(){if(!c.data(this,b)){c.data(this,b,new a(this,f))}})};c(document).on("dragenter",function(f){f.stopPropagation();f.preventDefault()});c(document).on("dragover",function(f){f.stopPropagation();f.preventDefault()});c(document).on("drop",function(f){f.stopPropagation();f.preventDefault()})})(jQuery);
|
||||
Vendored
+4
File diff suppressed because one or more lines are too long
@@ -1,7 +0,0 @@
|
||||
% layout 'default';
|
||||
% title 'Welcome';
|
||||
<h2><%= $msg %></h2>
|
||||
This page was generated from the template "templates/example/welcome.html.ep"
|
||||
and the layout "templates/layouts/default.html.ep",
|
||||
<a href="<%== url_for %>">click here</a> to reload the page or
|
||||
<a href="/index.html">here</a> to move forward to a static page.
|
||||
@@ -0,0 +1,127 @@
|
||||
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
|
||||
<div class="messages">
|
||||
% if (defined(flash('short'))) {
|
||||
<div class="alert alert-success">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
<strong><%= flash('filename') %></strong>
|
||||
<ul>
|
||||
<li><%=l 'view-link'%><%= link_to url_for('/')->to_abs.flash('short') => begin %><%= url_for('/')->to_abs.flash('short') %><%= end %></li>
|
||||
<li><%=l 'download-link' %> <%= link_to url_for('/')->to_abs.flash('short').'?dl' => begin %><%= url_for('/')->to_abs.flash('short').'?dl' %><%= end %></li>
|
||||
</ul>
|
||||
</div>
|
||||
% }
|
||||
% if (defined(flash('msg'))) {
|
||||
<div class="alert alert-danger">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>
|
||||
<strong><%=l 'some-bad' %></strong><br>
|
||||
<%= flash('filename') %> <%= flash('msg') %>
|
||||
</div>
|
||||
% }
|
||||
</div>
|
||||
|
||||
<noscript>
|
||||
<form class="form" role="form" method="POST" action="<%== url_for 'add' %>" enctype="multipart/form-data">
|
||||
<div class="form-group form-inline">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="first-view"> <%=l 'delete-first' %>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" name="delete-day"> <%=l 'delete-day' %>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="lutim-file"><%=l 'upload_image' %></label>
|
||||
<input type="file" name="file" id="lutim-file" required></input>
|
||||
<p class="help-block"><%=l 'image-only' %></p>
|
||||
</div>
|
||||
<%= submit_button l('go'), class => 'btn btn-default btn-primary', id => 'submitbutton' %>
|
||||
</form>
|
||||
</noscript>
|
||||
|
||||
<!-- D&D Zone-->
|
||||
<div class="jsonly">
|
||||
<div class="form-group form-inline">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="first-view"> <%=l 'delete-first' %>
|
||||
</label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" id="delete-day"> <%=l 'delete-day' %>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div id="drag-and-drop-zone" class="uploader">
|
||||
<div><%=l 'drag-n-drop' %></div>
|
||||
<div class="or"><%=l 'or' %></div>
|
||||
<div class="browser">
|
||||
<label>
|
||||
<span><%=l 'file-browser' %></span>
|
||||
<input type="file" name="files[]" multiple="multiple" title='Click to add Files'>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /D&D Zone -->
|
||||
|
||||
%= javascript begin
|
||||
function link(url, dl) {
|
||||
if (dl) {
|
||||
url = url+'?dl';
|
||||
}
|
||||
return '<a href="<%== url_for('index')->to_abs() %>'+url+'"><%== url_for('index')->to_abs() %>'+url+'</a>';
|
||||
}
|
||||
function message(success, msg) {
|
||||
if(success) {
|
||||
return '<div class="alert alert-success"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button><strong>'
|
||||
+msg.filename
|
||||
+'</strong><ul><li>view link '
|
||||
+link(msg.short, false)
|
||||
+'</a></li><li>download link '
|
||||
+link(msg.short, true)
|
||||
+'</li></div>';
|
||||
} else {
|
||||
return '<div class="alert alert-danger"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button><strong><%=l 'some-bad' %></strong><br>'
|
||||
+msg.filename
|
||||
+' '
|
||||
+msg.msg
|
||||
+'</div>';
|
||||
}
|
||||
}
|
||||
$('document').ready(function() {
|
||||
$('.jsonly').show();
|
||||
$('#drag-and-drop-zone').dmUploader({
|
||||
url: '<%== url_for('add') %>',
|
||||
dataType: 'json',
|
||||
allowedTypes: 'image/*',
|
||||
extraData: {
|
||||
'format': 'json',
|
||||
'first-view': $("#first-view").val(),
|
||||
'delete-day': $("#delete-day").val()
|
||||
},
|
||||
/*onBeforeUpload: function(id){
|
||||
$.danidemo.updateFileStatus(id, 'default', 'Uploading...');
|
||||
},
|
||||
onNewFile: function(id, file){
|
||||
$.danidemo.addFile('#demo-files', id, file);
|
||||
},
|
||||
onUploadProgress: function(id, percent){
|
||||
var percentStr = percent + '%';
|
||||
|
||||
$.danidemo.updateFileProgress(id, percentStr);
|
||||
},*/
|
||||
onUploadSuccess: function(id, data){
|
||||
console.dir(data.msg);
|
||||
$(".messages").append(message(data.success, data.msg));
|
||||
},
|
||||
onUploadError: function(id, message){
|
||||
$(".messages").append(message(false, ''));
|
||||
}
|
||||
});
|
||||
});
|
||||
% end
|
||||
@@ -1,5 +1,80 @@
|
||||
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
|
||||
% use Mojo::Util qw(url_escape);
|
||||
% my $twitter_url = 'https://twitter.com/share';
|
||||
% my $url = url_for('/')->to_abs();
|
||||
% $twitter_url .= '?url='.url_escape("$url")
|
||||
% .'&via=framasky'
|
||||
% .'&text=Check out this %23LUTIm instance! '.$url;
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head><title><%= title %></title></head>
|
||||
<body><%= content %></body>
|
||||
<head>
|
||||
<title>LUTIm</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta charset="utf-8" />
|
||||
%= stylesheet 'css/bootstrap.min.css', media => 'screen'
|
||||
%= stylesheet 'css/fontello.css'
|
||||
%= stylesheet 'css/uploader.css'
|
||||
%= stylesheet begin
|
||||
body {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 15px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.jsonly {
|
||||
display: none;
|
||||
}
|
||||
% end
|
||||
%= javascript 'js/jquery-2.1.0.min.js'
|
||||
%= javascript 'js/bootstrap.min.js'
|
||||
%= javascript 'js/dmuploader.min.js'
|
||||
%= javascript 'js/modernizr.custom.min.js'
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Let's Upload That Image!</h1>
|
||||
<p>
|
||||
© 2014 <%= link_to 'http://www.fiat-tux.fr' => begin %>Luc Didry<% end %> —
|
||||
<%=l 'license' %> <%= link_to 'https://www.gnu.org/licenses/agpl-3.0.html' => begin %>AGPL<% end %> —
|
||||
<span class="jsonly"><a data-toggle="modal" href="#myModal"><%=l 'informations' %></a> — </span>
|
||||
<%= link_to 'https://github.com/ldidry/lutim' => (title => l 'fork-me') => begin %><i class="lead icon icon-github-circled"></i><% end %>
|
||||
<%= link_to $twitter_url => (title => l 'share-twitter') => begin %><i class="lead icon icon-touiteur"></i><% end %>
|
||||
<%= link_to 'https://flattr.com/submit/auto?user_id=_SKy_&url='.$url.'&title=LUTIm&category=software' => (title => 'Flattr this') => begin %><i class="lead icon icon-flattr"></i><% end %>
|
||||
<%= link_to 'bitcoin:1K3n4MXNRSMHk28oTfXEvDunWFthePvd8v?label=lutim' => (title => 'Give Bitcoins') => begin %><i class="lead icon icon-bitcoin"></i><% end %>
|
||||
</p>
|
||||
<%= content %>
|
||||
<div class="modal fade bs-modal-lg" id="myModal" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3 class="modal-title">LUTIm</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<%==l 'informations-body', url_for('index')->to_abs(), config('contact') %>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
</div><!-- /.modal -->
|
||||
<noscript>
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">LUTIm</h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<%==l 'informations-body', url_for('index')->to_abs(), config('contact') %>
|
||||
</div>
|
||||
</noscript>
|
||||
</div>
|
||||
% if (defined(config('piwik_img'))) {
|
||||
<img src="<%== config('piwik_img') %>" style="border:0" alt="" />
|
||||
% }
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user