Compare commits
307 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72f0469674 | ||
|
|
a842311304 | ||
|
|
ce84d403df | ||
|
|
ec6b9ce028 | ||
|
|
321b8bbf97 | ||
|
|
78ce5dc69d | ||
|
|
82289ece59 | ||
|
|
32ca358886 | ||
|
|
c5dac2d5e9 | ||
|
|
88b77f91fb | ||
|
|
75b645e6d4 | ||
|
|
9cfb694779 | ||
|
|
37b6f82f32 | ||
|
|
65403d934c | ||
|
|
36bae6e042 | ||
|
|
2a0f2ef4a2 | ||
|
|
54374765e7 | ||
|
|
0cb82fee0b | ||
|
|
b7e799353f | ||
|
|
c5831168af | ||
|
|
8a8e331de9 | ||
|
|
790da8deeb | ||
|
|
c7b15dc952 | ||
|
|
4f8a27a10b | ||
|
|
6014ea4889 | ||
|
|
e389869414 | ||
|
|
c9dda1c720 | ||
|
|
3b1a6af092 | ||
|
|
b7d4ea0a23 | ||
|
|
05dcdc2729 | ||
|
|
b8212e4920 | ||
|
|
3faee2402c | ||
|
|
ef1463f8c9 | ||
|
|
028961113c | ||
|
|
63a7ad74cd | ||
|
|
3f21ddb35a | ||
|
|
a8d38f6ea8 | ||
|
|
efb71654d6 | ||
|
|
8421efc3da | ||
|
|
e0f8ddec64 | ||
|
|
1f03678348 | ||
|
|
9aed9a0f03 | ||
|
|
c2110dc171 | ||
|
|
381f4e934e | ||
|
|
b710c3250b | ||
|
|
6738c49730 | ||
|
|
9318058f2b | ||
|
|
d2cd4b8335 | ||
|
|
b6d7860472 | ||
|
|
9a4a5a5799 | ||
|
|
1a8d2ea171 | ||
|
|
179def2d3e | ||
|
|
0de43b74db | ||
|
|
5dffc402c9 | ||
|
|
b6cfec60e2 | ||
|
|
efec636f2e | ||
|
|
eb6dc4235a | ||
|
|
d1b6c00a55 | ||
|
|
7af0ee5df4 | ||
|
|
1b9dad0f3f | ||
|
|
4c0df8f8b1 | ||
|
|
4629d2ae2d | ||
|
|
f4f25aab4f | ||
|
|
c6ee5408da | ||
|
|
6cc48bb991 | ||
|
|
91174081b5 | ||
|
|
a69e0df68d | ||
|
|
545059cbe5 | ||
|
|
a848d7aef8 | ||
|
|
cc3281fe2f | ||
|
|
48cc398efb | ||
|
|
4d2721f533 | ||
|
|
2923180f0c | ||
|
|
4130a77aa0 | ||
|
|
dd4ca47ac0 | ||
|
|
b63eebbefa | ||
|
|
e767f850bf | ||
|
|
374b99f77d | ||
|
|
c58edbae83 | ||
|
|
c03082c2c1 | ||
|
|
9f872a3f6a | ||
|
|
fd3d9a6e31 | ||
|
|
fbcc133e47 | ||
|
|
e8eb804d3c | ||
|
|
453bc5d2c5 | ||
|
|
c450b27c0d | ||
|
|
1bd82463d1 | ||
|
|
6a4b0910d4 | ||
|
|
ef6509a3bc | ||
|
|
0a318dc4d4 | ||
|
|
58901989dd | ||
|
|
08a07cd93d | ||
|
|
a7884e8785 | ||
|
|
41fef61f7c | ||
|
|
a1ce8618de | ||
|
|
b60a849752 | ||
|
|
b33c7d3d23 | ||
|
|
99e5ea8c75 | ||
|
|
dced03c964 | ||
|
|
fe06675d0b | ||
|
|
1082f42682 | ||
|
|
1dff747b64 | ||
|
|
c33840f3aa | ||
|
|
a9669b5f7b | ||
|
|
86ee5287bf | ||
|
|
e51e8f3d3a | ||
|
|
688f4517c1 | ||
|
|
1cb5aab686 | ||
|
|
0c23c9ba67 | ||
|
|
204df6bf08 | ||
|
|
2f96407f5c | ||
|
|
14943906d3 | ||
|
|
1aa6e9b859 | ||
|
|
a64808f206 | ||
|
|
af9323365c | ||
|
|
7a7eb8f4cc | ||
|
|
170546df64 | ||
|
|
1ad1929a0e | ||
|
|
8b76684fcd | ||
|
|
71576ce749 | ||
|
|
e0b05ff0d1 | ||
|
|
f121a9f807 | ||
|
|
d98f95811f | ||
|
|
7472650b59 | ||
|
|
a1fc2997c7 | ||
|
|
bb9fae43e2 | ||
|
|
bb5c7050bb | ||
|
|
6fab43b15b | ||
|
|
2f7b2f5fbb | ||
|
|
2ca4ba1f0e | ||
|
|
62e82b8224 | ||
|
|
7b9ed1fa4a | ||
|
|
4aa9a649be | ||
|
|
6d260af932 | ||
|
|
5bcd010055 | ||
|
|
0f7d8e745e | ||
|
|
1f0aa046d4 | ||
|
|
b6c3af7bc6 | ||
|
|
c86faf208d | ||
|
|
4fe657d0d7 | ||
|
|
023952648e | ||
|
|
baaf4ab861 | ||
|
|
ae450a9649 | ||
|
|
b4d06a21a0 | ||
|
|
b0a19e3e42 | ||
|
|
e1840e96b0 | ||
|
|
e7138a40ab | ||
|
|
080542fd95 | ||
|
|
774f3ebda9 | ||
|
|
2e8f0eda2a | ||
|
|
a9ea0d35e6 | ||
|
|
a049163646 | ||
|
|
2e5a3c9c0b | ||
|
|
db50470ef8 | ||
|
|
1cb3ec09e3 | ||
|
|
fa47a97be7 | ||
|
|
afb377faca | ||
|
|
339cdf39b2 | ||
|
|
f1c096fd68 | ||
|
|
fc28efa116 | ||
|
|
152b677614 | ||
|
|
9431b60f9b | ||
|
|
9e27e0df59 | ||
|
|
0544a1b346 | ||
|
|
bb1b43e215 | ||
|
|
ad04bdd571 | ||
|
|
23c130750e | ||
|
|
a0b507e48e | ||
|
|
9692504096 | ||
|
|
8386a2f4d2 | ||
|
|
bef9dfaca3 | ||
|
|
b71c25bf54 | ||
|
|
b0e5f771f2 | ||
|
|
2b361fce26 | ||
|
|
64e0db48f2 | ||
|
|
241e8b8ea1 | ||
|
|
e0f13489a4 | ||
|
|
1ca3137dd1 | ||
|
|
b791c609c2 | ||
|
|
388feba7c0 | ||
|
|
542d3efdf5 | ||
|
|
a57815a2ea | ||
|
|
44c0d5a9c9 | ||
|
|
ebb5282579 | ||
|
|
d03ce97c8b | ||
|
|
a4ca866790 | ||
|
|
73b09d28c6 | ||
|
|
5c45be0099 | ||
|
|
150f27bf9b | ||
|
|
d0b388834f | ||
|
|
e951a44324 | ||
|
|
9fcefcdbd4 | ||
|
|
05892366d8 | ||
|
|
989412046b | ||
|
|
f2baf273ca | ||
|
|
420a37ee75 | ||
|
|
940faed363 | ||
|
|
f86b0e71d1 | ||
|
|
7f99d73691 | ||
|
|
4633fdacef | ||
|
|
bf0e2d47b9 | ||
|
|
f044c1e953 | ||
|
|
277053d2a8 | ||
|
|
b450ea7607 | ||
|
|
510bfb3eed | ||
|
|
673d80cec2 | ||
|
|
d8498b89fd | ||
|
|
846d8a1bfe | ||
|
|
75dde62989 | ||
|
|
d9c094ff16 | ||
|
|
37244e866c | ||
|
|
124ccd6ec2 | ||
|
|
3fb3bac3ef | ||
|
|
00ccb56c8a | ||
|
|
8696cd43c4 | ||
|
|
313bae584c | ||
|
|
63651bd277 | ||
|
|
04d38bfdf7 | ||
|
|
d05827102e | ||
|
|
eb0dac2b4b | ||
|
|
9f130e1761 | ||
|
|
1b580a2e76 | ||
|
|
2a7cb615ba | ||
|
|
6e9a8a79c8 | ||
|
|
a7704987a3 | ||
|
|
6d155a57ab | ||
|
|
cc99fba3fa | ||
|
|
cd699dd6e8 | ||
|
|
c84d5cf691 | ||
|
|
ac301e104c | ||
|
|
b0af4ccd75 | ||
|
|
6b71bbaf35 | ||
|
|
0f3b99e617 | ||
|
|
ad5032b720 | ||
|
|
7e60f4876a | ||
|
|
8264356176 | ||
|
|
52b1005b69 | ||
|
|
c7c8a7d786 | ||
|
|
12e0bf093a | ||
|
|
2c4416985b | ||
|
|
123d597c5f | ||
|
|
096bf1acc3 | ||
|
|
5349d327ed | ||
|
|
ad0e799601 | ||
|
|
ff8ab141f9 | ||
|
|
ebb9cafb1e | ||
|
|
d6cbaa1a6f | ||
|
|
2fae7345d9 | ||
|
|
1f93835060 | ||
|
|
2786a3bda2 | ||
|
|
9a283274e0 | ||
|
|
8953ddf840 | ||
|
|
f40c8e1195 | ||
|
|
e794edd6d1 | ||
|
|
b8401e259e | ||
|
|
afb5eb3ecd | ||
|
|
551b9cadc5 | ||
|
|
0b106f6b99 | ||
|
|
04b220a665 | ||
|
|
b1c73555aa | ||
|
|
37feb11430 | ||
|
|
9c896f1a59 | ||
|
|
e014bc229b | ||
|
|
9787a7210a | ||
|
|
662ef1c461 | ||
|
|
54d8bf12a8 | ||
|
|
fb51b92e09 | ||
|
|
96dc4758ef | ||
|
|
584e9d2dd2 | ||
|
|
dee5d0a22e | ||
|
|
682923726c | ||
|
|
f8807288c6 | ||
|
|
fc2b866238 | ||
|
|
373ec23bbc | ||
|
|
b0b905b139 | ||
|
|
49f1838ed0 | ||
|
|
2c9eca80e3 | ||
|
|
96072d0a2a | ||
|
|
b2a408a207 | ||
|
|
8eb2c200c8 | ||
|
|
be80462d2e | ||
|
|
9d9e29e906 | ||
|
|
fcd1b1489b | ||
|
|
cacd1a46ee | ||
|
|
d3bde59421 | ||
|
|
de1dff9f35 | ||
|
|
096e2b3e07 | ||
|
|
bc7a7fabf0 | ||
|
|
6561a60bdc | ||
|
|
5373ec63a8 | ||
|
|
23a74b2b86 | ||
|
|
51e0483652 | ||
|
|
6766ed6aef | ||
|
|
dbd68796e8 | ||
|
|
3388577790 | ||
|
|
5da1e9ee03 | ||
|
|
992850d99b | ||
|
|
1f7559effc | ||
|
|
4cb9f4adf5 | ||
|
|
239f49b2e4 | ||
|
|
6f9c1bcdf4 | ||
|
|
3a11b93d35 | ||
|
|
4b11f1b38c | ||
|
|
b3420967ee | ||
|
|
067b2198fd | ||
|
|
b1ecf6aa4b | ||
|
|
47aa06d3b0 |
14
.gitignore
vendored
@@ -1,5 +1,17 @@
|
||||
*.swp
|
||||
lutim.conf
|
||||
lutim.db
|
||||
*.db
|
||||
*.db-shm
|
||||
*.db-wal
|
||||
script/hypnotoad.pid
|
||||
local/*
|
||||
files/*
|
||||
stop-upload
|
||||
themes/*
|
||||
!themes/default
|
||||
!themes/default/*
|
||||
themes/default/templates/data.html.ep
|
||||
themes/default/templates/raw.html.ep
|
||||
themes/default/templates/stats.json.ep
|
||||
themes/default/public/packed/*
|
||||
tmp/*
|
||||
|
||||
121
.gitlab-ci.yml
Normal file
@@ -0,0 +1,121 @@
|
||||
image: hatsoftwares/test-ci:latest
|
||||
stages:
|
||||
- sqlite
|
||||
- postgresql
|
||||
before_script:
|
||||
- carton install
|
||||
- rm -f *db
|
||||
sqlite1:
|
||||
stage: sqlite
|
||||
cache:
|
||||
key: "$CI_BUILD_REF_NAME"
|
||||
untracked: true
|
||||
paths:
|
||||
- local
|
||||
script:
|
||||
- make podcheck
|
||||
- MOJO_CONFIG=t/sqlite1.conf make test-sqlite
|
||||
- MOJO_CONFIG=t/sqlite1.conf make watch
|
||||
- MOJO_CONFIG=t/sqlite1.conf make cleanbdd
|
||||
- MOJO_CONFIG=t/sqlite1.conf make cleanfiles
|
||||
- MOJO_CONFIG=t/sqlite1.conf make stats
|
||||
sqlite2:
|
||||
stage: sqlite
|
||||
cache:
|
||||
key: "$CI_BUILD_REF_NAME"
|
||||
untracked: true
|
||||
paths:
|
||||
- local
|
||||
script:
|
||||
- make podcheck
|
||||
- MOJO_CONFIG=t/sqlite2.conf make minion &
|
||||
- sleep 3
|
||||
- MOJO_CONFIG=t/sqlite2.conf make test-sqlite
|
||||
- MOJO_CONFIG=t/sqlite2.conf make watch
|
||||
- MOJO_CONFIG=t/sqlite2.conf make cleanbdd
|
||||
- MOJO_CONFIG=t/sqlite2.conf make cleanfiles
|
||||
- MOJO_CONFIG=t/sqlite2.conf make stats
|
||||
sqlite3:
|
||||
stage: sqlite
|
||||
cache:
|
||||
key: "$CI_BUILD_REF_NAME"
|
||||
untracked: true
|
||||
paths:
|
||||
- local
|
||||
script:
|
||||
- make podcheck
|
||||
- service postgresql restart
|
||||
- sleep 10
|
||||
- service postgresql status
|
||||
- make create-pg-test-db
|
||||
- MOJO_CONFIG=t/sqlite3.conf make minion &
|
||||
- sleep 3
|
||||
- MOJO_CONFIG=t/sqlite3.conf make test-sqlite
|
||||
- MOJO_CONFIG=t/sqlite3.conf make watch
|
||||
- MOJO_CONFIG=t/sqlite3.conf make cleanbdd
|
||||
- MOJO_CONFIG=t/sqlite3.conf make cleanfiles
|
||||
- MOJO_CONFIG=t/sqlite3.conf make stats
|
||||
tags:
|
||||
- Debian
|
||||
- Jessie
|
||||
postgresql1:
|
||||
stage: postgresql
|
||||
cache:
|
||||
key: "$CI_BUILD_REF_NAME"
|
||||
untracked: true
|
||||
paths:
|
||||
- local
|
||||
script:
|
||||
- make podcheck
|
||||
- service postgresql restart
|
||||
- sleep 10
|
||||
- service postgresql status
|
||||
- make create-pg-test-db
|
||||
- MOJO_CONFIG=t/postgresql1.conf make test-pg
|
||||
- MOJO_CONFIG=t/postgresql1.conf make watch
|
||||
- MOJO_CONFIG=t/postgresql1.conf make cleanbdd
|
||||
- MOJO_CONFIG=t/postgresql1.conf make cleanfiles
|
||||
- MOJO_CONFIG=t/postgresql1.conf make stats
|
||||
postgresql2:
|
||||
stage: postgresql
|
||||
cache:
|
||||
key: "$CI_BUILD_REF_NAME"
|
||||
untracked: true
|
||||
paths:
|
||||
- local
|
||||
script:
|
||||
- make podcheck
|
||||
- service postgresql restart
|
||||
- sleep 10
|
||||
- service postgresql status
|
||||
- make create-pg-test-db
|
||||
- MOJO_CONFIG=t/postgresql2.conf make minion &
|
||||
- sleep 3
|
||||
- MOJO_CONFIG=t/postgresql2.conf make test-pg
|
||||
- MOJO_CONFIG=t/postgresql2.conf make watch
|
||||
- MOJO_CONFIG=t/postgresql2.conf make cleanbdd
|
||||
- MOJO_CONFIG=t/postgresql2.conf make cleanfiles
|
||||
- MOJO_CONFIG=t/postgresql2.conf make stats
|
||||
postgresql3:
|
||||
stage: postgresql
|
||||
cache:
|
||||
key: "$CI_BUILD_REF_NAME"
|
||||
untracked: true
|
||||
paths:
|
||||
- local
|
||||
script:
|
||||
- make podcheck
|
||||
- service postgresql restart
|
||||
- sleep 10
|
||||
- service postgresql status
|
||||
- make create-pg-test-db
|
||||
- MOJO_CONFIG=t/postgresql3.conf make minion &
|
||||
- sleep 3
|
||||
- MOJO_CONFIG=t/postgresql3.conf make test-pg
|
||||
- MOJO_CONFIG=t/postgresql3.conf make watch
|
||||
- MOJO_CONFIG=t/postgresql3.conf make cleanbdd
|
||||
- MOJO_CONFIG=t/postgresql3.conf make cleanfiles
|
||||
- MOJO_CONFIG=t/postgresql3.conf make stats
|
||||
tags:
|
||||
- Debian
|
||||
- Jessie
|
||||
8
.tx/config
Normal file
@@ -0,0 +1,8 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
|
||||
[lutim.enpo]
|
||||
source_file = lib/Lutim/I18N/en.po
|
||||
source_lang = en
|
||||
type = PO
|
||||
file_filter = lib/Lutim/I18N/<lang>.po
|
||||
17
AUTHORS.md
Normal file
@@ -0,0 +1,17 @@
|
||||
# Lutim's authors
|
||||
|
||||
## Main developers
|
||||
|
||||
* Luc Didry, aka Sky (<http://www.fiat-tux.fr>), core developer, @framasky on [Twitter](https://twitter.com/framasky) and on [Diaspora*](https://framasphere.org/public/framasky)
|
||||
* Dattaz (<http://dattaz.fr>), webapp developer, [@dat_taz](https://twitter.com/dat_taz)
|
||||
|
||||
## Contributors
|
||||
|
||||
* Jean-Bernard Marcon, aka Goofy (<https://github.com/goofy-bz>)
|
||||
* Jean-Christophe Bach (<https://github.com/jcb>)
|
||||
* Florian Bigard, aka Chocobozzz (<https://github.com/Chocobozzz>)
|
||||
* Sandro Cazzaniga, aka Kharec (<http://sandrocazzaniga.fr>), [@Kharec](https://twitter.com/Kharec)
|
||||
* Laura Arjona Reina (<https://wiki.debian.org/LauraArjona>), spanish translation
|
||||
* Thor77 (<http://thor77.org>), german translation, among other things
|
||||
* Quentin Pagès, occitan translation
|
||||
* Alexis Clairet (<https://github.com/Turboconnard>), paste image to upload ability
|
||||
113
CHANGELOG
Normal file
@@ -0,0 +1,113 @@
|
||||
Revision history for Lutim
|
||||
|
||||
0.8.4 2017-06-24
|
||||
- Mitigate a bug using the same empty record twice
|
||||
|
||||
0.8.3 2017-06-15
|
||||
- Fix the donuts charts in the /stats page.
|
||||
|
||||
0.8.2 2017-06-14
|
||||
- Enforce Mojolicious::Plugin::AssetPack version
|
||||
|
||||
0.8.1 2017-06-13
|
||||
- Fix #46
|
||||
|
||||
0.8 2017-06-13
|
||||
- Improve statistics page
|
||||
- Add database abstraction layer (#42)
|
||||
- Add PostgreSQL support (#42)
|
||||
- Asks for Mojolicious 7.31 minimum (to install it: `carton update`)
|
||||
- Add Liberapay and Tipeee buttons
|
||||
- Remove Flattr button
|
||||
- Handle MOJO_CONFIG env variable (#44)
|
||||
- Fix bug #39
|
||||
- Add gallery constructor to "my files" list (#33)
|
||||
- Handle too much images in zip download URL (#27)
|
||||
- LocalStorage is now updated if an image's delay is modified
|
||||
- Allow user to paste image from clipboard to upload images (#14 and !5)
|
||||
- Fix #40
|
||||
- Add stats in JSON format (GET /stats.json)
|
||||
- Add Cache-control headers for static files
|
||||
- Put almost all js/css stuff outside templates
|
||||
- Allow to use Minion to increment counter (#43)
|
||||
|
||||
0.7.1 2016-06-21
|
||||
- Fix dependency bug
|
||||
|
||||
0.7 2016-06-21
|
||||
- Use .po files for internationalization
|
||||
- Add spanish translation (thx to Laura Arjona Reina)
|
||||
- Allow Lutim to be on a sub-directory (like http://example.org/lutim/) (#46 and #57)
|
||||
- Remove deprecated (due to typo) option "provisionning".
|
||||
- Allow to upload svg images (no thumbnail for now, ImageMagick in Debian Jessie don't work with svg) (#47)
|
||||
- Allow to change location of the database (#48)
|
||||
- Autorotate images
|
||||
- Purge images from their EXIF tags (for more privacy)
|
||||
- Provide markdown syntax at upload for using lutim's hosted images
|
||||
- Now using a wiki: makes README lighter (https://framagit.org/luc/lutim/wikis/home)
|
||||
- Update twitter bootstrap
|
||||
- Add "Copy to clipboard" buttons to each link
|
||||
- Add "Copy all links" button
|
||||
- Add file extension to view link
|
||||
- Add list of user's images in localStorage and a page to list the user's images
|
||||
- Use cryptographically secure random generator
|
||||
- Allow to set the encryption length in lutim.conf
|
||||
- Add the possibility of displaying images in a gallery
|
||||
- Add the possibility to download a zip file
|
||||
- bugfixes
|
||||
|
||||
0.6 2014-10-03
|
||||
- Add OpenGraph tags in social page (ex-twitter page)
|
||||
- Update README.md
|
||||
- Update info page
|
||||
|
||||
0.5 2014-09-24
|
||||
- Add support for animated gif in Twitter cards (#45)
|
||||
- Update README.md with Twitter integration informations
|
||||
- bugfixes
|
||||
|
||||
0.4 2014-07-12
|
||||
- Webapp ! Downloadable directly from the Lutim instance
|
||||
- Configure expiration delay after uploading (#12)
|
||||
- Twitter share button in the "upload success" message (#35)
|
||||
|
||||
0.3 2014-06-01
|
||||
- Add a delete link to images (#28)
|
||||
- Concatenated css and js with Mojolicious::Plugin::AssetPack
|
||||
- Antiflood protection for the "Download by URL" feature (#29)
|
||||
- Stats page improved
|
||||
- Self-documented configuration template
|
||||
- Remote port detection can now use the X-Remote-Port header if set
|
||||
- Lutim now uses the X-Forwarded-Proto header to set the scheme to https if needed
|
||||
The "https" option in configuration file is deprecated and will be removed in 0.4
|
||||
- Optionally delete images that are no longer viewed after a configurable delay in order to avoid saturation (#27)
|
||||
- Provide init script
|
||||
- Update Shutter plugin
|
||||
- Small bugfixes
|
||||
|
||||
0.2 2014-03-07
|
||||
- Server-side encryption available
|
||||
- Thumbnails of uploaded images in response
|
||||
- Bugfixes
|
||||
- HTML validity
|
||||
- Stats (via cron stats command)
|
||||
- Anonymize IP in DB after a delay (via cron cleanbdd command)
|
||||
- Watch files directory size (via cron watch command)
|
||||
- Anonymize logs (log only the senders' IP address)
|
||||
- Favicon and logo
|
||||
- Better MIME type detection
|
||||
- Broadcast message on all pages available
|
||||
- File max size configurable
|
||||
- Progress bar
|
||||
- More options for suppression delay
|
||||
- Updated documentation
|
||||
- Cross-domain API
|
||||
- Upload by image URL
|
||||
- Add HTTP headers Expires and Content-Cache
|
||||
|
||||
0.1 2014-02-15
|
||||
- Image viewing link
|
||||
- Image downloading link
|
||||
- Image twitter card link
|
||||
- Shutter Plugin
|
||||
- Configurable "Hosted by" information
|
||||
3
CONTRIBUTING.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# Contributing
|
||||
|
||||
See how to contribute on the [wiki](https://framagit.org/luc/lutim/wikis/contribute).
|
||||
64
Makefile
Normal file
@@ -0,0 +1,64 @@
|
||||
EXTRACTDIR=-D lib -D themes/default/templates
|
||||
EN=themes/default/lib/Lutim/I18N/en.po
|
||||
FR=themes/default/lib/Lutim/I18N/fr.po
|
||||
DE=themes/default/lib/Lutim/I18N/de.po
|
||||
ES=themes/default/lib/Lutim/I18N/es.po
|
||||
OC=themes/default/lib/Lutim/I18N/oc.po
|
||||
XGETTEXT=carton exec local/bin/xgettext.pl
|
||||
CARTON=carton exec
|
||||
LUTIM=script/lutim
|
||||
REAL_LUTIM=script/application
|
||||
|
||||
locales:
|
||||
$(XGETTEXT) $(EXTRACTDIR) -o $(EN) 2>/dev/null
|
||||
$(XGETTEXT) $(EXTRACTDIR) -o $(FR) 2>/dev/null
|
||||
$(XGETTEXT) $(EXTRACTDIR) -o $(DE) 2>/dev/null
|
||||
$(XGETTEXT) $(EXTRACTDIR) -o $(ES) 2>/dev/null
|
||||
$(XGETTEXT) $(EXTRACTDIR) -o $(OC) 2>/dev/null
|
||||
|
||||
podcheck:
|
||||
podchecker lib/Lutim/DB/Image.pm
|
||||
|
||||
test-sqlite:
|
||||
$(CARTON) $(REAL_LUTIM) test
|
||||
|
||||
test-pg:
|
||||
$(CARTON) $(REAL_LUTIM) test
|
||||
|
||||
test: podcheck test-sqlite test-pg
|
||||
|
||||
clean:
|
||||
rm -rf lutim.db files/
|
||||
|
||||
rmassets:
|
||||
rm -rf themes/default/public/packed/*
|
||||
|
||||
dev: rmassets
|
||||
$(CARTON) morbo $(LUTIM) --listen http://0.0.0.0:3000 --watch lib/ --watch script/ --watch themes/ --watch lutim.conf
|
||||
|
||||
devlog:
|
||||
multitail log/development.log
|
||||
|
||||
prod: rmassets
|
||||
$(CARTON) hypnotoad -f $(LUTIM)
|
||||
|
||||
prodlog:
|
||||
multitail log/production.log
|
||||
|
||||
minion:
|
||||
$(CARTON) $(REAL_LUTIM) minion worker
|
||||
|
||||
create-pg-test-db:
|
||||
sudo -u postgres psql -f t/create-pg-testdb.sql
|
||||
|
||||
stats:
|
||||
$(CARTON) $(LUTIM) cron stats -m production
|
||||
|
||||
watch:
|
||||
$(CARTON) $(LUTIM) cron watch -m production
|
||||
|
||||
cleanfiles:
|
||||
$(CARTON) $(LUTIM) cron cleanfiles -m production
|
||||
|
||||
cleanbdd:
|
||||
$(CARTON) $(LUTIM) cron cleanbdd -m production
|
||||
112
README.md
@@ -1,87 +1,69 @@
|
||||
#LUTIm
|
||||
# Lutim
|
||||
|
||||
##What LUTIm means?
|
||||
## What Lutim means?
|
||||
It means Let's Upload That Image.
|
||||
|
||||
##What does it do?
|
||||
It stores images and allows you to see them or download them.
|
||||
Images are indefinitly stored unless you request that they will be deleted at first view or after 24 hours.
|
||||
## What does it do?
|
||||
It stores images and allows you to see them, download them or share them on social networks. From version 0.5, the gif images can be displayed as animated gifs in Twitter, but you need an HTTPS server (Twitter requires that. Lutim detects if you have a HTTPS server and displays a static image twitter card if you don't);
|
||||
|
||||
##License
|
||||
LUTIm is licensed under the terms of the AGPL. See the LICENSE file.
|
||||
Images are indefinitely stored unless you request that they will be deleted at first view or after 24 hours / one week / one month / one year.
|
||||
|
||||
##Dependancies
|
||||
* Carton : Perl dependancies manager, it will get what you need, so don't bother for dependancies (but you can read the file `cpanfile` if you want).
|
||||
## License
|
||||
Lutim is licensed under the terms of the AGPL. See the LICENSE file.
|
||||
|
||||
```shell
|
||||
sudo cpan Carton
|
||||
## Official instance
|
||||
You can see it working at https://lut.im.
|
||||
|
||||
## Logo
|
||||
Lutim's logo is an adaptation of [Lutin](http://commons.wikimedia.org/wiki/File:Lutin_by_godo.jpg) by [Godo](http://godoillustrateur.wordpress.com/), licensed under the terms of the CC-BY-SA 3.0 license.
|
||||
|
||||

|
||||
|
||||
## Wiki
|
||||
|
||||
The official wiki contains all you need to know about Lutim (installation, API, etc.). Go to <https://framagit.org/luc/lutim/wikis/home> or clone it:
|
||||
|
||||
```
|
||||
git clone https://framagit.org/luc/lutim.wiki.git
|
||||
```
|
||||
|
||||
##Installation
|
||||
After installing Carton :
|
||||
```shell
|
||||
git clone https://github.com/ldidry/lutim.git
|
||||
cd lutim
|
||||
carton install
|
||||
cp lutim.conf.template lutim.conf
|
||||
```
|
||||
## Encryption
|
||||
|
||||
##Usage
|
||||
```
|
||||
carton exec hypnotoad script/lutim
|
||||
```
|
||||
Lutim does encryption on the server if asked to, but does not store the key.
|
||||
|
||||
Yup, that's all (Mojolicious magic), it will listen at "http://127.0.0.1:8080".
|
||||
The encryption is done on the server since Lutim is made to be usable even without javascript. If you want to add client-side encryption for javascript-enabled browsers, patches are welcome.
|
||||
|
||||
For more options (interfaces, user, etc.), change the configuration in `lutim.conf` (have a look at http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad#SETTINGS for the available options).
|
||||
## Internationalization
|
||||
|
||||
##Reverse proxy
|
||||
You can use a reverse proxy like Nginx or Varnish (or Apache with the mod\_proxy module). The web is full of tutos.
|
||||
Lutim comes with English, French and Spanish languages. It will choose the language to display from the browser's settings.
|
||||
|
||||
Here's a valid *Varnish* configuration:
|
||||
```
|
||||
backend lutim {
|
||||
.host = "127.0.0.1";
|
||||
.port = "8080";
|
||||
}
|
||||
sub vcl_recv {
|
||||
if (req.restarts == 0) {
|
||||
set req.http.X-Forwarded-For = client.ip;
|
||||
}
|
||||
if (req.http.host == "lut.im") {
|
||||
set req.backend = lutim;
|
||||
return(pass);
|
||||
}
|
||||
}
|
||||
```
|
||||
## Authors
|
||||
|
||||
##Shutter integration
|
||||
See where Shutter (<http://en.wikipedia.org/wiki/Shutter_%28software%29>) keeps its plugins on your computer.
|
||||
On my computer, it's in `/usr/share/shutter/resources/system/upload_plugins/upload`.
|
||||
See [AUTHORS.md](AUTHORS.md) file.
|
||||
|
||||
Then:
|
||||
```
|
||||
sudo cp utilities/Shutter.pm /usr/share/shutter/resources/system/upload_plugins/upload/Lutim.pm
|
||||
```
|
||||
## Contribute!
|
||||
|
||||
And restart Shutter if it was running.
|
||||
Please consider contributing, either by [reporting issues](https://framagit.org/luc/lutim/issues) or by helping the [internationalization](https://pootle.framasoft.org/projects/lutim/). And of course, code contribution are welcome!
|
||||
|
||||
Of course, this plugin is configured for the official instance of LUTIm (<http://lut.im>), feel free to edit it for your own instance.
|
||||
The details on how to contribute are on the [wiki](https://framagit.org/luc/lutim/wikis/contribute).
|
||||
|
||||
##Internationalization
|
||||
LUTIm comes with english and french languages. It will choose the language to display from the browser's settings.
|
||||
## Make a donation
|
||||
|
||||
If you want to add more languages, for example german:
|
||||
```shell
|
||||
cd lib/I18N
|
||||
cp en.pm de.pm
|
||||
vim de.pm
|
||||
```
|
||||
You can make a donation to the author on [Tipeee](https://www.tipeee.com/fiat-tux) or on [Liberapay](https://liberapay.com/sky/).
|
||||
|
||||
There's just a few sentences, so it will be quick to translate. Please consider to send me you language file in order to help the other users :smile:.
|
||||
## Others projects dependencies
|
||||
|
||||
##Others projects dependancies
|
||||
LUTIm is written in Perl with the Mojolicious framework, uses the Twitter bootstrap framework to look not too ugly, JQuery and JQuery File Uploader (<https://github.com/danielm/uploader/>) to add some modernity.
|
||||
Lutim is written in Perl with the [Mojolicious](http://mojolicio.us) framework.
|
||||
|
||||
##Official instance
|
||||
You can see it working at http://lut.im.
|
||||
It uses:
|
||||
|
||||
* [Twitter bootstrap](http://getbootstrap.com) framework to look not too ugly
|
||||
* [JQuery](http://jquery.com) and [JQuery File Uploader](https://github.com/danielm/uploader/) (slightly modified) to add some modernity
|
||||
* [Raphaël](http://raphaeljs.com/) and [morris.js](https://morrisjs.github.io/morris.js/) for stats graphs
|
||||
* [freezeframe.js](http://freezeframe.chrisantonellis.com/) (slightly modified) to be able to freeze animated gifs in twitter card
|
||||
* [Moment.js](http://momentjs.com/) for displaying real dates instead of unix timestamps.
|
||||
* [Fontello](http://fontello.com/) and the [markdown font](https://github.com/dcurtis/markdown-mark/) for the icons, licenses for the fontello icons fonts are in `public/font/LICENSE.txt`
|
||||
* [Henny Penny](https://www.google.com/fonts/specimen/Henny+Penny) font designed by Olga Umpeleva for [Brownfox](http://brownfox.org)
|
||||
* [Unite gallery](http://unitegallery.net/) for the gallery
|
||||
* [JSZip](https://stuk.github.io/jszip/) for generating a zip containing all the images in the gallery
|
||||
* [FileSaver.js](https://github.com/eligrey/FileSaver.js/) for saving the zip
|
||||
|
||||
29
cpanfile
@@ -1,6 +1,31 @@
|
||||
requires 'Mojolicious';
|
||||
requires 'Mojolicious', '>= 7.31';
|
||||
requires 'EV';
|
||||
requires 'IO::Socket::SSL';
|
||||
requires 'Net::SSLeay', '>= 1.81';
|
||||
requires 'Data::Validate::URI';
|
||||
requires 'Net::Domain::TLD', '>= 1.73'; # Must have the last version to handle (at least) .xyz and .link
|
||||
requires 'Mojo::Pg';
|
||||
requires 'Mojolicious::Plugin::I18N';
|
||||
requires 'Mojolicious::Plugin::AssetPack', '>= 1.44';
|
||||
requires 'Mojolicious::Plugin::DebugDumperHelper';
|
||||
requires 'Mojolicious::Plugin::PgURLHelper';
|
||||
requires "Minion", "== 4.06";
|
||||
requires 'Minion::Backend::SQLite', "== 0.009";
|
||||
requires 'CSS::Minifier::XS';
|
||||
requires 'JavaScript::Minifier::XS';
|
||||
requires 'ORLite';
|
||||
requires 'MIME::Types';
|
||||
requires 'Text::Unidecode';
|
||||
requires 'DateTime';
|
||||
requires 'Filesys::DiskUsage';
|
||||
requires 'Switch';
|
||||
requires 'Data::Validate::URI';
|
||||
requires 'Crypt::CBC';
|
||||
requires 'Crypt::Blowfish';
|
||||
requires 'Locale::Maketext';
|
||||
requires 'Locale::Maketext::Extract';
|
||||
requires 'File::MimeInfo';
|
||||
requires 'IO::Scalar';
|
||||
requires 'Image::ExifTool';
|
||||
requires 'Data::Entropy';
|
||||
requires 'List::MoreUtils', '> 0.33';
|
||||
requires 'Archive::Zip';
|
||||
|
||||
1955
cpanfile.snapshot
429
lib/Lutim.pm
@@ -1,286 +1,245 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
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);
|
||||
use Text::Unidecode;
|
||||
use Lutim::DB::Image;
|
||||
|
||||
use vars qw($im_loaded);
|
||||
BEGIN {
|
||||
eval "use Image::Magick";
|
||||
if ($@) {
|
||||
warn "You don't have Image::Magick installed so you won't have thumbnails.";
|
||||
$im_loaded = 0;
|
||||
} else {
|
||||
$im_loaded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
$ENV{MOJO_TMPDIR} = 'tmp';
|
||||
mkdir($ENV{MOJO_TMPDIR}, 0700) unless (-d $ENV{MOJO_TMPDIR});
|
||||
# This method will run once at server start
|
||||
sub startup {
|
||||
my $self = shift;
|
||||
|
||||
$self->plugin('I18N');
|
||||
$self->{wait_for_it} = {};
|
||||
|
||||
my $config = $self->plugin('Config');
|
||||
$self->plugin('DebugDumperHelper');
|
||||
$self->plugin('PgURLHelper');
|
||||
|
||||
# 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}));
|
||||
my $config = $self->plugin('Config', {
|
||||
default => {
|
||||
provisioning => 100,
|
||||
provis_step => 5,
|
||||
length => 8,
|
||||
always_encrypt => 0,
|
||||
anti_flood_delay => 5,
|
||||
tweet_card_via => '@framasky',
|
||||
max_file_size => 10*1024*1024,
|
||||
https => 0,
|
||||
default_delay => 0,
|
||||
max_delay => 0,
|
||||
token_length => 24,
|
||||
crypto_key_length => 8,
|
||||
thumbnail_size => 100,
|
||||
theme => 'default',
|
||||
dbtype => 'sqlite',
|
||||
max_files_in_zip => 15,
|
||||
minion => {
|
||||
enabled => 0,
|
||||
dbtype => 'sqlite',
|
||||
db_path => 'minion.db'
|
||||
},
|
||||
}
|
||||
});
|
||||
|
||||
die "You need to provide a contact information in lutim.conf !" unless (defined($config->{contact}));
|
||||
|
||||
$ENV{MOJO_MAX_MESSAGE_SIZE} = $config->{max_file_size};
|
||||
|
||||
$self->secrets($config->{secrets});
|
||||
|
||||
$self->helper(
|
||||
render_file => sub {
|
||||
my $c = shift;
|
||||
my ($filename, $path, $mediatype, $dl) = @_;
|
||||
# Themes handling
|
||||
shift @{$self->renderer->paths};
|
||||
shift @{$self->static->paths};
|
||||
if ($config->{theme} ne 'default') {
|
||||
my $theme = $self->home->rel_file('themes/'.$config->{theme});
|
||||
push @{$self->renderer->paths}, $theme.'/templates' if -d $theme.'/templates';
|
||||
push @{$self->static->paths}, $theme.'/public' if -d $theme.'/public';
|
||||
}
|
||||
push @{$self->renderer->paths}, $self->home->rel_file('themes/default/templates');
|
||||
push @{$self->static->paths}, $self->home->rel_file('themes/default/public');
|
||||
# Internationalization
|
||||
my $lib = $self->home->rel_file('themes/'.$config->{theme}.'/lib');
|
||||
eval qq(use lib "$lib");
|
||||
$self->plugin('I18N');
|
||||
|
||||
$filename = quote($filename);
|
||||
# Compressed assets
|
||||
$self->plugin('AssetPack' => { pipes => [qw(Combine)] });
|
||||
|
||||
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;
|
||||
# Helpers
|
||||
$self->plugin('Lutim::Plugin::Helpers');
|
||||
|
||||
# Minion
|
||||
if ($config->{minion}->{enabled}) {
|
||||
$self->config->{minion}->{dbtype} = 'sqlite' unless defined $config->{minion}->{dbtype};
|
||||
if ($config->{minion}->{dbtype} eq 'sqlite') {
|
||||
$self->config('minion')->{db_path} = 'minion.db' unless defined $config->{minion}->{db_path};
|
||||
$self->plugin('Minion' => { SQLite => 'sqlite:'.$config->{minion}->{db_path} });
|
||||
} elsif ($config->{minion}->{dbtype} eq 'postgresql') {
|
||||
$self->plugin('Minion' => { Pg => $self->pg_url($config->{minion}->{'pgdb'}) });
|
||||
}
|
||||
$self->app->minion->add_task(
|
||||
accessed => sub {
|
||||
my $job = shift;
|
||||
my $short = $job->args->[0];
|
||||
my $time = $job->args->[1];
|
||||
|
||||
my $img = Lutim::DB::Image->new(app => $job->app, short => $short);
|
||||
$img->accessed($time) if $img->path;
|
||||
}
|
||||
$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(
|
||||
ip => sub {
|
||||
my $c = shift;
|
||||
my @ip = ($c->tx->remote_address eq '127.0.0.1' && $c->app->mode eq 'production') ? $c->tx->req->{content}->{headers}->{headers}->{'x-forwarded-for'}->[0]->[0] : ($c->tx->remote_address);
|
||||
return join(',', @ip);
|
||||
}
|
||||
);
|
||||
|
||||
$self->helper(
|
||||
provisionning => sub {
|
||||
# Hooks
|
||||
$self->hook(
|
||||
before_dispatch => sub {
|
||||
my $c = shift;
|
||||
$c->stop_upload();
|
||||
|
||||
# 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;
|
||||
# API allowed domains
|
||||
if (defined($c->config->{allowed_domains})) {
|
||||
if ($c->config->{allowed_domains}->[0] eq '*') {
|
||||
$c->res->headers->header('Access-Control-Allow-Origin' => '*');
|
||||
} elsif (my $origin = $c->req->headers->origin) {
|
||||
for my $domain ($c->config->{allowed_domains}) {
|
||||
if ($domain->[0] eq $origin) {
|
||||
$c->res->headers->header('Access-Control-Allow-Origin' => $origin);
|
||||
last;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$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)];
|
||||
# Scheme detection
|
||||
if ((defined($c->req->headers->header('X-Forwarded-Proto')) && $c->req->headers->header('X-Forwarded-Proto') eq 'https') || $c->config->{https}) {
|
||||
$c->req->url->base->scheme('https');
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
);
|
||||
|
||||
$self->hook(
|
||||
after_dispatch => sub {
|
||||
my $c = shift;
|
||||
$c->provisioning();
|
||||
|
||||
# Purge expired anti-flood protection
|
||||
my $wait_for_it = $c->app->{wait_for_it};
|
||||
delete @{$wait_for_it}{grep { time - $wait_for_it->{$_} > $c->config->{anti_flood_delay} } keys %{$wait_for_it}} if (defined($wait_for_it));
|
||||
}
|
||||
);
|
||||
$self->hook(after_static => sub {
|
||||
my $c = shift;
|
||||
$c->res->headers->cache_control('max-age=2592000, must-revalidate');
|
||||
});
|
||||
|
||||
$self->asset->store->paths($self->static->paths);
|
||||
$self->asset->process('index.css' => ('css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/animation.css', 'css/uploader.css', 'css/hennypenny.css', 'css/lutim.css', 'css/markdown.css'));
|
||||
$self->asset->process('stats.css' => ('css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/morris-0.4.3.min.css', 'css/hennypenny.css', 'css/lutim.css'));
|
||||
$self->asset->process('about.css' => ('css/bootstrap.min.css', 'css/fontello-embedded.css', 'css/hennypenny.css', 'css/lutim.css'));
|
||||
$self->asset->process('gallery.css' => ('/gallery/css/unite-gallery.css', '/gallery/themes/default/ug-theme-default.css'));
|
||||
|
||||
$self->asset->process('index.js' => ('js/bootstrap.min.js', 'js/lutim.js', 'js/dmuploader.min.js'));
|
||||
$self->asset->process('stats.js' => ('js/bootstrap.min.js', 'js/lutim.js', 'js/raphael-min.js', 'js/morris-0.4.3.min.js', 'js/stats.js'));
|
||||
$self->asset->process('freeze.js' => ('js/jquery-2.1.0.min.js', 'js/freezeframe.min.js'));
|
||||
|
||||
$self->defaults(layout => 'default');
|
||||
|
||||
$self->provisionning();
|
||||
$self->provisioning();
|
||||
|
||||
# Router
|
||||
my $r = $self->routes;
|
||||
|
||||
$r->get('/' => sub {
|
||||
my $c = shift;
|
||||
$r->options(sub {
|
||||
my $c = shift;
|
||||
$c->res->headers->allow('POST') if (defined($c->config->{allowed_domains}));
|
||||
$c->render(data => '', status => 204);
|
||||
});
|
||||
|
||||
$c->render( template => 'index');
|
||||
$r->get('/')->
|
||||
to('Controller#home')->
|
||||
name('index');
|
||||
|
||||
# Check provisionning
|
||||
$c->on(finish => sub {
|
||||
shift->provisionning();
|
||||
}
|
||||
);
|
||||
}
|
||||
)->name('index');
|
||||
$r->get('/about')->
|
||||
to('Controller#about')->
|
||||
name('about');
|
||||
|
||||
$r->post('/' => sub {
|
||||
my $c = shift;
|
||||
my $upload = $c->param('file');
|
||||
$r->get('/infos')->
|
||||
to('Controller#infos')->
|
||||
name('infos');
|
||||
|
||||
my ($mediatype, $encoding) = by_suffix $upload->filename;
|
||||
$r->get('/stats')->
|
||||
to('Controller#stats')->
|
||||
name('stats');
|
||||
|
||||
my $ip = $c->ip;
|
||||
|
||||
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 = unidecode($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 => $ip
|
||||
);
|
||||
|
||||
# Log image creation
|
||||
$c->app->log->info('[CREATION] '.$ip.' 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);
|
||||
$r->get('/partial/:file' => sub {
|
||||
my $c = shift;
|
||||
$c->render(
|
||||
template => 'partial/'.$c->param('file'),
|
||||
format => 'js',
|
||||
layout => undef,
|
||||
d => {
|
||||
delay_0 => $c->l('no time limit'),
|
||||
delay_1 => $c->l('24 hours'),
|
||||
delay_365 => $c->l('1 year')
|
||||
}
|
||||
);
|
||||
})->name('partial');
|
||||
|
||||
# Check provisionning
|
||||
$c->on(finish => sub {
|
||||
shift->provisionning();
|
||||
}
|
||||
);
|
||||
$r->get('/gallery' => sub {
|
||||
shift->render(
|
||||
template => 'gallery',
|
||||
);
|
||||
})->name('gallery');
|
||||
|
||||
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('/myfiles' => sub {
|
||||
shift->render(
|
||||
template => 'myfiles'
|
||||
);
|
||||
})->name('myfiles');
|
||||
|
||||
$r->get('/:short' => sub {
|
||||
my $c = shift;
|
||||
my $short = $c->param('short');
|
||||
my $touit = $c->param('t');
|
||||
my $dl = (defined($c->param('dl'))) ? 'attachment' : 'inline';
|
||||
$r->get('/manifest.webapp')->
|
||||
to('Controller#webapp')->
|
||||
name('manifest.webapp');
|
||||
|
||||
my @images = LutimModel::Lutim->select('WHERE short = ? AND ENABLED = 1 AND path IS NOT NULL', $short);
|
||||
my $ip = $c->ip;
|
||||
$r->get('/zip')
|
||||
->to('Controller#zip')
|
||||
->name('zip');
|
||||
|
||||
if (scalar(@images)) {
|
||||
if($images[0]->delete_at_day && $images[0]->created_at + 86400 <= time()) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] '.$ip.' tried to view '.$images[0]->filename.' but it has been removed by expiration (path: '.$images[0]->path.')');
|
||||
$r->post('/')->
|
||||
to('Controller#add')->
|
||||
name('add');
|
||||
|
||||
# Delete image
|
||||
unlink $images[0]->path();
|
||||
$images[0]->update(enabled => 0);
|
||||
$r->get('/d/:short/:token')->
|
||||
to('Controller#delete')->
|
||||
name('delete');
|
||||
|
||||
# Warn user
|
||||
$c->flash(
|
||||
msg => $c->l('image_not_found')
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
$r->post('/m/:short/:token')->
|
||||
to('Controller#modify')->
|
||||
name('modify');
|
||||
|
||||
my $test;
|
||||
if (defined($touit)) {
|
||||
$test = 1;
|
||||
$c->render(
|
||||
template => 'twitter',
|
||||
layout => undef,
|
||||
short => $images[0]->short,
|
||||
filename => $images[0]->filename
|
||||
);
|
||||
} else {
|
||||
$test = $c->render_file($images[0]->filename, $images[0]->path, $images[0]->mediatype, $dl);
|
||||
}
|
||||
$r->post('/c')->
|
||||
to('Controller#get_counter')->
|
||||
name('counter');
|
||||
|
||||
if ($test != 500) {
|
||||
# Update counter and check provisionning
|
||||
$c->on(finish => sub {
|
||||
# Log access
|
||||
$c->app->log->info('[VIEW] '.$ip.' viewed '.$images[0]->filename.' (path: '.$images[0]->path.')');
|
||||
$r->get('/(:short).(:f)')->
|
||||
to('Controller#short')->
|
||||
name('short');
|
||||
$r->get('/:short')->
|
||||
to('Controller#short');
|
||||
|
||||
# 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 => $ip);
|
||||
|
||||
# Delete image if needed
|
||||
if ($images[0]->delete_at_first_view) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] '.$ip.' 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] '.$ip.' 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');
|
||||
$r->get('/:short/(:key).(:f)')->
|
||||
to('Controller#short');
|
||||
$r->get('/:short/:key')->
|
||||
to('Controller#short');
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
27
lib/Lutim/Command/cron.pm
Normal file
@@ -0,0 +1,27 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::Command::cron;
|
||||
use Mojo::Base 'Mojolicious::Commands';
|
||||
|
||||
has description => 'Execute tasks.';
|
||||
has hint => <<EOF;
|
||||
|
||||
See 'script/lutim cron help TASK' for more information on a specific task.
|
||||
EOF
|
||||
has message => sub { shift->extract_usage . "\nCron tasks:\n" };
|
||||
has namespaces => sub { ['Lutim::Command::cron'] };
|
||||
|
||||
sub help { shift->run(@_) }
|
||||
|
||||
1;
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Lutim::Command::cron - Cron commands
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: script/lutim cron TASK [OPTIONS]
|
||||
|
||||
=cut
|
||||
49
lib/Lutim/Command/cron/cleanbdd.pm
Normal file
@@ -0,0 +1,49 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::Command::cron::cleanbdd;
|
||||
use Mojo::Base 'Mojolicious::Command';
|
||||
use Mojo::File;
|
||||
use Lutim::DB::Image;
|
||||
use FindBin qw($Bin);
|
||||
use File::Spec qw(catfile);
|
||||
|
||||
has description => 'Delete IP addresses from database after configured delay.';
|
||||
has usage => sub { shift->extract_usage };
|
||||
|
||||
sub run {
|
||||
my $c = shift;
|
||||
|
||||
my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf');
|
||||
if (defined $ENV{MOJO_CONFIG}) {
|
||||
$cfile = Mojo::File->new($ENV{MOJO_CONFIG});
|
||||
unless (-e $cfile->to_abs) {
|
||||
$cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG});
|
||||
}
|
||||
}
|
||||
my $config = $c->app->plugin('Config', {
|
||||
file => $cfile,
|
||||
default => {
|
||||
keep_ip_during => 365,
|
||||
dbtype => 'sqlite',
|
||||
}
|
||||
});
|
||||
|
||||
my $separation = time() - $config->{keep_ip_during} * 86400;
|
||||
|
||||
my $dbi = Lutim::DB::Image->new(app => $c->app);
|
||||
|
||||
$dbi->clean_ips_until($separation);
|
||||
}
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Lutim::Command::cron::cleanbdd - Delete IP addresses from database after configured delay
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: script/lutim cron cleanbdd
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
64
lib/Lutim/Command/cron/cleanfiles.pm
Normal file
@@ -0,0 +1,64 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::Command::cron::cleanfiles;
|
||||
use Mojo::Base 'Mojolicious::Command';
|
||||
use Mojo::File;
|
||||
use Lutim::DB::Image;
|
||||
use Lutim;
|
||||
use FindBin qw($Bin);
|
||||
use File::Spec qw(catfile);
|
||||
|
||||
has description => 'Delete expired files.';
|
||||
has usage => sub { shift->extract_usage };
|
||||
|
||||
sub run {
|
||||
my $c = shift;
|
||||
|
||||
my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf');
|
||||
if (defined $ENV{MOJO_CONFIG}) {
|
||||
$cfile = Mojo::File->new($ENV{MOJO_CONFIG});
|
||||
unless (-e $cfile->to_abs) {
|
||||
$cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG});
|
||||
}
|
||||
}
|
||||
my $config = $c->app->plugin('Config', {
|
||||
file => $cfile,
|
||||
default => {
|
||||
dbtype => 'sqlite',
|
||||
}
|
||||
});
|
||||
|
||||
my $l = Lutim->new;
|
||||
|
||||
my $dbi = Lutim::DB::Image->new(app => $c->app);
|
||||
|
||||
$dbi->get_images_to_clean()->each(
|
||||
sub {
|
||||
my ($img, $num) = @_;
|
||||
$l->app->delete_image($img);
|
||||
}
|
||||
);
|
||||
|
||||
if (defined($config->{delete_no_longer_viewed_files}) && $config->{delete_no_longer_viewed_files} > 0) {
|
||||
my $time = time() - $config->{delete_no_longer_viewed_files} * 86400;
|
||||
$dbi->get_no_longer_viewed_files($time)->each(
|
||||
sub {
|
||||
my ($img, $num) = @_;
|
||||
$l->app->delete_image($img);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Lutim::Command::cron::cleanfiles - Delete expired files
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: script/lutim cron cleanfiles
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
210
lib/Lutim/Command/cron/stats.pm
Normal file
@@ -0,0 +1,210 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::Command::cron::stats;
|
||||
use Mojo::Base 'Mojolicious::Command';
|
||||
use Mojo::DOM;
|
||||
use Mojo::Util qw(encode);
|
||||
use Mojo::File;
|
||||
use Mojo::JSON qw(encode_json);
|
||||
use Lutim::DB::Image;
|
||||
use DateTime;
|
||||
use FindBin qw($Bin);
|
||||
use File::Spec qw(catfile);
|
||||
use POSIX;
|
||||
|
||||
has description => 'Generate statistics about Lutim.';
|
||||
has usage => sub { shift->extract_usage };
|
||||
|
||||
sub run {
|
||||
my $c = shift;
|
||||
|
||||
my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf');
|
||||
if (defined $ENV{MOJO_CONFIG}) {
|
||||
$cfile = Mojo::File->new($ENV{MOJO_CONFIG});
|
||||
unless (-e $cfile->to_abs) {
|
||||
$cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG});
|
||||
}
|
||||
}
|
||||
my $config = $c->app->plugin('Config', {
|
||||
file => $cfile,
|
||||
default => {
|
||||
theme => 'default',
|
||||
stats_day_num => 365,
|
||||
dbtype => 'sqlite'
|
||||
}
|
||||
});
|
||||
|
||||
my $template = 'themes/'.$config->{theme}.'/templates/data.html.ep.template';
|
||||
unless (-e $template) {
|
||||
$config->{theme} = 'default';
|
||||
$template = 'themes/'.$config->{theme}.'/templates/data.html.ep.template';
|
||||
}
|
||||
|
||||
my $stats = {};
|
||||
|
||||
my $text = Mojo::File->new($template)->slurp;
|
||||
my $dom = Mojo::DOM->new($text);
|
||||
my $thead_tr = $dom->at('table thead tr');
|
||||
my $tbody_tr = $dom->at('table tbody tr');
|
||||
my $tbody_t2 = $tbody_tr->next;
|
||||
|
||||
my $separation = time() - $config->{stats_day_num} * 86400;
|
||||
|
||||
my %data;
|
||||
my $img = Lutim::DB::Image->new(app => $c->app);
|
||||
my $sca = $img->select_created_after($separation);
|
||||
|
||||
$stats->{total} = $img->count_not_empty;
|
||||
$stats->{average} = floor($sca->size / $config->{stats_day_num}) if $config->{stats_day_num};
|
||||
$stats->{for_days} = $config->{stats_day_num};
|
||||
|
||||
$sca->each(
|
||||
sub {
|
||||
my ($e, $num) = @_;
|
||||
my $time = DateTime->from_epoch(epoch => $e->created_at);
|
||||
my ($year, $month, $day) = ($time->year(), $time->month(), $time->day());
|
||||
|
||||
if (defined($data{$year}->{$month}->{$day})) {
|
||||
$data{$year}->{$month}->{$day} += 1;
|
||||
} else {
|
||||
$data{$year}->{$month}->{$day} = 1;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
my $total = $img->count_created_before($separation);
|
||||
for my $year (sort {$a <=> $b} keys %data) {
|
||||
for my $month (sort {$a <=> $b} keys %{$data{$year}}) {
|
||||
for my $day (sort {$a <=> $b} keys %{$data{$year}->{$month}}) {
|
||||
$thead_tr->append_content('<th>'."$day/$month/$year".'</th>'."\n");
|
||||
$tbody_tr->append_content('<td>'.$data{$year}->{$month}->{$day}.'</td>'."\n");
|
||||
$total += $data{$year}->{$month}->{$day};
|
||||
$tbody_t2->append_content('<td>'.$total.'</td>'."\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $moy = $total / $config->{stats_day_num};
|
||||
|
||||
# Raw datas
|
||||
my $template2 = 'themes/'.$config->{theme}.'/templates/raw.html.ep.template';
|
||||
unless (-e $template2) {
|
||||
$config->{theme} = 'default';
|
||||
$template = 'themes/'.$config->{theme}.'/templates/raw.html.ep.template';
|
||||
}
|
||||
my $text2 = Mojo::File->new($template2)->slurp;
|
||||
my $dom2 = Mojo::DOM->new($text2);
|
||||
my $raw = $dom2->at('table tbody');
|
||||
my $raw_foot = $dom2->at('table tfoot');
|
||||
my $unlimited_enabled = $img->count_delete_at_day_endis(0, 1);
|
||||
my $unlimited_disabled = $img->count_delete_at_day_endis(0, 0);
|
||||
my $day_enabled = $img->count_delete_at_day_endis(1, 1);
|
||||
my $day_disabled = $img->count_delete_at_day_endis(1, 0);
|
||||
my $week_enabled = $img->count_delete_at_day_endis(7, 1);
|
||||
my $week_disabled = $img->count_delete_at_day_endis(7, 0);
|
||||
my $month_enabled = $img->count_delete_at_day_endis(30, 1);
|
||||
my $month_disabled = $img->count_delete_at_day_endis(30, 0);
|
||||
my $year_enabled = $img->count_delete_at_day_endis(365, 1);
|
||||
my $year_disabled = $img->count_delete_at_day_endis(365, 0);
|
||||
my $year_disabled_in_month = $img->count_delete_at_day_endis(365, 1, time - 335 * 86400);
|
||||
|
||||
$stats->{unlimited} = {
|
||||
enabled => $unlimited_enabled,
|
||||
disabled => $unlimited_disabled
|
||||
};
|
||||
$stats->{day} = {
|
||||
enabled => $day_enabled,
|
||||
disabled => $day_disabled
|
||||
};
|
||||
$stats->{week} = {
|
||||
enabled => $week_enabled,
|
||||
disabled => $week_disabled
|
||||
};
|
||||
$stats->{month} = {
|
||||
enabled => $month_enabled,
|
||||
disabled => $month_disabled
|
||||
};
|
||||
$stats->{year} = {
|
||||
enabled => $year_enabled,
|
||||
disabled => $year_disabled
|
||||
};
|
||||
|
||||
my $year_disabled_in_month_pct = ($year_enabled != 0) ? " (".sprintf('%.2f', $year_disabled_in_month/$year_enabled)."%)" : '';
|
||||
|
||||
$raw->append_content("\n<tr><td><%= \$raw[4] %></td><td>".$unlimited_enabled."</td><td>".$unlimited_disabled."</td><td>ø</td></tr>\n");
|
||||
$raw->append_content("<tr><td><%= \$raw[5] %></td><td>".$day_enabled."</td><td>".$day_disabled."</td><td>".$day_enabled." (100%)</td></tr>\n");
|
||||
$raw->append_content("<tr><td><%= \$raw[6] %></td><td>".$week_enabled."</td><td>".$week_disabled."</td><td>".$week_enabled." (100%)</td></tr>\n");
|
||||
$raw->append_content("<tr><td><%= \$raw[7] %></td><td>".$month_enabled."</td><td>".$month_disabled."</td><td>".$month_enabled." (100%)</td></tr>\n");
|
||||
$raw->append_content("<tr><td><%= \$raw[8] %></td><td>".$year_enabled."</td><td>".$year_disabled."</td><td>".$year_disabled_in_month.$year_disabled_in_month_pct."</td></tr>\n");
|
||||
|
||||
$raw_foot->append_content("\n<tr><td><%= \$raw[9] %></td><td>".($unlimited_enabled + $day_enabled + $week_enabled + $month_enabled + $year_enabled)."</td><td>".($unlimited_disabled + $day_disabled + $week_disabled + $month_disabled + $year_disabled)."</td><td>".($day_enabled + $week_enabled + $month_enabled + $year_disabled_in_month)."</td></tr>\n");
|
||||
|
||||
$dom2 = <<EOF;
|
||||
% my \@raw = (
|
||||
% l('Image delay'),
|
||||
% l('Active images'),
|
||||
% l('Deleted images'),
|
||||
% l('Deleted images in 30 days'),
|
||||
% l('no time limit'),
|
||||
% l('24 hours'),
|
||||
% l('%1 days', 7),
|
||||
% l('%1 days', 30),
|
||||
% l('1 year'),
|
||||
% l('Total')
|
||||
% );
|
||||
<script>
|
||||
var enabled_donut = {
|
||||
element: 'raw-enabled-holder',
|
||||
data: [
|
||||
{label: "<%= l('no time limit') %>", value: $unlimited_enabled},
|
||||
{label: "<%= l('24 hours') %>", value: $day_enabled},
|
||||
{label: "<%= l('%1 days', 7) %>", value: $week_enabled},
|
||||
{label: "<%= l('%1 days', 30) %>", value: $month_enabled},
|
||||
{label: "<%= l('1 year') %>", value: $year_enabled},
|
||||
],
|
||||
colors: [
|
||||
'#40b489',
|
||||
'#40b9b1',
|
||||
'#40a1be',
|
||||
'#427dc1',
|
||||
'#455ac3',
|
||||
]
|
||||
};
|
||||
var disabled_donut = {
|
||||
element: 'raw-disabled-holder',
|
||||
data: [
|
||||
{label: "<%= l('no time limit') %>", value: $unlimited_disabled},
|
||||
{label: "<%= l('24 hours') %>", value: $day_disabled},
|
||||
{label: "<%= l('%1 days', 7) %>", value: $week_disabled},
|
||||
{label: "<%= l('%1 days', 30) %>", value: $month_disabled},
|
||||
{label: "<%= l('1 year') %>", value: $year_disabled},
|
||||
],
|
||||
colors: [
|
||||
'#40b489',
|
||||
'#40b9b1',
|
||||
'#40a1be',
|
||||
'#427dc1',
|
||||
'#455ac3',
|
||||
]
|
||||
};
|
||||
</script>
|
||||
$dom2
|
||||
EOF
|
||||
|
||||
Mojo::File->new('themes/'.$config->{theme}.'/templates/stats.json.ep')->spurt(encode_json($stats));
|
||||
Mojo::File->new('themes/'.$config->{theme}.'/templates/data.html.ep')->spurt($dom);
|
||||
Mojo::File->new('themes/'.$config->{theme}.'/templates/raw.html.ep')->spurt(encode('UTF-8', $dom2));
|
||||
}
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Lutim::Command::cron::stats - Stats generator
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: script/lutim cron stats
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
84
lib/Lutim/Command/cron/watch.pm
Normal file
@@ -0,0 +1,84 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::Command::cron::watch;
|
||||
use Mojo::Base 'Mojolicious::Command';
|
||||
use Filesys::DiskUsage qw/du/;
|
||||
use Lutim::DB::Image;
|
||||
use Lutim;
|
||||
use Mojo::File;
|
||||
use Switch;
|
||||
use FindBin qw($Bin);
|
||||
use File::Spec qw(catfile);
|
||||
|
||||
has description => 'Watch the files directory and take action when over quota';
|
||||
has usage => sub { shift->extract_usage };
|
||||
|
||||
sub run {
|
||||
my $c = shift;
|
||||
|
||||
my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf');
|
||||
if (defined $ENV{MOJO_CONFIG}) {
|
||||
$cfile = Mojo::File->new($ENV{MOJO_CONFIG});
|
||||
unless (-e $cfile->to_abs) {
|
||||
$cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG});
|
||||
}
|
||||
}
|
||||
my $config = $c->app->plugin('Config', {
|
||||
file => $cfile,
|
||||
default => {
|
||||
policy_when_full => 'warn',
|
||||
dbtype => 'sqlite',
|
||||
}
|
||||
});
|
||||
|
||||
if (defined($config->{max_total_size})) {
|
||||
my $total = du(qw/files/);
|
||||
|
||||
if ($total > $config->{max_total_size}) {
|
||||
say "[Lutim cron job watch] Files directory is over quota ($total > ".$config->{max_total_size}.")";
|
||||
switch ($config->{policy_when_full}) {
|
||||
case 'warn' {
|
||||
say "[Lutim cron job watch] Please, delete some files or increase quota (".$config->{max_total_size}.")";
|
||||
}
|
||||
case 'stop-upload' {
|
||||
open (my $fh, '>', 'stop-upload') or die ("Couldn't open stop-upload: $!");
|
||||
close($fh);
|
||||
say '[Lutim cron job watch] Uploads are stopped. Delete some images and the stop-upload file to reallow uploads.';
|
||||
}
|
||||
case 'delete' {
|
||||
say '[Lutim cron job watch] Older files are being deleted';
|
||||
my $dbi = Lutim::DB::Image->new(app => $c->app);
|
||||
my $l = Lutim->new;
|
||||
do {
|
||||
$dbi->get_50_oldest()->each(
|
||||
sub {
|
||||
my ($img, $num) = @_;
|
||||
$l->app->delete_image($img);
|
||||
}
|
||||
);
|
||||
} while (du(qw/files/) > $config->{max_total_size});
|
||||
}
|
||||
else {
|
||||
say '[Lutim cron job watch] Unrecognized policy_when_full option: '.$config->{policy_when_full}.'. Aborting.';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unlink 'stop-upload' if (-f 'stop-upload');
|
||||
}
|
||||
} else {
|
||||
say "[Lutim cron job watch] No max_total_size found in the configuration file. Aborting.";
|
||||
}
|
||||
}
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Lutim::Command::cron::watch - Watch the files directory and take action when over quota
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: script/lutim cron watch
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
114
lib/Lutim/Command/theme.pm
Normal file
@@ -0,0 +1,114 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::Command::theme;
|
||||
use Mojo::Base 'Mojolicious::Commands';
|
||||
use FindBin qw($Bin);
|
||||
use File::Spec qw(catfile cat dir);
|
||||
use File::Path qw(make_path);
|
||||
|
||||
has description => 'Create new theme skeleton.';
|
||||
has usage => sub { shift->extract_usage };
|
||||
has message => sub { shift->extract_usage . "\nCreate new theme skeleton:\n" };
|
||||
has namespaces => sub { ['Lutim::Command::theme'] };
|
||||
|
||||
sub run {
|
||||
my $c = shift;
|
||||
my $name = shift;
|
||||
|
||||
unless (defined $name) {
|
||||
say $c->extract_usage;
|
||||
exit 1;
|
||||
}
|
||||
|
||||
my $home = File::Spec->catdir($Bin, '..', 'themes', $name);
|
||||
|
||||
unless (-d $home) {
|
||||
|
||||
# Create skeleton
|
||||
mkdir $home;
|
||||
mkdir File::Spec->catdir($home, 'public');
|
||||
make_path(File::Spec->catdir($home, 'templates', 'layouts'));
|
||||
make_path(File::Spec->catdir($home, 'lib', 'Lutim', 'I18N'));
|
||||
|
||||
my $i18n = <<EOF;
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::I18N;
|
||||
|
||||
use base 'Locale::Maketext';
|
||||
use File::Basename qw/dirname/;
|
||||
use Locale::Maketext::Lexicon {
|
||||
_auto => 1,
|
||||
_decode => 1,
|
||||
_style => 'gettext',
|
||||
'*' => [
|
||||
Gettext => dirname(__FILE__) . '/I18N/*.po',
|
||||
Gettext => dirname(__FILE__) . '/../../../default/lib/Lutim/I18N/*.po',
|
||||
]
|
||||
};
|
||||
|
||||
1;
|
||||
EOF
|
||||
|
||||
open my $f, '>', File::Spec->catfile($home, 'lib', 'Lutim', 'I18N.pm') or die "Unable to open $home/lib/Lutim/I18N.pm: $!";
|
||||
print $f $i18n;
|
||||
close $f;
|
||||
|
||||
my $makefile = <<EOF;
|
||||
EN=lib/Lutim/I18N/en.po
|
||||
FR=lib/Lutim/I18N/fr.po
|
||||
DE=lib/Lutim/I18N/de.po
|
||||
ES=lib/Lutim/I18N/es.po
|
||||
OC=lib/Lutim/I18N/oc.po
|
||||
SEDOPTS=-e "s\@SOME DESCRIPTIVE TITLE\@Lutim language file\@" \\
|
||||
-e "s\@YEAR THE PACKAGE'S COPYRIGHT HOLDER\@2015 Luc Didry\@" \\
|
||||
-e "s\@CHARSET\@utf8\@" \\
|
||||
-e "s\@the PACKAGE package\@the Lutim package\@" \\
|
||||
-e '/^\\#\\. (/{N;/\\n\\#\\. (/{N;/\\n.*\\.\\.\\/default\\//{s/\\#\\..*\\n.*\\#\\./\\#. (/g}}}' \\
|
||||
-e '/^\\#\\. (/{N;/\\n.*\\.\\.\\/default\\//{s/\\n/ /}}'
|
||||
SEDOPTS2=-e '/^\\#.*\\.\\.\\/default\\//,+3d'
|
||||
XGETTEXT=carton exec ../../local/bin/xgettext.pl
|
||||
CARTON=carton exec
|
||||
|
||||
locales:
|
||||
\$(XGETTEXT) -D templates -D ../default/templates -o \$(EN) 2>/dev/null
|
||||
\$(XGETTEXT) -D templates -D ../default/templates -o \$(FR) 2>/dev/null
|
||||
\$(XGETTEXT) -D templates -D ../default/templates -o \$(DE) 2>/dev/null
|
||||
\$(XGETTEXT) -D templates -D ../default/templates -o \$(ES) 2>/dev/null
|
||||
\$(XGETTEXT) -D templates -D ../default/templates -o \$(OC) 2>/dev/null
|
||||
sed \$(SEDOPTS) -i \$(EN)
|
||||
sed \$(SEDOPTS2) -i \$(EN)
|
||||
sed \$(SEDOPTS) -i \$(FR)
|
||||
sed \$(SEDOPTS2) -i \$(FR)
|
||||
sed \$(SEDOPTS) -i \$(DE)
|
||||
sed \$(SEDOPTS2) -i \$(DE)
|
||||
sed \$(SEDOPTS) -i \$(ES)
|
||||
sed \$(SEDOPTS2) -i \$(ES)
|
||||
sed \$(SEDOPTS) -i \$(OC)
|
||||
sed \$(SEDOPTS2) -i \$(OC)
|
||||
EOF
|
||||
|
||||
open $f, '>', File::Spec->catfile($home, 'Makefile') or die "Unable to open $home/Makefile: $!";
|
||||
print $f $makefile;
|
||||
close $f;
|
||||
open $f, '>', File::Spec->catfile($home, '.gitignore') or die "Unable to open $home/.gitignore: $!";
|
||||
print $f "public/packed/\ntemplates/data.html.ep";
|
||||
close $f;
|
||||
} else {
|
||||
say "$name theme already exists. Aborting.";
|
||||
exit 1;
|
||||
}
|
||||
}
|
||||
|
||||
=encoding utf8
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Lutim::Command::theme - Create new theme skeleton.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
Usage: script/lutim theme THEME_NAME
|
||||
|
||||
Your new theme will be available in the themes directory.
|
||||
=cut
|
||||
|
||||
1;
|
||||
747
lib/Lutim/Controller.pm
Normal file
@@ -0,0 +1,747 @@
|
||||
# vim:set sw=4 ts=4 sts=4 expandtab:
|
||||
package Lutim::Controller;
|
||||
use Mojo::Base 'Mojolicious::Controller';
|
||||
use Mojo::Util qw(url_escape url_unescape b64_encode encode);
|
||||
use Mojo::Asset::Memory;
|
||||
use Mojo::JSON qw(true false);
|
||||
use Lutim::DB::Image;
|
||||
use DateTime;
|
||||
use Digest::file qw(digest_file_hex);
|
||||
use Text::Unidecode;
|
||||
use Data::Validate::URI qw(is_http_uri is_https_uri);
|
||||
use File::MimeInfo::Magic qw(mimetype extensions);
|
||||
use IO::Scalar;
|
||||
use Image::ExifTool;
|
||||
use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
|
||||
|
||||
use vars qw($im_loaded);
|
||||
BEGIN {
|
||||
eval "use Image::Magick";
|
||||
if ($@) {
|
||||
warn "You don't have Image::Magick installed so you won't have thumbnails.";
|
||||
$im_loaded = 0;
|
||||
} else {
|
||||
$im_loaded = 1;
|
||||
}
|
||||
}
|
||||
|
||||
sub home {
|
||||
my $c = shift;
|
||||
|
||||
$c->render(
|
||||
template => 'index',
|
||||
max_file_size => $c->req->max_message_size
|
||||
);
|
||||
|
||||
|
||||
$c->on(finish => sub {
|
||||
my $c = shift;
|
||||
$c->app->log->info('[HIT] someone visited site index');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub about {
|
||||
shift->render(template => 'about');
|
||||
}
|
||||
|
||||
sub stats {
|
||||
my $c = shift;
|
||||
|
||||
my $img = Lutim::DB::Image->new(app => $c);
|
||||
$c->render(
|
||||
template => 'stats',
|
||||
total => $img->count_not_empty
|
||||
);
|
||||
}
|
||||
|
||||
sub infos {
|
||||
my $c = shift;
|
||||
|
||||
$c->render(
|
||||
json => {
|
||||
broadcast_message => $c->config('broadcast_message'),
|
||||
image_magick => ($im_loaded) ? true : false,
|
||||
contact => $c->config('contact'),
|
||||
max_file_size => $c->config('max_file_size'),
|
||||
default_delay => $c->config('default_delay'),
|
||||
max_delay => $c->config('max_delay'),
|
||||
always_encrypt => ($c->config('always_encrypt')) ? true : false,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub webapp {
|
||||
my $c = shift;
|
||||
|
||||
my $headers = Mojo::Headers->new();
|
||||
$headers->add('Content-Type' => 'application/x-web-app-manifest+json');
|
||||
$c->res->content->headers($headers);
|
||||
|
||||
$c->render(
|
||||
template => 'manifest',
|
||||
format => 'webapp'
|
||||
);
|
||||
}
|
||||
|
||||
sub get_counter {
|
||||
my $c = shift;
|
||||
my $short = $c->param('short');
|
||||
my $token = $c->param('token');
|
||||
|
||||
my $img = Lutim::DB::Image->new(app => $c->app, short => $short);
|
||||
if (defined($img->mod_token) && $img->mod_token eq $token) {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => true,
|
||||
counter => $img->counter,
|
||||
enabled => ($img->enabled) ? true : false
|
||||
}
|
||||
);
|
||||
}
|
||||
$c->render(
|
||||
json => {
|
||||
success => false,
|
||||
msg => $c->l('Unable to get counter')
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
sub modify {
|
||||
my $c = shift;
|
||||
my $short = $c->param('short');
|
||||
my $token = $c->param('token');
|
||||
my $url = $c->param('url');
|
||||
|
||||
my $image = Lutim::DB::Image->new(app => $c->app, short => $short);
|
||||
if ($image->path) {
|
||||
my $msg;
|
||||
if ($image->mod_token ne $token || $token eq '') {
|
||||
$msg = $c->l('The delete token is invalid.');
|
||||
} else {
|
||||
$c->app->log->info('[MODIFICATION] someone modify '.$image->filename.' with token method (path: '.$image->path.')');
|
||||
|
||||
$image->delete_at_day(($c->param('delete-day') && ($c->param('delete-day') <= $c->max_delay || $c->max_delay == 0)) ? $c->param('delete-day') : $c->max_delay);
|
||||
$image->delete_at_first_view(($c->param('first-view')) ? 1 : 0);
|
||||
$image->write;
|
||||
|
||||
$msg = $c->l('The image\'s delay has been successfully modified');
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => Mojo::JSON->true,
|
||||
msg => $msg
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$msg .= ' (<a href="'.$url.'">'.$url.'</a>)' unless (!defined($url));
|
||||
$c->flash(
|
||||
success => $msg
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
}
|
||||
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => Mojo::JSON->false,
|
||||
msg => $msg
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->flash(
|
||||
msg => $msg
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
} else {
|
||||
$c->app->log->info('[UNSUCCESSFUL] someone tried to modify '.$short.' but it does\'nt exist.');
|
||||
|
||||
# Image never existed
|
||||
my $msg = $c->l('Unable to find the image %1.', $short);
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => Mojo::JSON->false,
|
||||
msg => $msg
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->flash(
|
||||
msg => $msg
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub delete {
|
||||
my $c = shift;
|
||||
my $short = $c->param('short');
|
||||
my $token = $c->param('token');
|
||||
|
||||
my $image = Lutim::DB::Image->new(app => $c->app, short => $short);
|
||||
if ($image->path) {
|
||||
my $msg;
|
||||
if ($image->mod_token ne $token || $token eq '') {
|
||||
$msg = $c->l('The delete token is invalid.');
|
||||
} elsif ($image->enabled() == 0) {
|
||||
$msg = $c->l('The image %1 has already been deleted.', $image->filename);
|
||||
} else {
|
||||
$c->app->log->info('[DELETION] someone made '.$image->filename.' removed with token method (path: '.$image->path.')');
|
||||
|
||||
$c->delete_image($image);
|
||||
return $c->respond_to(
|
||||
json => {
|
||||
json => {
|
||||
success => true,
|
||||
msg => $c->l('The image %1 has been successfully deleted', $image->filename)
|
||||
}
|
||||
},
|
||||
any => sub {
|
||||
$c->flash(
|
||||
success => $c->l('The image %1 has been successfully deleted', $image->filename)
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
return $c->respond_to(
|
||||
json => {
|
||||
json => {
|
||||
success => false,
|
||||
msg => $msg
|
||||
}
|
||||
},
|
||||
any => sub {
|
||||
$c->flash(
|
||||
msg => $msg
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->app->log->info('[UNSUCCESSFUL] someone tried to delete '.$short.' but it does\'nt exist.');
|
||||
|
||||
# Image never existed
|
||||
return $c->respond_to(
|
||||
json => {
|
||||
json => {
|
||||
success => false,
|
||||
msg => $c->l('Unable to find the image %1.', $short)
|
||||
}
|
||||
},
|
||||
any => sub {
|
||||
shift->render_not_found;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
sub add {
|
||||
my $c = shift;
|
||||
my $upload = $c->param('file');
|
||||
my $file_url = $c->param('lutim-file-url');
|
||||
my $keep_exif = $c->param('keep-exif');
|
||||
|
||||
if(!defined($c->stash('stop_upload'))) {
|
||||
if (defined($file_url) && $file_url) {
|
||||
if (is_http_uri($file_url) || is_https_uri($file_url)) {
|
||||
# Anti-flood protection
|
||||
my $ip = $c->ip(1);
|
||||
while (defined($c->app->{wait_for_it}->{$ip}) && (time - $c->app->{wait_for_it}->{$ip}) <= $c->config->{anti_flood_delay} ) {
|
||||
sleep($c->config->{anti_flood_delay});
|
||||
}
|
||||
my $ua = Mojo::UserAgent->new;
|
||||
my $tx = $ua->get($file_url => {DNT => 1});
|
||||
if (my $res = $tx->success) {
|
||||
$file_url = url_unescape $file_url;
|
||||
$file_url =~ m#^.*/([^/?]*)\??.*$#;
|
||||
my $filename = $1;
|
||||
$filename = 'uploaded.image' unless (defined($filename));
|
||||
$filename .= '.image' if (index($filename, '.') == -1);
|
||||
$upload = Mojo::Upload->new(
|
||||
asset => $res->content->asset,
|
||||
filename => $filename
|
||||
);
|
||||
$c->app->{wait_for_it}->{$ip} = time;
|
||||
} elsif ($tx->res->is_limit_exceeded) {
|
||||
my $msg = $c->l('The file exceed the size limit (%1)', $tx->res->max_message_size);
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => Mojo::JSON->false,
|
||||
msg => {
|
||||
filename => $file_url,
|
||||
msg => $msg
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->flash(msg => $msg);
|
||||
$c->flash(filename => $upload->filename);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
} else {
|
||||
my $msg = $c->l('An error occured while downloading the image.');
|
||||
$c->app->log->warn('[DOWNLOAD ERROR]'.$c->dumper($tx->error));
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => Mojo::JSON->false,
|
||||
msg => {
|
||||
filename => $file_url,
|
||||
msg => $msg
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->flash(msg => $msg);
|
||||
$c->flash(filename => $file_url);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
my $msg = $c->l('The URL is not valid.');
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => Mojo::JSON->false,
|
||||
msg => {
|
||||
filename => $file_url,
|
||||
msg => $msg
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->flash(msg => $msg);
|
||||
$c->flash(filename => $file_url);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my $io_scalar = new IO::Scalar \$upload->slurp();
|
||||
my $mediatype = mimetype($io_scalar);
|
||||
|
||||
my ($ext) = ($upload->filename =~ m/.*\.(.*)$/);
|
||||
|
||||
my $ip = $c->ip;
|
||||
|
||||
my ($msg, $short, $real_short, $token, $thumb, $limit, $created);
|
||||
# Check file type
|
||||
if (index($mediatype, 'image/') >= 0) {
|
||||
# Create directory if needed
|
||||
mkdir('files', 0700) unless (-d 'files');
|
||||
|
||||
if ($c->req->is_limit_exceeded) {
|
||||
$msg = $c->l('The file exceed the size limit (%1)', $c->req->max_message_size);
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => Mojo::JSON->false,
|
||||
msg => $msg
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->flash(msg => $msg);
|
||||
$c->flash(filename => $upload->filename);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
}
|
||||
my $record = Lutim::DB::Image->new(app => $c->app)->select_empty;
|
||||
if ($record->short) {
|
||||
# Save file and create record
|
||||
my $filename = unidecode($upload->filename);
|
||||
my $ext = ($filename =~ m/([^.]+)$/)[0];
|
||||
my $path = 'files/'.$record->short.'.'.$ext;
|
||||
|
||||
my ($width, $height);
|
||||
if ($im_loaded && $mediatype ne 'image/svg+xml' && $mediatype !~ m#image/(x-)?xcf# && $mediatype ne 'image/webp') { # ImageMagick don't work in Debian with svg (for now?)
|
||||
my $im = Image::Magick->new;
|
||||
$im->BlobToImage($upload->slurp);
|
||||
|
||||
# Automatic rotation from EXIF tag
|
||||
$im->AutoOrient();
|
||||
|
||||
# Update the uploaded file with it's auto-rotated clone
|
||||
my $asset = Mojo::Asset::Memory->new->add_chunk($im->ImageToBlob());
|
||||
$upload->asset($asset);
|
||||
|
||||
# Create the thumbnail
|
||||
$width = $im->Get('width');
|
||||
$height = $im->Get('height');
|
||||
$im->Resize(geometry=>'x85');
|
||||
|
||||
$thumb = 'data:'.$mediatype.';base64,';
|
||||
if ($mediatype eq 'image/gif') {
|
||||
$thumb .= b64_encode $im->[0]->ImageToBlob();
|
||||
} else {
|
||||
$thumb .= b64_encode $im->ImageToBlob();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unless ((defined($keep_exif) && $keep_exif) || $mediatype eq 'image/svg+xml' || $mediatype !~ m#image/(x-)?xcf# || $mediatype ne 'image/webp') {
|
||||
# Remove the EXIF tags
|
||||
my $data = new IO::Scalar \$upload->slurp();
|
||||
my $et = new Image::ExifTool;
|
||||
|
||||
# Use $data in Image::ExifTool object
|
||||
$et->ExtractInfo($data);
|
||||
# Remove all metadata
|
||||
$et->SetNewValue('*', undef);
|
||||
|
||||
# Create a temporary IO::Scalar to write into
|
||||
my $temp;
|
||||
my $a = new IO::Scalar \$temp;
|
||||
$et->WriteInfo($data, $a);
|
||||
|
||||
# Update the uploaded file with it's no-tags clone
|
||||
$data = Mojo::Asset::Memory->new->add_chunk($temp);
|
||||
$upload->asset($data);
|
||||
}
|
||||
|
||||
my $key;
|
||||
if ($c->param('crypt') || $c->config('always_encrypt')) {
|
||||
($upload, $key) = $c->crypt($upload, $filename);
|
||||
}
|
||||
$upload->move_to($path);
|
||||
|
||||
$record->path($path)
|
||||
->filename($filename)
|
||||
->mediatype($mediatype)
|
||||
->footprint(digest_file_hex($path, 'SHA-512'))
|
||||
->enabled(1)
|
||||
->delete_at_day(($c->param('delete-day') && ($c->param('delete-day') <= $c->max_delay || $c->max_delay == 0)) ? $c->param('delete-day') : $c->max_delay)
|
||||
->delete_at_first_view(($c->param('first-view'))? 1 : 0)
|
||||
->created_at(time())
|
||||
->created_by($ip)
|
||||
->width($width)
|
||||
->height($height)
|
||||
->write;
|
||||
|
||||
# Log image creation
|
||||
$c->app->log->info('[CREATION] '.$ip.' pushed '.$filename.' (path: '.$path.')');
|
||||
|
||||
# Give url to user
|
||||
$short = $record->short;
|
||||
$real_short = $short;
|
||||
if (!defined($record->mod_token)) {
|
||||
$record->mod_token($c->shortener($c->config->{token_length}))->write;
|
||||
}
|
||||
$token = $record->mod_token;
|
||||
$short .= '/'.$key if (defined($key));
|
||||
|
||||
$limit = $record->delete_at_day;
|
||||
$created = $record->created_at;
|
||||
} else {
|
||||
# Houston, we have a problem
|
||||
$msg = $c->l('There is no more available URL. Retry or contact the administrator. %1', $c->config->{contact});
|
||||
}
|
||||
} else {
|
||||
$msg = $c->l('The file %1 is not an image.', $upload->filename);
|
||||
}
|
||||
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
if (defined($short)) {
|
||||
$msg = {
|
||||
filename => $upload->filename,
|
||||
short => $short,
|
||||
real_short => $real_short,
|
||||
token => $token,
|
||||
ext => $ext || extensions($mediatype),
|
||||
thumb => $thumb,
|
||||
del_at_view => ($c->param('first-view')) ? true : false,
|
||||
limit => $limit,
|
||||
created_at => $created
|
||||
};
|
||||
} else {
|
||||
$msg = {
|
||||
filename => $upload->filename,
|
||||
msg => $msg
|
||||
};
|
||||
}
|
||||
return $c->render(
|
||||
json => {
|
||||
success => (defined($short)) ? Mojo::JSON->true : Mojo::JSON->false,
|
||||
msg => $msg
|
||||
}
|
||||
);
|
||||
} else {
|
||||
if ((defined($msg))) {
|
||||
$c->flash(msg => $msg);
|
||||
$c->flash(filename => $upload->filename);
|
||||
return $c->redirect_to('/');
|
||||
} else {
|
||||
$c->stash(short => $short) if (defined($short));
|
||||
$c->stash(real_short => $real_short);
|
||||
$c->stash(token => $token);
|
||||
$c->stash(ext => $ext || extensions($mediatype));
|
||||
$c->stash(thumb => $thumb);
|
||||
$c->stash(filename => $upload->filename);
|
||||
return $c->render(
|
||||
template => 'index',
|
||||
max_file_size => $c->req->max_message_size
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (defined($c->param('format')) && $c->param('format') eq 'json') {
|
||||
return $c->render(
|
||||
json => {
|
||||
success => Mojo::JSON->false,
|
||||
msg => {
|
||||
filename => $upload->filename,
|
||||
msg => $c->stash('stop_upload')
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$c->flash(msg => $c->stash('stop_upload'));
|
||||
$c->flash(filename => $upload->filename);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub short {
|
||||
my $c = shift;
|
||||
my $short = $c->param('short');
|
||||
my $touit = $c->param('t');
|
||||
my $key = $c->param('key');
|
||||
my $thumb = $c->param('thumb');
|
||||
my $dl = (defined($c->param('dl'))) ? 'attachment' : 'inline';
|
||||
|
||||
my $image = Lutim::DB::Image->new(app => $c->app, short => $short);
|
||||
if ($image->enabled && $image->path) {
|
||||
if($image->delete_at_day && $image->created_at + $image->delete_at_day * 86400 <= time()) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] someone tried to view '.$image->filename.' but it has been removed by expiration (path: '.$image->path.')');
|
||||
|
||||
# Delete image
|
||||
$c->delete_image($image);
|
||||
|
||||
# Warn user
|
||||
$c->flash(
|
||||
msg => $c->l('Unable to find the image: it has been deleted.')
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
|
||||
my $test;
|
||||
if (defined($touit)) {
|
||||
$test = 1;
|
||||
my $short = $image->short;
|
||||
$short .= '/'.$key if (defined($key));
|
||||
my ($width, $height) = (340,340);
|
||||
if ($image->mediatype eq 'image/gif') {
|
||||
if (defined($image->width) && defined($image->height)) {
|
||||
($width, $height) = ($image->width, $image->height);
|
||||
} elsif ($im_loaded) {
|
||||
my $upload = $c->decrypt($key, $image->path);
|
||||
my $im = Image::Magick->new;
|
||||
$im->BlobToImage($upload->slurp);
|
||||
$width = $im->Get('width');
|
||||
$height = $im->Get('height');
|
||||
|
||||
$image->width($width)
|
||||
->height($height)
|
||||
->write;
|
||||
}
|
||||
}
|
||||
return $c->render(
|
||||
template => 'twitter',
|
||||
layout => undef,
|
||||
short => $short,
|
||||
filename => $image->filename,
|
||||
mimetype => ($c->req->url->to_abs()->scheme eq 'https') ? $image->mediatype : '',
|
||||
width => $width,
|
||||
height => $height
|
||||
);
|
||||
} else {
|
||||
# Delete image if needed
|
||||
if ($image->delete_at_first_view && $image->counter >= 1) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')');
|
||||
|
||||
# Delete image
|
||||
$c->delete_image($image);
|
||||
|
||||
$c->flash(
|
||||
msg => $c->l('Unable to find the image: it has been deleted.')
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
} else {
|
||||
my $expires = ($image->delete_at_day) ? $image->delete_at_day : 360;
|
||||
my $dt = DateTime->from_epoch( epoch => $expires * 86400 + $image->created_at);
|
||||
$dt->set_time_zone('GMT');
|
||||
$expires = $dt->strftime("%a, %d %b %Y %H:%M:%S GMT");
|
||||
|
||||
$test = $c->render_file($im_loaded, $image->filename, $image->path, $image->mediatype, $dl, $expires, $image->delete_at_first_view, $key, $thumb);
|
||||
}
|
||||
}
|
||||
|
||||
if ($test != 500) {
|
||||
# Update counter
|
||||
$c->on(finish => sub {
|
||||
# Log access
|
||||
$c->app->log->info('[VIEW] someone viewed '.$image->filename.' (path: '.$image->path.')');
|
||||
|
||||
# Update record
|
||||
if ($c->config('minion')->{enabled}) {
|
||||
$c->app->minion->enqueue(accessed => [$image->short, time]);
|
||||
} else {
|
||||
$image->accessed(time);
|
||||
}
|
||||
|
||||
# Delete image if needed
|
||||
if ($image->delete_at_first_view) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')');
|
||||
|
||||
# Delete image
|
||||
$c->delete_image($image);
|
||||
}
|
||||
});
|
||||
}
|
||||
} elsif ($image->path && !$image->enabled) {
|
||||
# Log access try
|
||||
$c->app->log->info('[NOT FOUND] someone tried to view '.$short.' but it does\'nt exist anymore.');
|
||||
|
||||
# Warn user
|
||||
$c->flash(
|
||||
msg => $c->l('Unable to find the image: it has been deleted.')
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
} else {
|
||||
# Image never existed
|
||||
$c->render_not_found;
|
||||
}
|
||||
}
|
||||
|
||||
sub zip {
|
||||
my $c = shift;
|
||||
my $imgs = $c->every_param('i');
|
||||
|
||||
my $img_nb = scalar(@{$imgs});
|
||||
my $max_zip = $c->config('max_files_in_zip');
|
||||
|
||||
if ($img_nb <= $max_zip) {
|
||||
my $zip = Archive::Zip->new();
|
||||
|
||||
# We HAVE to add a png file at the beginning, otherwise the $zip
|
||||
# could use the mimetype of an SVG file if it's the first file asked.
|
||||
$zip->addFile('themes/default/public/img/favicon.png', 'hosted_with_lutim.png');
|
||||
|
||||
$zip->addDirectory('images/');
|
||||
for my $img (@{$imgs}) {
|
||||
my ($short, $key) = split('/', $img);
|
||||
if (defined $key) {
|
||||
$key =~ s/\.[^.]*//;
|
||||
} else {
|
||||
$short =~ s/\.[^.]*//;
|
||||
}
|
||||
my $image = Lutim::DB::Image->new(app => $c->app, short => $short);
|
||||
|
||||
if ($image->enabled && $image->path) {
|
||||
my $filename = $image->filename;
|
||||
if($image->delete_at_day && $image->created_at + $image->delete_at_day * 86400 <= time()) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] someone tried to view '.$image->filename.' but it has been removed by expiration (path: '.$image->path.')');
|
||||
|
||||
# Delete image
|
||||
$c->delete_image($image);
|
||||
|
||||
# Warn user
|
||||
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$filename.'.txt');
|
||||
next;
|
||||
}
|
||||
|
||||
# Delete image if needed
|
||||
if ($image->delete_at_first_view && $image->counter >= 1) {
|
||||
# Log deletion
|
||||
$c->app->log->info('[DELETION] someone made '.$image->filename.' removed (path: '.$image->path.')');
|
||||
|
||||
# Delete image
|
||||
$c->delete_image($image);
|
||||
|
||||
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$filename.'.txt');
|
||||
next;
|
||||
} else {
|
||||
my $expires = ($image->delete_at_day) ? $image->delete_at_day : 360;
|
||||
my $dt = DateTime->from_epoch( epoch => $expires * 86400 + $image->created_at);
|
||||
$dt->set_time_zone('GMT');
|
||||
$expires = $dt->strftime("%a, %d %b %Y %H:%M:%S GMT");
|
||||
|
||||
my $path = $image->path;
|
||||
unless ( -f $path && -r $path ) {
|
||||
$c->app->log->error("Cannot read file [$path]. error [$!]");
|
||||
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$filename.'.txt');
|
||||
next;
|
||||
}
|
||||
|
||||
if ($key) {
|
||||
$zip->addString($c->decrypt($key, $path)->slurp, "images/$filename");
|
||||
} else {
|
||||
$zip->addFile($path, "images/$filename");
|
||||
}
|
||||
|
||||
# Log access
|
||||
$c->app->log->info('[VIEW] someone viewed '.$image->filename.' (path: '.$image->path.')');
|
||||
|
||||
# Update counter and record
|
||||
if ($c->config('minion')->{enabled}) {
|
||||
$c->app->minion->enqueue(accessed => [$image->short, time]);
|
||||
} else {
|
||||
$image->accessed(time);
|
||||
}
|
||||
}
|
||||
} elsif ($image->path && !$image->enabled) {
|
||||
# Log access try
|
||||
$c->app->log->info('[NOT FOUND] someone tried to view '.$short.' but it does\'nt exist anymore.');
|
||||
|
||||
# Warn user
|
||||
$zip->addString(encode('UTF-8', $c->l('Unable to find the image: it has been deleted.')), 'images/'.$image->filename.'.txt');
|
||||
next;
|
||||
} else {
|
||||
$zip->addString(encode('UTF-8', $c->l('Image not found.')), 'images/'.$short.'.txt');
|
||||
next;
|
||||
}
|
||||
}
|
||||
my ($fh, $zipfile) = Archive::Zip::tempFile();
|
||||
unless ($zip->writeToFileNamed($zipfile) == AZ_OK) {
|
||||
$c->flash(
|
||||
msg => $c->l('Something went wrong when creating the zip file. Try again later or contact the administrator (%1).', $c->config('contact'))
|
||||
);
|
||||
return $c->redirect_to('/');
|
||||
}
|
||||
$c->res->content->headers->content_type('application/zip;name=images.zip');
|
||||
$c->res->content->headers->content_disposition('attachment;filename=images.zip');;
|
||||
|
||||
my $asset = Mojo::Asset::File->new(path => $zipfile);
|
||||
$c->res->content->asset($asset);
|
||||
$c->res->content->headers->content_length($asset->size);
|
||||
|
||||
unlink $zipfile;
|
||||
|
||||
return $c->rendered(200);
|
||||
} else {
|
||||
my $i = -1;
|
||||
my @urls = ();
|
||||
my @esc_imgs = map { my $e = $_; $e = url_escape($e); $e =~ s#%2F#/#g; $e } @{$imgs};
|
||||
while (++$i < $img_nb) {
|
||||
my $stop = ($i + $max_zip - 1 < $img_nb) ? $i + $max_zip - 1 : $img_nb - 1;
|
||||
push @urls, $c->url_for('/zip')->to_abs->to_string.'?i='.join('&i=', @esc_imgs[$i..$stop]);
|
||||
$i = $stop;
|
||||
}
|
||||
$c->render(
|
||||
template => 'zip',
|
||||
urls => \@urls
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
||||
332
lib/Lutim/DB/Image.pm
Normal file
@@ -0,0 +1,332 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::DB::Image;
|
||||
use Mojo::Base -base;
|
||||
|
||||
has 'short';
|
||||
has 'path';
|
||||
has 'footprint';
|
||||
has 'enabled';
|
||||
has 'mediatype';
|
||||
has 'filename';
|
||||
has 'counter' => 0;
|
||||
has 'delete_at_first_view';
|
||||
has 'delete_at_day';
|
||||
has 'created_at';
|
||||
has 'created_by';
|
||||
has 'last_access_at';
|
||||
has 'mod_token';
|
||||
has 'width';
|
||||
has 'height';
|
||||
has 'app';
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Lutim::DB::Image - DB abstraction layer for Lutim images
|
||||
|
||||
=head1 Contributing
|
||||
|
||||
When creating a new database accessor, make sure that it provides the following subroutines.
|
||||
After that, modify this file and modify the C<new> subroutine to allow to use your accessor.
|
||||
|
||||
Have a look at Lutim::DB::Image::SQLite's code: it's simple and may be more understandable that this doc.
|
||||
|
||||
=head1 Attributes
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<short> : random string
|
||||
|
||||
=item B<path> : string, path to the image, relative to lutim's installation directory
|
||||
|
||||
=item B<footprint> : string, sha512 checksum of the image
|
||||
|
||||
=item B<enabled> : boolean, is the image accessible?
|
||||
|
||||
=item B<mediatype> : string, mimetype of the image
|
||||
|
||||
=item B<filename> : string
|
||||
|
||||
=item B<counter> : integer
|
||||
|
||||
=item B<delete_at_first_view> : boolean
|
||||
|
||||
=item B<delete_at_day> : integer, number of days from image upload to deletion
|
||||
|
||||
=item B<created_at> : unix timestamp
|
||||
|
||||
=item B<created_by> : unix timestamp
|
||||
|
||||
=item B<last_access_at> : unix timestamp
|
||||
|
||||
=item B<mod_token> : random string
|
||||
|
||||
=item B<width> : integer
|
||||
|
||||
=item B<height> : integer
|
||||
|
||||
=item B<app> : a mojolicious object
|
||||
|
||||
=back
|
||||
|
||||
=head1 Sub routines
|
||||
|
||||
=head2 new
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c = Lutim::DB::Image-E<gt>new(app =E<gt> $self);>
|
||||
|
||||
=item B<Arguments> : any of the attribute above
|
||||
|
||||
=item B<Purpose> : construct a new db accessor object. If the C<short> attribute is provided, it have to load the informations from the database.
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=item B<Info> : the app argument is used by Lutim::DB::Image to choose which db accessor will be used, you don't need to use it in new(), but you can use it to access helpers or configuration settings in the other subroutines
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my $c = shift;
|
||||
|
||||
$c = $c->SUPER::new(@_);
|
||||
|
||||
if (ref($c) eq 'Lutim::DB::Image') {
|
||||
my $dbtype = $c->app->config('dbtype');
|
||||
if ($dbtype eq 'sqlite') {
|
||||
use Lutim::DB::Image::SQLite;
|
||||
$c = Lutim::DB::Image::SQLite->new(@_);
|
||||
} elsif ($dbtype eq 'postgresql') {
|
||||
use Lutim::DB::Image::Pg;
|
||||
$c = Lutim::DB::Image::Pg->new(@_);
|
||||
}
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub to_hash {
|
||||
my $c = shift;
|
||||
|
||||
return {
|
||||
short => $c->short,
|
||||
path => $c->path,
|
||||
footprint => $c->footprint,
|
||||
enabled => $c->enabled,
|
||||
mediatype => $c->mediatype,
|
||||
filename => $c->filename,
|
||||
counter => $c->counter,
|
||||
delete_at_first_view => $c->delete_at_first_view,
|
||||
delete_at_day => $c->delete_at_day,
|
||||
created_at => $c->created_at,
|
||||
created_by => $c->created_by,
|
||||
last_access_at => $c->last_access_at,
|
||||
mod_token => $c->mod_token,
|
||||
width => $c->width,
|
||||
height => $c->height
|
||||
};
|
||||
}
|
||||
|
||||
=head2 accessed
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>accessed($time)>
|
||||
|
||||
=item B<Arguments> : an unix timestamp
|
||||
|
||||
=item B<Purpose> : increments the counter attribute by one, set the last_access_at attribute to $time and update the database
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=head2 count_delete_at_day_endis
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>count_delete_at_day_endis($delete_at_day, $enabled[, $time])>
|
||||
|
||||
=item B<Arguments> : two mandatory parameters: one integer, the delete_at_day attribute, a boolean (0 or 1), the enabled attribute
|
||||
an optional parameter: an unix timestamp
|
||||
|
||||
=item B<Purpose> : count how many images there is with the given delete_at_day attribute, and enabled or disabled, depending on the given enabled attribute
|
||||
if the optional parameter is given, count only images according to the given mandatory parameters that were created before the timestamp
|
||||
|
||||
=item B<Returns> : integer
|
||||
|
||||
=back
|
||||
|
||||
=head2 count_created_before
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>count_created_before($time)>
|
||||
|
||||
=item B<Arguments> : an unix timestamp
|
||||
|
||||
=item B<Purpose> : count how many images have been created before the given timestamp
|
||||
|
||||
=item B<Returns> : integer
|
||||
|
||||
=back
|
||||
|
||||
=head2 select_created_after
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>select_created_after($time)>
|
||||
|
||||
=item B<Arguments> : an unix timestamp
|
||||
|
||||
=item B<Purpose> : select images created after the given timestamp
|
||||
|
||||
=item B<Returns> : a Mojo::Collection object containing the images created after the given timestamp
|
||||
|
||||
=back
|
||||
|
||||
=head2 select_empty
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>select_empty>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : select a ready-to-use empty record
|
||||
|
||||
=item B<Returns> : a db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=head2 write
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>write>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : create or update a record in the database, with the values of the object's attributes
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=head2 count_short
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>count_short($short)>
|
||||
|
||||
=item B<Arguments> : a random string, unique image identifier in the database
|
||||
|
||||
=item B<Purpose> : checks that an identifier isn't already used
|
||||
|
||||
=item B<Returns> : integer, number of records having this identifier (should be 0 or 1)
|
||||
|
||||
=back
|
||||
|
||||
=head2 count_empty
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>count_empty>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : counts the number of record which path is null
|
||||
|
||||
=item B<Returns> : integer
|
||||
|
||||
=back
|
||||
|
||||
=head2 count_not_empty
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>count_not_empty>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : counts the number of record which path is not null
|
||||
|
||||
=item B<Returns> : integer
|
||||
|
||||
=back
|
||||
|
||||
=head2 clean_ips_until
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>clean_ips_until($time)>
|
||||
|
||||
=item B<Arguments> : unix timestamp
|
||||
|
||||
=item B<Purpose> : remove the image's sender information on images created before the given timestamp
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=head2 get_no_longer_viewed_files
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>get_no_longer_viewed_files($time)>
|
||||
|
||||
=item B<Arguments> : unix timestamp
|
||||
|
||||
=item B<Purpose> : get images no longer viewed after the given timestamp
|
||||
|
||||
=item B<Returns> : a Mojo::Collection object containing the no longer viewed images as Lutim::DB::Image objects
|
||||
|
||||
=back
|
||||
|
||||
=head2 get_images_to_clean
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>get_images_to_clean>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : get images that are expired but not marked as it
|
||||
|
||||
=item B<Returns> : a Mojo::Collection object containing the images to clean as Lutim::DB::Image objects
|
||||
|
||||
=back
|
||||
|
||||
=head2 get_50_oldest
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>get_50_oldest>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : get the 50 oldest enabled images
|
||||
|
||||
=item B<Returns> : a Mojo::Collection object containing the 50 oldest enabled images as Lutim::DB::Image objects
|
||||
|
||||
=back
|
||||
|
||||
=head2 disable
|
||||
|
||||
=over 1
|
||||
|
||||
=item B<Usage> : C<$c-E<gt>disable>
|
||||
|
||||
=item B<Arguments> : none
|
||||
|
||||
=item B<Purpose> : change the attribute C<enabled> to false and update the database record
|
||||
|
||||
=item B<Returns> : the db accessor object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
230
lib/Lutim/DB/Image/Pg.pm
Normal file
@@ -0,0 +1,230 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::DB::Image::Pg;
|
||||
use Mojo::Base 'Lutim::DB::Image';
|
||||
use Mojo::Collection 'c';
|
||||
|
||||
has 'record' => 0;
|
||||
|
||||
sub new {
|
||||
my $c = shift;
|
||||
|
||||
$c = $c->SUPER::new(@_);
|
||||
$c = $c->_slurp if ($c->short);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub accessed {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
my $h = $c->app->pg->db->query('UPDATE lutim SET counter = counter + 1, last_access_at = ? WHERE short = ? RETURNING counter, last_access_at', $time, $c->short)->hashes->first;
|
||||
$c->counter($h->{counter});
|
||||
$c->last_access_at($h->{last_access_at});
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub count_delete_at_day_endis {
|
||||
my $c = shift;
|
||||
my $day = shift;
|
||||
my $enabled = shift;
|
||||
my $created = shift;
|
||||
|
||||
if (defined $created) {
|
||||
return $c->app->pg->db->query('SELECT count(short) FROM lutim WHERE path IS NOT NULL AND delete_at_day = ? AND enabled = ? AND created_at < ?', $day, $enabled, $created)->hashes->first->{count};
|
||||
} else {
|
||||
return $c->app->pg->db->query('SELECT count(short) FROM lutim WHERE path IS NOT NULL AND delete_at_day = ? AND enabled = ?', $day, $enabled)->hashes->first->{count};
|
||||
}
|
||||
}
|
||||
|
||||
sub count_created_before {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
return $c->app->pg->db->query('SELECT count(short) FROM lutim WHERE path IS NOT NULL AND created_at < ?', $time)->hashes->first->{count};
|
||||
}
|
||||
|
||||
sub select_created_after {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
my @images;
|
||||
|
||||
my $records = $c->app->pg->db->query('SELECT * FROM lutim WHERE path IS NOT NULL AND created_at >= ?', $time)->hashes;
|
||||
|
||||
$records->each(
|
||||
sub {
|
||||
my ($e, $num) = @_;
|
||||
my $i = Lutim::DB::Image->new(app => $c->app);
|
||||
$i->_slurp($e);
|
||||
|
||||
push @images, $i;
|
||||
}
|
||||
);
|
||||
|
||||
return c(@images);
|
||||
}
|
||||
|
||||
sub select_empty {
|
||||
my $c = shift;
|
||||
|
||||
my $record = $c->app->pg->db->query('SELECT * FROM lutim WHERE path IS NULL')->hashes->shuffle->first;
|
||||
$c->app->pg->db->query('UPDATE lutim SET path = ? WHERE short = ?', 'used', $record->{short});
|
||||
|
||||
$c = $c->_slurp($record);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub write {
|
||||
my $c = shift;
|
||||
|
||||
if ($c->record) {
|
||||
$c->app->pg->db->query('UPDATE lutim SET counter = ?, created_at = ?, created_by = ?, delete_at_day = ?, delete_at_first_view = ?, enabled = ?, filename = ?, footprint = ?, height = ?, last_access_at = ?, mediatype = ?, mod_token = ?, path = ?, short = ?, width = ? WHERE short = ?', $c->counter, $c->created_at, $c->created_by, $c->delete_at_day, $c->delete_at_first_view, $c->enabled, $c->filename, $c->footprint, $c->height, $c->last_access_at, $c->mediatype, $c->mod_token, $c->path, $c->short, $c->width, $c->short);
|
||||
} else {
|
||||
$c->app->pg->db->query('INSERT INTO lutim (counter, created_at, created_by, delete_at_day, delete_at_first_view, enabled, filename, footprint, height, last_access_at, mediatype, mod_token, path, short, width) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', $c->counter, $c->created_at, $c->created_by, $c->delete_at_day, $c->delete_at_first_view, $c->enabled, $c->filename, $c->footprint, $c->height, $c->last_access_at, $c->mediatype, $c->mod_token, $c->path, $c->short, $c->width);
|
||||
$c->record(1);
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub count_short {
|
||||
my $c = shift;
|
||||
my $short = shift;
|
||||
|
||||
return $c->app->pg->db->query('SELECT count(short) FROM lutim WHERE short = ?', $short)->hashes->first->{count};
|
||||
}
|
||||
|
||||
sub count_empty {
|
||||
my $c = shift;
|
||||
|
||||
return $c->app->pg->db->query('SELECT count(short) FROM lutim WHERE path IS NULL')->hashes->first->{count};
|
||||
}
|
||||
|
||||
sub count_not_empty {
|
||||
my $c = shift;
|
||||
|
||||
return $c->app->pg->db->query('SELECT count(short) FROM lutim WHERE path IS NOT NULL')->hashes->first->{count};
|
||||
}
|
||||
|
||||
sub clean_ips_until {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
$c->app->pg->db->query('UPDATE lutim SET created_by = NULL WHERE path IS NOT NULL AND created_at < ?', $time);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub get_no_longer_viewed_files {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
my @images;
|
||||
|
||||
my $records = $c->app->pg->db->query('SELECT * FROM lutim WHERE enabled = 1 AND last_access_at < ?', $time)->{hashes};
|
||||
|
||||
$records->each(
|
||||
sub {
|
||||
my ($e, $num) = @_;
|
||||
my $i = Lutim::DB::Image->new(app => $c->app);
|
||||
$i->record(1);
|
||||
$i->_slurp($e);
|
||||
|
||||
push @images, $i;
|
||||
}
|
||||
);
|
||||
|
||||
return c(@images);
|
||||
}
|
||||
|
||||
sub get_images_to_clean {
|
||||
my $c = shift;
|
||||
|
||||
my @images;
|
||||
|
||||
my $records = $c->app->pg->db->query('SELECT * FROM lutim WHERE enabled = 1 AND (delete_at_day * 86400) < (? - created_at) AND delete_at_day != 0', time())->hashes;
|
||||
|
||||
$records->each(
|
||||
sub {
|
||||
my ($e, $num) = @_;
|
||||
my $i = Lutim::DB::Image->new(app => $c->app);
|
||||
$i->_slurp($e);
|
||||
|
||||
push @images, $i;
|
||||
}
|
||||
);
|
||||
|
||||
return c(@images);
|
||||
}
|
||||
|
||||
sub get_50_oldest {
|
||||
my $c = shift;
|
||||
|
||||
my @images;
|
||||
|
||||
my $records = $c->app->pg->db->query('SELECT * FROM lutim WHERE path IS NOT NULL AND enabled = 1 ORDER BY created_at ASC LIMIT 50')->hashes;
|
||||
|
||||
$records->each(
|
||||
sub {
|
||||
my ($e, $num) = @_;
|
||||
my $i = Lutim::DB::Image->new(app => $c->app);
|
||||
$i->_slurp($e);
|
||||
|
||||
push @images, $i;
|
||||
}
|
||||
);
|
||||
|
||||
return c(@images);
|
||||
}
|
||||
|
||||
sub disable {
|
||||
my $c = shift;
|
||||
|
||||
$c->app->pg->db->query('UPDATE lutim SET enabled = 0 WHERE short = ?', $c->short);
|
||||
$c->enabled(0);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub _slurp {
|
||||
my $c = shift;
|
||||
my $r = shift;
|
||||
|
||||
my $image;
|
||||
if (defined $r) {
|
||||
$image = $r;
|
||||
} else {
|
||||
my $images = $c->app->pg->db->query('SELECT * FROM lutim WHERE short = ?', $c->short)->hashes;
|
||||
|
||||
if ($images->size) {
|
||||
$image = $images->first;
|
||||
}
|
||||
}
|
||||
|
||||
if ($image) {
|
||||
$c->short($image->{short});
|
||||
$c->path($image->{path});
|
||||
$c->footprint($image->{footprint});
|
||||
$c->enabled($image->{enabled});
|
||||
$c->mediatype($image->{mediatype});
|
||||
$c->filename($image->{filename});
|
||||
$c->counter($image->{counter});
|
||||
$c->delete_at_first_view($image->{delete_at_first_view});
|
||||
$c->delete_at_day($image->{delete_at_day});
|
||||
$c->created_at($image->{created_at});
|
||||
$c->created_by($image->{created_by});
|
||||
$c->last_access_at($image->{last_access_at});
|
||||
$c->mod_token($image->{mod_token});
|
||||
$c->width($image->{width});
|
||||
$c->height($image->{height});
|
||||
|
||||
$c->record(1);
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
1;
|
||||
260
lib/Lutim/DB/Image/SQLite.pm
Normal file
@@ -0,0 +1,260 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::DB::Image::SQLite;
|
||||
use Mojo::Base 'Lutim::DB::Image';
|
||||
use Lutim::DB::SQLite;
|
||||
use Mojo::Collection 'c';
|
||||
|
||||
has 'record';
|
||||
|
||||
sub new {
|
||||
my $c = shift;
|
||||
|
||||
$c = $c->SUPER::new(@_);
|
||||
$c = $c->_slurp if ($c->short);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub accessed {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
$c->record->update(
|
||||
counter => $c->counter + 1,
|
||||
last_access_at => $time
|
||||
);
|
||||
|
||||
$c->counter($c->record->counter);
|
||||
$c->last_access_at($c->record->last_access_at);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub count_delete_at_day_endis {
|
||||
my $c = shift;
|
||||
my $day = shift;
|
||||
my $enabled = shift;
|
||||
my $created = shift;
|
||||
|
||||
if (defined $created) {
|
||||
return Lutim::DB::SQLite::Lutim->count('WHERE path IS NOT NULL AND delete_at_day = ? AND enabled = ? AND created_at < ?', $day, $enabled, $created);
|
||||
} else {
|
||||
return Lutim::DB::SQLite::Lutim->count('WHERE path IS NOT NULL AND delete_at_day = ? AND enabled = ?', $day, $enabled);
|
||||
}
|
||||
}
|
||||
|
||||
sub count_created_before {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
return Lutim::DB::SQLite::Lutim->count('WHERE path IS NOT NULL AND created_at < ?', $time);
|
||||
}
|
||||
|
||||
sub select_created_after {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
my @images;
|
||||
|
||||
my @records = Lutim::DB::SQLite::Lutim->select('WHERE path IS NOT NULL AND created_at >= ?', $time);
|
||||
|
||||
for my $e (@records) {
|
||||
my $i = Lutim::DB::Image->new(app => $c->app);
|
||||
$i->record($e);
|
||||
$i->_slurp;
|
||||
|
||||
push @images, $i;
|
||||
}
|
||||
|
||||
return c(@images);
|
||||
}
|
||||
|
||||
sub select_empty {
|
||||
my $c = shift;
|
||||
|
||||
my $record = c(Lutim::DB::SQLite::Lutim->select('WHERE path IS NULL'))->shuffle->first;
|
||||
$record->update(path => 'used');
|
||||
|
||||
$c->record($record);
|
||||
$c = $c->_slurp;
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub write {
|
||||
my $c = shift;
|
||||
|
||||
if ($c->record) {
|
||||
$c->record->update(
|
||||
counter => $c->counter,
|
||||
created_at => $c->created_at,
|
||||
created_by => $c->created_by,
|
||||
delete_at_day => $c->delete_at_day,
|
||||
delete_at_first_view => $c->delete_at_first_view,
|
||||
enabled => $c->enabled,
|
||||
filename => $c->filename,
|
||||
footprint => $c->footprint,
|
||||
height => $c->height,
|
||||
last_access_at => $c->last_access_at,
|
||||
mediatype => $c->mediatype,
|
||||
mod_token => $c->mod_token,
|
||||
path => $c->path,
|
||||
short => $c->short,
|
||||
width => $c->width
|
||||
);
|
||||
} else {
|
||||
my $record = Lutim::DB::SQLite::Lutim->create(
|
||||
counter => $c->counter,
|
||||
created_at => $c->created_at,
|
||||
created_by => $c->created_by,
|
||||
delete_at_day => $c->delete_at_day,
|
||||
delete_at_first_view => $c->delete_at_first_view,
|
||||
enabled => $c->enabled,
|
||||
filename => $c->filename,
|
||||
footprint => $c->footprint,
|
||||
height => $c->height,
|
||||
last_access_at => $c->last_access_at,
|
||||
mediatype => $c->mediatype,
|
||||
mod_token => $c->mod_token,
|
||||
path => $c->path,
|
||||
short => $c->short,
|
||||
width => $c->width
|
||||
);
|
||||
$c->record($record);
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub count_short {
|
||||
my $c = shift;
|
||||
my $short = shift;
|
||||
|
||||
return Lutim::DB::SQLite::Lutim->count('WHERE short IS ?', $short);
|
||||
}
|
||||
|
||||
sub count_empty {
|
||||
my $c = shift;
|
||||
|
||||
return Lutim::DB::SQLite::Lutim->count('WHERE path IS NULL');
|
||||
}
|
||||
|
||||
sub count_not_empty {
|
||||
my $c = shift;
|
||||
|
||||
return Lutim::DB::SQLite::Lutim->count('WHERE path IS NOT NULL');
|
||||
}
|
||||
|
||||
sub clean_ips_until {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
Lutim::DB::SQLite->do(
|
||||
'UPDATE lutim SET created_by = "" WHERE path IS NOT NULL AND created_at < ?',
|
||||
{},
|
||||
$time
|
||||
);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub get_no_longer_viewed_files {
|
||||
my $c = shift;
|
||||
my $time = shift;
|
||||
|
||||
my @images;
|
||||
|
||||
my @records = Lutim::DB::SQLite::Lutim->select('WHERE enabled = 1 AND last_access_at < ?', $time);
|
||||
|
||||
for my $e (@records) {
|
||||
my $i = Lutim::DB::Image->new(app => $c->app);
|
||||
$i->record($e);
|
||||
$i->_slurp;
|
||||
|
||||
push @images, $i;
|
||||
}
|
||||
|
||||
return c(@images);
|
||||
}
|
||||
|
||||
sub get_images_to_clean {
|
||||
my $c = shift;
|
||||
|
||||
my @images;
|
||||
|
||||
my @records = Lutim::DB::SQLite::Lutim->select('WHERE enabled = 1 AND (delete_at_day * 86400) < (? - created_at) AND delete_at_day != 0', time());
|
||||
|
||||
for my $e (@records) {
|
||||
my $i = Lutim::DB::Image->new(app => $c->app);
|
||||
$i->record($e);
|
||||
$i->_slurp;
|
||||
|
||||
push @images, $i;
|
||||
}
|
||||
|
||||
return c(@images);
|
||||
}
|
||||
|
||||
sub get_50_oldest {
|
||||
my $c = shift;
|
||||
|
||||
my @images;
|
||||
|
||||
my @records = Lutim::DB::SQLite::Lutim->select('WHERE path IS NOT NULL AND enabled = 1 ORDER BY created_at ASC LIMIT 50');
|
||||
|
||||
for my $e (@records) {
|
||||
my $i = Lutim::DB::Image->new(app => $c->app);
|
||||
$i->record($e);
|
||||
$i->_slurp;
|
||||
|
||||
push @images, $i;
|
||||
}
|
||||
|
||||
return c(@images);
|
||||
}
|
||||
|
||||
sub disable {
|
||||
my $c = shift;
|
||||
|
||||
$c->record->update(enabled => 0);
|
||||
$c->enabled(0);
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
sub _slurp {
|
||||
my $c = shift;
|
||||
|
||||
my @images;
|
||||
if ($c->record) {
|
||||
@images = ($c->record);
|
||||
} elsif ($c->short) {
|
||||
@images = Lutim::DB::SQLite::Lutim->select('WHERE short = ?', $c->short);
|
||||
}
|
||||
|
||||
if (scalar @images) {
|
||||
my $image = $images[0];
|
||||
|
||||
$c->short($image->short);
|
||||
$c->path($image->path);
|
||||
$c->footprint($image->footprint);
|
||||
$c->enabled($image->enabled);
|
||||
$c->mediatype($image->mediatype);
|
||||
$c->filename($image->filename);
|
||||
$c->counter($image->counter);
|
||||
$c->delete_at_first_view($image->delete_at_first_view);
|
||||
$c->delete_at_day($image->delete_at_day);
|
||||
$c->created_at($image->created_at);
|
||||
$c->created_by($image->created_by);
|
||||
$c->last_access_at($image->last_access_at);
|
||||
$c->mod_token($image->mod_token);
|
||||
$c->width($image->width);
|
||||
$c->height($image->height);
|
||||
|
||||
$c->record($image) unless $c->record;
|
||||
}
|
||||
|
||||
return $c;
|
||||
}
|
||||
|
||||
1;
|
||||
54
lib/Lutim/DB/SQLite.pm
Normal file
@@ -0,0 +1,54 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::DB::SQLite;
|
||||
use Mojolicious;
|
||||
use Mojo::File;
|
||||
use FindBin qw($Bin);
|
||||
|
||||
BEGIN {
|
||||
my $m = Mojolicious->new;
|
||||
my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf');
|
||||
if (defined $ENV{MOJO_CONFIG}) {
|
||||
$cfile = Mojo::File->new($ENV{MOJO_CONFIG});
|
||||
unless (-e $cfile->to_abs) {
|
||||
$cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG});
|
||||
}
|
||||
}
|
||||
our $config = $m->plugin('Config' =>
|
||||
{
|
||||
file => $cfile->to_abs->to_string,
|
||||
default => {
|
||||
db_path => 'lutim.db'
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
# Create database
|
||||
use ORLite {
|
||||
file => $config->{db_path},
|
||||
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,
|
||||
mod_token TEXT,
|
||||
width INTEGER,
|
||||
height INTEGER)'
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
|
||||
1;
|
||||
@@ -1,49 +0,0 @@
|
||||
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:',
|
||||
'twitter-link' => 'Link for put in a tweet:',
|
||||
'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;
|
||||
@@ -1,49 +0,0 @@
|
||||
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 :',
|
||||
'twitter-link' => 'Lien pour mettre dans un tweet :',
|
||||
'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;
|
||||
245
lib/Lutim/Plugin/Helpers.pm
Normal file
@@ -0,0 +1,245 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Lutim::Plugin::Helpers;
|
||||
use Mojo::Base 'Mojolicious::Plugin';
|
||||
use Mojo::Util qw(quote);
|
||||
use Crypt::CBC;
|
||||
use Data::Entropy qw(entropy_source);
|
||||
|
||||
sub register {
|
||||
my ($self, $app) = @_;
|
||||
|
||||
$app->plugin('PgURLHelper');
|
||||
|
||||
if ($app->config('dbtype') eq 'postgresql') {
|
||||
use Mojo::Pg;
|
||||
$app->helper(pg => \&_pg);
|
||||
|
||||
# Database migration
|
||||
my $migrations = Mojo::Pg::Migrations->new(pg => $app->pg);
|
||||
if ($app->mode eq 'development' && $ENV{LUTIM_DEBUG}) {
|
||||
$migrations->from_file('utilities/migrations.sql')->migrate(0)->migrate(1);
|
||||
} else {
|
||||
$migrations->from_file('utilities/migrations.sql')->migrate(1);
|
||||
}
|
||||
}
|
||||
|
||||
$app->helper(render_file => \&_render_file);
|
||||
$app->helper(ip => \&_ip);
|
||||
$app->helper(provisioning => \&_provisioning);
|
||||
$app->helper(shortener => \&_shortener);
|
||||
$app->helper(stop_upload => \&_stop_upload);
|
||||
$app->helper(max_delay => \&_max_delay);
|
||||
$app->helper(default_delay => \&_default_delay);
|
||||
$app->helper(is_selected => \&_is_selected);
|
||||
$app->helper(crypt => \&_crypt);
|
||||
$app->helper(decrypt => \&_decrypt);
|
||||
$app->helper(delete_image => \&_delete_image);
|
||||
}
|
||||
|
||||
sub _pg {
|
||||
my $c = shift;
|
||||
|
||||
state $pg = Mojo::Pg->new($c->app->pg_url($c->app->config('pgdb')));
|
||||
return $pg;
|
||||
}
|
||||
|
||||
sub _render_file {
|
||||
my $c = shift;
|
||||
my ($im_loaded, $filename, $path, $mediatype, $dl, $expires, $nocache, $key, $thumb) = @_;
|
||||
|
||||
$dl = 'attachment' if ($mediatype =~ m/svg/);
|
||||
$filename = quote($filename);
|
||||
|
||||
my $asset;
|
||||
unless (-f $path && -r $path) {
|
||||
$c->app->log->error("Cannot read file [$path]. error [$!]");
|
||||
$c->flash(
|
||||
msg => $c->l('Unable to find the image: it has been deleted.')
|
||||
);
|
||||
return 500;
|
||||
}
|
||||
|
||||
$mediatype =~ s/x-//;
|
||||
|
||||
my $headers = Mojo::Headers->new();
|
||||
if ($nocache) {
|
||||
$headers->add('Cache-Control' => 'no-cache, no-store, max-age=0, must-revalidate');
|
||||
} else {
|
||||
$headers->add('Expires' => $expires);
|
||||
}
|
||||
$headers->add('Content-Type' => $mediatype.';name='.$filename);
|
||||
$headers->add('Content-Disposition' => $dl.';filename='.$filename);
|
||||
$c->res->content->headers($headers);
|
||||
|
||||
if ($key) {
|
||||
$asset = $c->decrypt($key, $path);
|
||||
} else {
|
||||
$asset = Mojo::Asset::File->new(path => $path);
|
||||
}
|
||||
|
||||
if (defined $thumb && $im_loaded && $mediatype ne 'image/svg+xml' && $mediatype !~ m#image/(x-)?xcf# && $mediatype ne 'image/webp') { # ImageMagick don't work in Debian with svg (for now?)
|
||||
my $im = Image::Magick->new;
|
||||
$im->BlobToImage($asset->slurp);
|
||||
|
||||
# Create the thumbnail
|
||||
$im->Resize(geometry=>'x'.$c->config('thumbnail_size'));
|
||||
|
||||
# Replace the asset with the thumbnail
|
||||
$asset = Mojo::Asset::Memory->new->add_chunk($im->ImageToBlob());
|
||||
}
|
||||
|
||||
$c->res->content->asset($asset);
|
||||
$headers->add('Content-Length' => $asset->size);
|
||||
|
||||
return $c->rendered(200);
|
||||
}
|
||||
|
||||
sub _ip {
|
||||
my $c = shift;
|
||||
my $ip_only = shift || 0;
|
||||
|
||||
my $proxy = $c->req->headers->header('X-Forwarded-For');
|
||||
|
||||
my $ip = ($proxy) ? $proxy : $c->tx->remote_address;
|
||||
|
||||
my $remote_port = (defined($c->req->headers->header('X-Remote-Port'))) ? $c->req->headers->header('X-Remote-Port') : $c->tx->remote_port;
|
||||
|
||||
return ($ip_only) ? $ip : "$ip remote port:$remote_port";
|
||||
}
|
||||
|
||||
sub _provisioning {
|
||||
my $c = shift;
|
||||
|
||||
# Create some short patterns for provisioning
|
||||
my $img = Lutim::DB::Image->new(app => $c->app);
|
||||
if ($img->count_empty < $c->app->config('provisioning')) {
|
||||
for (my $i = 0; $i < $c->app->config('provis_step'); $i++) {
|
||||
my $short;
|
||||
do {
|
||||
$short = $c->shortener($c->app->config('length'));
|
||||
} while ($img->count_short($short) || $short eq 'about' || $short eq 'stats' || $short eq 'd' || $short eq 'm' || $short eq 'gallery' || $short eq 'zip' || $short eq 'infos');
|
||||
|
||||
$img->short($short)
|
||||
->counter(0)
|
||||
->enabled(1)
|
||||
->delete_at_first_view(0)
|
||||
->delete_at_day(0)
|
||||
->mod_token($c->shortener($c->app->config('token_length')))
|
||||
->write;
|
||||
|
||||
$img = Lutim::DB::Image->new(app => $c->app);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub _shortener {
|
||||
my $c = shift;
|
||||
my $length = shift;
|
||||
|
||||
my @chars = ('a'..'z','A'..'Z','0'..'9');
|
||||
my $result = '';
|
||||
foreach (1..$length) {
|
||||
$result .= $chars[entropy_source->get_int(scalar(@chars))];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
sub _stop_upload {
|
||||
my $c = shift;
|
||||
|
||||
if (-f 'stop-upload' || -f 'stop-upload.manual') {
|
||||
$c->stash(
|
||||
stop_upload => $c->l('Uploading is currently disabled, please try later or contact the administrator (%1).', $c->app->config('contact'))
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub _max_delay {
|
||||
my $c = shift;
|
||||
|
||||
return $c->app->config('max_delay') if ($c->app->config('max_delay') >= 0);
|
||||
|
||||
warn "max_delay set to a negative value. Default to 0.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub _default_delay {
|
||||
my $c = shift;
|
||||
|
||||
return $c->app->config('default_delay') if ($c->app->config('default_delay') >= 0);
|
||||
|
||||
warn "default_delay set to a negative value. Default to 0.";
|
||||
return 0;
|
||||
}
|
||||
|
||||
sub _is_selected {
|
||||
my $c = shift;
|
||||
my $num = shift;
|
||||
|
||||
return ($num == $c->default_delay) ? 'selected="selected"' : '';
|
||||
}
|
||||
|
||||
sub _crypt {
|
||||
my $c = shift;
|
||||
my $upload = shift;
|
||||
my $filename = shift;
|
||||
|
||||
my $key = $c->shortener($c->config('crypto_key_length'));
|
||||
|
||||
my $cipher = Crypt::CBC->new(
|
||||
-key => $key,
|
||||
-cipher => 'Blowfish',
|
||||
-header => 'none',
|
||||
-iv => 'dupajasi'
|
||||
);
|
||||
|
||||
$cipher->start('encrypting');
|
||||
|
||||
my $crypt_asset = Mojo::Asset::File->new;
|
||||
|
||||
$crypt_asset->add_chunk($cipher->crypt($upload->slurp));
|
||||
$crypt_asset->add_chunk($cipher->finish);
|
||||
|
||||
my $crypt_upload = Mojo::Upload->new;
|
||||
$crypt_upload->filename($filename);
|
||||
$crypt_upload->asset($crypt_asset);
|
||||
|
||||
return ($crypt_upload, $key);
|
||||
}
|
||||
|
||||
sub _decrypt {
|
||||
my $c = shift;
|
||||
my $key = shift;
|
||||
my $file = shift;
|
||||
|
||||
my $cipher = Crypt::CBC->new(
|
||||
-key => $key,
|
||||
-cipher => 'Blowfish',
|
||||
-header => 'none',
|
||||
-iv => 'dupajasi'
|
||||
);
|
||||
|
||||
$cipher->start('decrypting');
|
||||
|
||||
my $decrypt_asset = Mojo::Asset::File->new;
|
||||
|
||||
open(my $f, "<",$file) or die "Unable to read encrypted file: $!";
|
||||
binmode $f;
|
||||
while (read($f, my $buffer,1024)) {
|
||||
$decrypt_asset->add_chunk($cipher->crypt($buffer));
|
||||
}
|
||||
$decrypt_asset->add_chunk($cipher->finish) ;
|
||||
|
||||
return $decrypt_asset;
|
||||
}
|
||||
|
||||
sub _delete_image {
|
||||
my $c = shift;
|
||||
my $img = shift;
|
||||
unlink $img->path or warn "Could not unlink ".$img->path.": $!";
|
||||
$img->disable();
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,29 +0,0 @@
|
||||
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;
|
||||
52
lib/Mounter.pm
Normal file
@@ -0,0 +1,52 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
package Mounter;
|
||||
use Mojo::Base 'Mojolicious';
|
||||
use Mojo::File;
|
||||
use FindBin qw($Bin);
|
||||
use File::Spec qw(catfile);
|
||||
|
||||
# This method will run once at server start
|
||||
sub startup {
|
||||
my $self = shift;
|
||||
|
||||
push @{$self->commands->namespaces}, 'Lutim::Command';
|
||||
|
||||
my $cfile = Mojo::File->new($Bin, '..' , 'lutim.conf');
|
||||
if (defined $ENV{MOJO_CONFIG}) {
|
||||
$cfile = Mojo::File->new($ENV{MOJO_CONFIG});
|
||||
unless (-e $cfile->to_abs) {
|
||||
$cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG});
|
||||
}
|
||||
}
|
||||
my $config = $self->plugin('Config' =>
|
||||
{
|
||||
file => $cfile,
|
||||
default => {
|
||||
prefix => '/',
|
||||
theme => 'default',
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$self->plugin('Lutim::Plugin::Helpers');
|
||||
|
||||
$config->{prefix} = $config->{url_sub_dir} if (defined($config->{url_sub_dir}) && $config->{prefix} eq '/');
|
||||
|
||||
$self->app->log->warn('"url_sub_dir" configuration option is deprecated. Use "prefix" instead. "url_sub_dir" will be removed in the future') if (defined($config->{url_sub_dir}));
|
||||
|
||||
# Themes handling
|
||||
shift @{$self->static->paths};
|
||||
if ($config->{theme} ne 'default') {
|
||||
my $theme = $self->home->rel_file('themes/'.$config->{theme});
|
||||
push @{$self->static->paths}, $theme.'/public' if -d $theme.'/public';
|
||||
}
|
||||
push @{$self->static->paths}, $self->home->rel_file('themes/default/public');
|
||||
|
||||
$self->hook(after_static => sub {
|
||||
my $c = shift;
|
||||
$c->res->headers->cache_control('max-age=2592000, must-revalidate');
|
||||
});
|
||||
$self->plugin('Mount' => {$config->{prefix} => File::Spec->catfile($Bin, '..', 'script', 'application')});
|
||||
}
|
||||
|
||||
1;
|
||||
@@ -1,16 +1,202 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
{
|
||||
####################
|
||||
# Hypnotoad settings
|
||||
####################
|
||||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
listen => ['http://127.0.0.1:8080'],
|
||||
user => 'www-data',
|
||||
group => 'www-data'
|
||||
# if you use Lutim behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lutim directly, let it commented
|
||||
#proxy => 1,
|
||||
},
|
||||
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
|
||||
hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">', # optional
|
||||
tweet_card_via => '@framasky' # optional
|
||||
|
||||
################
|
||||
# Lutim settings
|
||||
################
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# mandatory
|
||||
#contact => 'John Doe, admin[at]example.com',
|
||||
|
||||
# random string used to encrypt cookies
|
||||
# mandatory
|
||||
secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the images random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# length of the encryption key
|
||||
# optional, default is 8
|
||||
#crypto_key_length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# anti-flood protection delay, in seconds
|
||||
# users won't be able to ask Lutim to download images more than one per anti_flood_delay seconds
|
||||
# optional, default is 5
|
||||
#anti_flood_delay => 5,
|
||||
|
||||
# twitter account which will appear on twitter cards
|
||||
# see https://dev.twitter.com/docs/cards/validation/validator to register your Lutim instance on twitter
|
||||
# optional, default is @framasky
|
||||
#tweet_card_via => '@framasky',
|
||||
|
||||
# max image size, in octets
|
||||
# you can write it 10*1024*1024
|
||||
# optional, default is 10485760
|
||||
#max_file_size => 10485760,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# if you want to include something in the right of the screen, put it here
|
||||
# here's an example to put the logo of your hoster
|
||||
# optional, no default
|
||||
#hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">',
|
||||
|
||||
# DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
|
||||
# Lutim now checks if the X-Forwarded-Proto header is present and equal to https.
|
||||
# set to 1 if you use Lutim behind a secure web server
|
||||
# optional, default is 0
|
||||
#https => 0,
|
||||
|
||||
# broadcast_message which will displayed on all pages of Lutim (but no in json response)
|
||||
# optional, no default
|
||||
#broadcast_message => 'Maintenance',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
#default_delay => 0,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
#max_delay => 0,
|
||||
|
||||
# if set to 1, all the images will be encrypted and the encryption option will no be displayed
|
||||
# optional, default is 0
|
||||
#always_encrypt => 0,
|
||||
|
||||
# length of the image's delete token
|
||||
# optional, default is 24
|
||||
#token_length => 24,
|
||||
|
||||
# URL sub-directory in which you want Lutim to be accessible
|
||||
# example: you want to have Lutim under https://example.org/lutim/
|
||||
# => set prefix to '/lutim' or to '/lutim/', it doesn't matter
|
||||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite and postgresql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
#dbtype => 'sqlite',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is lutim.db
|
||||
#db_path => 'lutim.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
#pgdb => {
|
||||
# database => 'lutim',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
#},
|
||||
|
||||
# use Minion instead of directly increase counters
|
||||
# need to launch a minion worker service if enabled
|
||||
# optional, Minion is disabled by default
|
||||
#minion => {
|
||||
# enabled => 0,
|
||||
# # Which Minion backend to use?
|
||||
# # valid values are sqlite and postgresql (all lowercase)
|
||||
# # mandatory if Minion is enabled, default is sqlite
|
||||
# dbtype => 'sqlite',
|
||||
# # SQLite ONLY - only used if if you choose sqlite as Minion backend, define the path to the minion database
|
||||
# # you can define it relative to lutim directory or set an absolute path
|
||||
# # remember that it has to be in a directory writable by Lutim user
|
||||
# # optional, default is minion.db
|
||||
# db_path => 'minion.db',
|
||||
# # PostgreSQL ONLY - only used if you choose postgresql as Minion backend
|
||||
# # these are the credentials to access the Minion's PostgreSQL database
|
||||
# # mandatory if you choosed postgresql as Minion backend, no default
|
||||
# pgdb => {
|
||||
# database => 'lutim_minion',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
# }
|
||||
#},
|
||||
|
||||
# define the height of the thumbnails generated at users' will
|
||||
# this is not the height of the thumbnails send after upload,
|
||||
# we're talking about thumbnails generated when someone asked for
|
||||
# https://example.org/lutim/tesrinp?thumb
|
||||
# this works only if you have ImageMagick
|
||||
# optional, default is 100 (pixels)
|
||||
#thumbnail_size => 100,
|
||||
|
||||
# maximum number of files that can be downloaded as a single zip archive
|
||||
# if too many files are asked, it results a timeout, so Lutim split the zip URL
|
||||
# in multiple URLs, each with max_file_size images.
|
||||
# timeout behavior depends heavily on your server ressources (CPU) and if images
|
||||
# are encrypted
|
||||
# optional, default is 15
|
||||
#max_files_in_zip => 15,
|
||||
|
||||
##########################
|
||||
# Lutim cron jobs settings
|
||||
##########################
|
||||
|
||||
# number of days shown in /stats page (used with script/lutim cron stats)
|
||||
# optional, default is 365
|
||||
#stats_day_num => 365,
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lutim cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lutim cron watch to trigger an action
|
||||
# optional, no default
|
||||
#max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lutim cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
|
||||
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
|
||||
# optional, no default
|
||||
#delete_no_longer_viewed_files => 90
|
||||
};
|
||||
|
||||
7
public/css/bootstrap.min.css
vendored
5
public/css/fontello-codes.css
vendored
@@ -1,5 +0,0 @@
|
||||
|
||||
.icon-bitcoin:before { content: '\e802'; } /* '' */
|
||||
.icon-github-circled:before { content: '\e800'; } /* '' */
|
||||
.icon-touiteur:before { content: '\e801'; } /* '' */
|
||||
.icon-flattr:before { content: '\e803'; } /* '' */
|
||||
58
public/css/fontello-embedded.css
vendored
5
public/css/fontello-ie7-codes.css
vendored
@@ -1,5 +0,0 @@
|
||||
|
||||
.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 = ' '); }
|
||||
16
public/css/fontello-ie7.css
vendored
@@ -1,16 +0,0 @@
|
||||
[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 = ' '); }
|
||||
56
public/css/fontello.css
vendored
@@ -1,56 +0,0 @@
|
||||
@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'; } /* '' */
|
||||
@@ -1,15 +0,0 @@
|
||||
<?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>
|
||||
|
Before Width: | Height: | Size: 2.3 KiB |
489
public/js/bootstrap.js
vendored
@@ -1,489 +0,0 @@
|
||||
/* ========================================================================
|
||||
* 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);
|
||||
7
public/js/bootstrap.min.js
vendored
11
script/application
Executable file
@@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
BEGIN { unshift @INC, "$FindBin::Bin/../lib" }
|
||||
|
||||
# Start command line interface for application
|
||||
require Mojolicious::Commands;
|
||||
Mojolicious::Commands->start_app('Lutim');
|
||||
@@ -8,4 +8,4 @@ BEGIN { unshift @INC, "$FindBin::Bin/../lib" }
|
||||
|
||||
# Start command line interface for application
|
||||
require Mojolicious::Commands;
|
||||
Mojolicious::Commands->start_app('Lutim');
|
||||
Mojolicious::Commands->start_app('Mounter');
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
use Mojo::Base -strict;
|
||||
|
||||
use Test::More;
|
||||
use Test::Mojo;
|
||||
|
||||
my $t = Test::Mojo->new('Lutim');
|
||||
$t->get_ok('/')->status_is(200)->content_like(qr/Mojolicious/i);
|
||||
|
||||
done_testing();
|
||||
4
t/create-pg-testdb.sql
Normal file
@@ -0,0 +1,4 @@
|
||||
CREATE USER lutim WITH PASSWORD 'lutim';
|
||||
CREATE DATABASE lutimtest OWNER lutim;
|
||||
CREATE DATABASE lutim_miniontest OWNER lutim;
|
||||
|
||||
202
t/postgresql1.conf
Normal file
@@ -0,0 +1,202 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
{
|
||||
####################
|
||||
# Hypnotoad settings
|
||||
####################
|
||||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
listen => ['http://127.0.0.1:8080'],
|
||||
# if you use Lutim behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lutim directly, let it commented
|
||||
#proxy => 1,
|
||||
},
|
||||
|
||||
################
|
||||
# Lutim settings
|
||||
################
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# mandatory
|
||||
contact => 'John Doe, admin[at]example.com',
|
||||
|
||||
# random string used to encrypt cookies
|
||||
# mandatory
|
||||
secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the images random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# length of the encryption key
|
||||
# optional, default is 8
|
||||
#crypto_key_length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# anti-flood protection delay, in seconds
|
||||
# users won't be able to ask Lutim to download images more than one per anti_flood_delay seconds
|
||||
# optional, default is 5
|
||||
#anti_flood_delay => 5,
|
||||
|
||||
# twitter account which will appear on twitter cards
|
||||
# see https://dev.twitter.com/docs/cards/validation/validator to register your Lutim instance on twitter
|
||||
# optional, default is @framasky
|
||||
#tweet_card_via => '@framasky',
|
||||
|
||||
# max image size, in octets
|
||||
# you can write it 10*1024*1024
|
||||
# optional, default is 10485760
|
||||
max_file_size => 1048576,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# if you want to include something in the right of the screen, put it here
|
||||
# here's an example to put the logo of your hoster
|
||||
# optional, no default
|
||||
#hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">',
|
||||
|
||||
# DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
|
||||
# Lutim now checks if the X-Forwarded-Proto header is present and equal to https.
|
||||
# set to 1 if you use Lutim behind a secure web server
|
||||
# optional, default is 0
|
||||
#https => 0,
|
||||
|
||||
# broadcast_message which will displayed on all pages of Lutim (but no in json response)
|
||||
# optional, no default
|
||||
broadcast_message => 'test broadcast message',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
default_delay => 30,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
max_delay => 200,
|
||||
|
||||
# if set to 1, all the images will be encrypted and the encryption option will no be displayed
|
||||
# optional, default is 0
|
||||
#always_encrypt => 0,
|
||||
|
||||
# length of the image's delete token
|
||||
# optional, default is 24
|
||||
#token_length => 24,
|
||||
|
||||
# URL sub-directory in which you want Lutim to be accessible
|
||||
# example: you want to have Lutim under https://example.org/lutim/
|
||||
# => set prefix to '/lutim' or to '/lutim/', it doesn't matter
|
||||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite and postgresql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
dbtype => 'postgresql',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is lutim.db
|
||||
#db_path => 'lutim.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
pgdb => {
|
||||
database => 'lutimtest',
|
||||
host => 'localhost',
|
||||
user => 'lutim',
|
||||
pwd => 'lutim'
|
||||
},
|
||||
|
||||
# use Minion instead of directly increase counters
|
||||
# need to launch a minion worker service if enabled
|
||||
# optional, Minion is disabled by default
|
||||
#minion => {
|
||||
# enabled => 0,
|
||||
# # Which Minion backend to use?
|
||||
# # valid values are sqlite and postgresql (all lowercase)
|
||||
# # mandatory if Minion is enabled, default is sqlite
|
||||
# dbtype => 'sqlite',
|
||||
# # SQLite ONLY - only used if if you choose sqlite as Minion backend, define the path to the minion database
|
||||
# # you can define it relative to lutim directory or set an absolute path
|
||||
# # remember that it has to be in a directory writable by Lutim user
|
||||
# # optional, default is minion.db
|
||||
# db_path => 'minion.db',
|
||||
# # PostgreSQL ONLY - only used if you choose postgresql as Minion backend
|
||||
# # these are the credentials to access the Minion's PostgreSQL database
|
||||
# # mandatory if you choosed postgresql as Minion backend, no default
|
||||
# pgdb => {
|
||||
# database => 'lutim_minion',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
# }
|
||||
#},
|
||||
|
||||
# define the height of the thumbnails generated at users' will
|
||||
# this is not the height of the thumbnails send after upload,
|
||||
# we're talking about thumbnails generated when someone asked for
|
||||
# https://example.org/lutim/tesrinp?thumb
|
||||
# this works only if you have ImageMagick
|
||||
# optional, default is 100 (pixels)
|
||||
#thumbnail_size => 100,
|
||||
|
||||
# maximum number of files that can be downloaded as a single zip archive
|
||||
# if too many files are asked, it results a timeout, so Lutim split the zip URL
|
||||
# in multiple URLs, each with max_file_size images.
|
||||
# timeout behavior depends heavily on your server ressources (CPU) and if images
|
||||
# are encrypted
|
||||
# optional, default is 15
|
||||
#max_files_in_zip => 15,
|
||||
|
||||
##########################
|
||||
# Lutim cron jobs settings
|
||||
##########################
|
||||
|
||||
# number of days shown in /stats page (used with script/lutim cron stats)
|
||||
# optional, default is 365
|
||||
#stats_day_num => 365,
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lutim cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lutim cron watch to trigger an action
|
||||
# optional, no default
|
||||
max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lutim cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
|
||||
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
|
||||
# optional, no default
|
||||
#delete_no_longer_viewed_files => 90
|
||||
};
|
||||
202
t/postgresql2.conf
Normal file
@@ -0,0 +1,202 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
{
|
||||
####################
|
||||
# Hypnotoad settings
|
||||
####################
|
||||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
listen => ['http://127.0.0.1:8080'],
|
||||
# if you use Lutim behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lutim directly, let it commented
|
||||
#proxy => 1,
|
||||
},
|
||||
|
||||
################
|
||||
# Lutim settings
|
||||
################
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# mandatory
|
||||
contact => 'John Doe, admin[at]example.com',
|
||||
|
||||
# random string used to encrypt cookies
|
||||
# mandatory
|
||||
secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the images random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# length of the encryption key
|
||||
# optional, default is 8
|
||||
#crypto_key_length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# anti-flood protection delay, in seconds
|
||||
# users won't be able to ask Lutim to download images more than one per anti_flood_delay seconds
|
||||
# optional, default is 5
|
||||
#anti_flood_delay => 5,
|
||||
|
||||
# twitter account which will appear on twitter cards
|
||||
# see https://dev.twitter.com/docs/cards/validation/validator to register your Lutim instance on twitter
|
||||
# optional, default is @framasky
|
||||
#tweet_card_via => '@framasky',
|
||||
|
||||
# max image size, in octets
|
||||
# you can write it 10*1024*1024
|
||||
# optional, default is 10485760
|
||||
max_file_size => 1048576,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# if you want to include something in the right of the screen, put it here
|
||||
# here's an example to put the logo of your hoster
|
||||
# optional, no default
|
||||
#hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">',
|
||||
|
||||
# DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
|
||||
# Lutim now checks if the X-Forwarded-Proto header is present and equal to https.
|
||||
# set to 1 if you use Lutim behind a secure web server
|
||||
# optional, default is 0
|
||||
#https => 0,
|
||||
|
||||
# broadcast_message which will displayed on all pages of Lutim (but no in json response)
|
||||
# optional, no default
|
||||
broadcast_message => 'test broadcast message',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
default_delay => 30,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
max_delay => 200,
|
||||
|
||||
# if set to 1, all the images will be encrypted and the encryption option will no be displayed
|
||||
# optional, default is 0
|
||||
#always_encrypt => 0,
|
||||
|
||||
# length of the image's delete token
|
||||
# optional, default is 24
|
||||
#token_length => 24,
|
||||
|
||||
# URL sub-directory in which you want Lutim to be accessible
|
||||
# example: you want to have Lutim under https://example.org/lutim/
|
||||
# => set prefix to '/lutim' or to '/lutim/', it doesn't matter
|
||||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite and postgresql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
dbtype => 'postgresql',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is lutim.db
|
||||
db_path => 'testpg2.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
pgdb => {
|
||||
database => 'lutimtest',
|
||||
host => 'localhost',
|
||||
user => 'lutim',
|
||||
pwd => 'lutim'
|
||||
},
|
||||
|
||||
# use Minion instead of directly increase counters
|
||||
# need to launch a minion worker service if enabled
|
||||
# optional, Minion is disabled by default
|
||||
minion => {
|
||||
enabled => 1,
|
||||
# # Which Minion backend to use?
|
||||
# # valid values are sqlite and postgresql (all lowercase)
|
||||
# # mandatory if Minion is enabled, default is sqlite
|
||||
# dbtype => 'sqlite',
|
||||
# # SQLite ONLY - only used if if you choose sqlite as Minion backend, define the path to the minion database
|
||||
# # you can define it relative to lutim directory or set an absolute path
|
||||
# # remember that it has to be in a directory writable by Lutim user
|
||||
# # optional, default is minion.db
|
||||
# db_path => 'minion.db',
|
||||
# # PostgreSQL ONLY - only used if you choose postgresql as Minion backend
|
||||
# # these are the credentials to access the Minion's PostgreSQL database
|
||||
# # mandatory if you choosed postgresql as Minion backend, no default
|
||||
# pgdb => {
|
||||
# database => 'lutim_minion',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
# }
|
||||
},
|
||||
|
||||
# define the height of the thumbnails generated at users' will
|
||||
# this is not the height of the thumbnails send after upload,
|
||||
# we're talking about thumbnails generated when someone asked for
|
||||
# https://example.org/lutim/tesrinp?thumb
|
||||
# this works only if you have ImageMagick
|
||||
# optional, default is 100 (pixels)
|
||||
#thumbnail_size => 100,
|
||||
|
||||
# maximum number of files that can be downloaded as a single zip archive
|
||||
# if too many files are asked, it results a timeout, so Lutim split the zip URL
|
||||
# in multiple URLs, each with max_file_size images.
|
||||
# timeout behavior depends heavily on your server ressources (CPU) and if images
|
||||
# are encrypted
|
||||
# optional, default is 15
|
||||
#max_files_in_zip => 15,
|
||||
|
||||
##########################
|
||||
# Lutim cron jobs settings
|
||||
##########################
|
||||
|
||||
# number of days shown in /stats page (used with script/lutim cron stats)
|
||||
# optional, default is 365
|
||||
#stats_day_num => 365,
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lutim cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lutim cron watch to trigger an action
|
||||
# optional, no default
|
||||
max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lutim cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
|
||||
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
|
||||
# optional, no default
|
||||
#delete_no_longer_viewed_files => 90
|
||||
};
|
||||
202
t/postgresql3.conf
Normal file
@@ -0,0 +1,202 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
{
|
||||
####################
|
||||
# Hypnotoad settings
|
||||
####################
|
||||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
listen => ['http://127.0.0.1:8080'],
|
||||
# if you use Lutim behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lutim directly, let it commented
|
||||
#proxy => 1,
|
||||
},
|
||||
|
||||
################
|
||||
# Lutim settings
|
||||
################
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# mandatory
|
||||
contact => 'John Doe, admin[at]example.com',
|
||||
|
||||
# random string used to encrypt cookies
|
||||
# mandatory
|
||||
secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the images random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# length of the encryption key
|
||||
# optional, default is 8
|
||||
#crypto_key_length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# anti-flood protection delay, in seconds
|
||||
# users won't be able to ask Lutim to download images more than one per anti_flood_delay seconds
|
||||
# optional, default is 5
|
||||
#anti_flood_delay => 5,
|
||||
|
||||
# twitter account which will appear on twitter cards
|
||||
# see https://dev.twitter.com/docs/cards/validation/validator to register your Lutim instance on twitter
|
||||
# optional, default is @framasky
|
||||
#tweet_card_via => '@framasky',
|
||||
|
||||
# max image size, in octets
|
||||
# you can write it 10*1024*1024
|
||||
# optional, default is 10485760
|
||||
max_file_size => 1048576,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# if you want to include something in the right of the screen, put it here
|
||||
# here's an example to put the logo of your hoster
|
||||
# optional, no default
|
||||
#hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">',
|
||||
|
||||
# DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
|
||||
# Lutim now checks if the X-Forwarded-Proto header is present and equal to https.
|
||||
# set to 1 if you use Lutim behind a secure web server
|
||||
# optional, default is 0
|
||||
#https => 0,
|
||||
|
||||
# broadcast_message which will displayed on all pages of Lutim (but no in json response)
|
||||
# optional, no default
|
||||
broadcast_message => 'test broadcast message',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
default_delay => 30,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
max_delay => 200,
|
||||
|
||||
# if set to 1, all the images will be encrypted and the encryption option will no be displayed
|
||||
# optional, default is 0
|
||||
#always_encrypt => 0,
|
||||
|
||||
# length of the image's delete token
|
||||
# optional, default is 24
|
||||
#token_length => 24,
|
||||
|
||||
# URL sub-directory in which you want Lutim to be accessible
|
||||
# example: you want to have Lutim under https://example.org/lutim/
|
||||
# => set prefix to '/lutim' or to '/lutim/', it doesn't matter
|
||||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite and postgresql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
dbtype => 'postgresql',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is lutim.db
|
||||
db_path => 'testpg3.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
pgdb => {
|
||||
database => 'lutimtest',
|
||||
host => 'localhost',
|
||||
user => 'lutim',
|
||||
pwd => 'lutim'
|
||||
},
|
||||
|
||||
# use Minion instead of directly increase counters
|
||||
# need to launch a minion worker service if enabled
|
||||
# optional, Minion is disabled by default
|
||||
minion => {
|
||||
enabled => 1,
|
||||
# Which Minion backend to use?
|
||||
# valid values are sqlite and postgresql (all lowercase)
|
||||
# mandatory if Minion is enabled, default is sqlite
|
||||
dbtype => 'postgresql',
|
||||
# SQLite ONLY - only used if if you choose sqlite as Minion backend, define the path to the minion database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is minion.db
|
||||
db_path => 'minion.db',
|
||||
# PostgreSQL ONLY - only used if you choose postgresql as Minion backend
|
||||
# these are the credentials to access the Minion's PostgreSQL database
|
||||
# mandatory if you choosed postgresql as Minion backend, no default
|
||||
pgdb => {
|
||||
database => 'lutim_miniontest',
|
||||
host => 'localhost',
|
||||
user => 'lutim',
|
||||
pwd => 'lutim'
|
||||
}
|
||||
},
|
||||
|
||||
# define the height of the thumbnails generated at users' will
|
||||
# this is not the height of the thumbnails send after upload,
|
||||
# we're talking about thumbnails generated when someone asked for
|
||||
# https://example.org/lutim/tesrinp?thumb
|
||||
# this works only if you have ImageMagick
|
||||
# optional, default is 100 (pixels)
|
||||
#thumbnail_size => 100,
|
||||
|
||||
# maximum number of files that can be downloaded as a single zip archive
|
||||
# if too many files are asked, it results a timeout, so Lutim split the zip URL
|
||||
# in multiple URLs, each with max_file_size images.
|
||||
# timeout behavior depends heavily on your server ressources (CPU) and if images
|
||||
# are encrypted
|
||||
# optional, default is 15
|
||||
#max_files_in_zip => 15,
|
||||
|
||||
##########################
|
||||
# Lutim cron jobs settings
|
||||
##########################
|
||||
|
||||
# number of days shown in /stats page (used with script/lutim cron stats)
|
||||
# optional, default is 365
|
||||
#stats_day_num => 365,
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lutim cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lutim cron watch to trigger an action
|
||||
# optional, no default
|
||||
max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lutim cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
|
||||
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
|
||||
# optional, no default
|
||||
#delete_no_longer_viewed_files => 90
|
||||
};
|
||||
202
t/sqlite1.conf
Normal file
@@ -0,0 +1,202 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
{
|
||||
####################
|
||||
# Hypnotoad settings
|
||||
####################
|
||||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
listen => ['http://127.0.0.1:8080'],
|
||||
# if you use Lutim behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lutim directly, let it commented
|
||||
#proxy => 1,
|
||||
},
|
||||
|
||||
################
|
||||
# Lutim settings
|
||||
################
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# mandatory
|
||||
contact => 'John Doe, admin[at]example.com',
|
||||
|
||||
# random string used to encrypt cookies
|
||||
# mandatory
|
||||
secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the images random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# length of the encryption key
|
||||
# optional, default is 8
|
||||
#crypto_key_length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# anti-flood protection delay, in seconds
|
||||
# users won't be able to ask Lutim to download images more than one per anti_flood_delay seconds
|
||||
# optional, default is 5
|
||||
#anti_flood_delay => 5,
|
||||
|
||||
# twitter account which will appear on twitter cards
|
||||
# see https://dev.twitter.com/docs/cards/validation/validator to register your Lutim instance on twitter
|
||||
# optional, default is @framasky
|
||||
#tweet_card_via => '@framasky',
|
||||
|
||||
# max image size, in octets
|
||||
# you can write it 10*1024*1024
|
||||
# optional, default is 10485760
|
||||
max_file_size => 1048576,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# if you want to include something in the right of the screen, put it here
|
||||
# here's an example to put the logo of your hoster
|
||||
# optional, no default
|
||||
#hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">',
|
||||
|
||||
# DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
|
||||
# Lutim now checks if the X-Forwarded-Proto header is present and equal to https.
|
||||
# set to 1 if you use Lutim behind a secure web server
|
||||
# optional, default is 0
|
||||
#https => 0,
|
||||
|
||||
# broadcast_message which will displayed on all pages of Lutim (but no in json response)
|
||||
# optional, no default
|
||||
broadcast_message => 'test broadcast message',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
default_delay => 30,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
max_delay => 200,
|
||||
|
||||
# if set to 1, all the images will be encrypted and the encryption option will no be displayed
|
||||
# optional, default is 0
|
||||
#always_encrypt => 0,
|
||||
|
||||
# length of the image's delete token
|
||||
# optional, default is 24
|
||||
#token_length => 24,
|
||||
|
||||
# URL sub-directory in which you want Lutim to be accessible
|
||||
# example: you want to have Lutim under https://example.org/lutim/
|
||||
# => set prefix to '/lutim' or to '/lutim/', it doesn't matter
|
||||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite and postgresql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
dbtype => 'sqlite',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is lutim.db
|
||||
db_path => 'testdqlite1.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
#pgdb => {
|
||||
# database => 'lutim',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
#},
|
||||
|
||||
# use Minion instead of directly increase counters
|
||||
# need to launch a minion worker service if enabled
|
||||
# optional, Minion is disabled by default
|
||||
#minion => {
|
||||
# enabled => 0,
|
||||
# # Which Minion backend to use?
|
||||
# # valid values are sqlite and postgresql (all lowercase)
|
||||
# # mandatory if Minion is enabled, default is sqlite
|
||||
# dbtype => 'sqlite',
|
||||
# # SQLite ONLY - only used if if you choose sqlite as Minion backend, define the path to the minion database
|
||||
# # you can define it relative to lutim directory or set an absolute path
|
||||
# # remember that it has to be in a directory writable by Lutim user
|
||||
# # optional, default is minion.db
|
||||
# db_path => 'minion.db',
|
||||
# # PostgreSQL ONLY - only used if you choose postgresql as Minion backend
|
||||
# # these are the credentials to access the Minion's PostgreSQL database
|
||||
# # mandatory if you choosed postgresql as Minion backend, no default
|
||||
# pgdb => {
|
||||
# database => 'lutim_minion',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
# }
|
||||
#},
|
||||
|
||||
# define the height of the thumbnails generated at users' will
|
||||
# this is not the height of the thumbnails send after upload,
|
||||
# we're talking about thumbnails generated when someone asked for
|
||||
# https://example.org/lutim/tesrinp?thumb
|
||||
# this works only if you have ImageMagick
|
||||
# optional, default is 100 (pixels)
|
||||
#thumbnail_size => 100,
|
||||
|
||||
# maximum number of files that can be downloaded as a single zip archive
|
||||
# if too many files are asked, it results a timeout, so Lutim split the zip URL
|
||||
# in multiple URLs, each with max_file_size images.
|
||||
# timeout behavior depends heavily on your server ressources (CPU) and if images
|
||||
# are encrypted
|
||||
# optional, default is 15
|
||||
#max_files_in_zip => 15,
|
||||
|
||||
##########################
|
||||
# Lutim cron jobs settings
|
||||
##########################
|
||||
|
||||
# number of days shown in /stats page (used with script/lutim cron stats)
|
||||
# optional, default is 365
|
||||
#stats_day_num => 365,
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lutim cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lutim cron watch to trigger an action
|
||||
# optional, no default
|
||||
max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lutim cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
|
||||
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
|
||||
# optional, no default
|
||||
#delete_no_longer_viewed_files => 90
|
||||
};
|
||||
202
t/sqlite2.conf
Normal file
@@ -0,0 +1,202 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
{
|
||||
####################
|
||||
# Hypnotoad settings
|
||||
####################
|
||||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
listen => ['http://127.0.0.1:8080'],
|
||||
# if you use Lutim behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lutim directly, let it commented
|
||||
#proxy => 1,
|
||||
},
|
||||
|
||||
################
|
||||
# Lutim settings
|
||||
################
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# mandatory
|
||||
contact => 'John Doe, admin[at]example.com',
|
||||
|
||||
# random string used to encrypt cookies
|
||||
# mandatory
|
||||
secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the images random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# length of the encryption key
|
||||
# optional, default is 8
|
||||
#crypto_key_length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# anti-flood protection delay, in seconds
|
||||
# users won't be able to ask Lutim to download images more than one per anti_flood_delay seconds
|
||||
# optional, default is 5
|
||||
#anti_flood_delay => 5,
|
||||
|
||||
# twitter account which will appear on twitter cards
|
||||
# see https://dev.twitter.com/docs/cards/validation/validator to register your Lutim instance on twitter
|
||||
# optional, default is @framasky
|
||||
#tweet_card_via => '@framasky',
|
||||
|
||||
# max image size, in octets
|
||||
# you can write it 10*1024*1024
|
||||
# optional, default is 10485760
|
||||
max_file_size => 1048576,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# if you want to include something in the right of the screen, put it here
|
||||
# here's an example to put the logo of your hoster
|
||||
# optional, no default
|
||||
#hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">',
|
||||
|
||||
# DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
|
||||
# Lutim now checks if the X-Forwarded-Proto header is present and equal to https.
|
||||
# set to 1 if you use Lutim behind a secure web server
|
||||
# optional, default is 0
|
||||
#https => 0,
|
||||
|
||||
# broadcast_message which will displayed on all pages of Lutim (but no in json response)
|
||||
# optional, no default
|
||||
broadcast_message => 'test broadcast message',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
default_delay => 30,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
max_delay => 200,
|
||||
|
||||
# if set to 1, all the images will be encrypted and the encryption option will no be displayed
|
||||
# optional, default is 0
|
||||
#always_encrypt => 0,
|
||||
|
||||
# length of the image's delete token
|
||||
# optional, default is 24
|
||||
#token_length => 24,
|
||||
|
||||
# URL sub-directory in which you want Lutim to be accessible
|
||||
# example: you want to have Lutim under https://example.org/lutim/
|
||||
# => set prefix to '/lutim' or to '/lutim/', it doesn't matter
|
||||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite and postgresql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
dbtype => 'sqlite',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is lutim.db
|
||||
db_path => 'testsqlite2.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
#pgdb => {
|
||||
# database => 'lutim',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
#},
|
||||
|
||||
# use Minion instead of directly increase counters
|
||||
# need to launch a minion worker service if enabled
|
||||
# optional, Minion is disabled by default
|
||||
minion => {
|
||||
enabled => 1,
|
||||
# # Which Minion backend to use?
|
||||
# # valid values are sqlite and postgresql (all lowercase)
|
||||
# # mandatory if Minion is enabled, default is sqlite
|
||||
# dbtype => 'sqlite',
|
||||
# # SQLite ONLY - only used if if you choose sqlite as Minion backend, define the path to the minion database
|
||||
# # you can define it relative to lutim directory or set an absolute path
|
||||
# # remember that it has to be in a directory writable by Lutim user
|
||||
# # optional, default is minion.db
|
||||
# db_path => 'minion.db',
|
||||
# # PostgreSQL ONLY - only used if you choose postgresql as Minion backend
|
||||
# # these are the credentials to access the Minion's PostgreSQL database
|
||||
# # mandatory if you choosed postgresql as Minion backend, no default
|
||||
# pgdb => {
|
||||
# database => 'lutim_minion',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
# }
|
||||
},
|
||||
|
||||
# define the height of the thumbnails generated at users' will
|
||||
# this is not the height of the thumbnails send after upload,
|
||||
# we're talking about thumbnails generated when someone asked for
|
||||
# https://example.org/lutim/tesrinp?thumb
|
||||
# this works only if you have ImageMagick
|
||||
# optional, default is 100 (pixels)
|
||||
#thumbnail_size => 100,
|
||||
|
||||
# maximum number of files that can be downloaded as a single zip archive
|
||||
# if too many files are asked, it results a timeout, so Lutim split the zip URL
|
||||
# in multiple URLs, each with max_file_size images.
|
||||
# timeout behavior depends heavily on your server ressources (CPU) and if images
|
||||
# are encrypted
|
||||
# optional, default is 15
|
||||
#max_files_in_zip => 15,
|
||||
|
||||
##########################
|
||||
# Lutim cron jobs settings
|
||||
##########################
|
||||
|
||||
# number of days shown in /stats page (used with script/lutim cron stats)
|
||||
# optional, default is 365
|
||||
#stats_day_num => 365,
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lutim cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lutim cron watch to trigger an action
|
||||
# optional, no default
|
||||
max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lutim cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
|
||||
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
|
||||
# optional, no default
|
||||
#delete_no_longer_viewed_files => 90
|
||||
};
|
||||
202
t/sqlite3.conf
Normal file
@@ -0,0 +1,202 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
{
|
||||
####################
|
||||
# Hypnotoad settings
|
||||
####################
|
||||
# see http://mojolicio.us/perldoc/Mojo/Server/Hypnotoad for a full list of settings
|
||||
hypnotoad => {
|
||||
# array of IP addresses and ports you want to listen to
|
||||
listen => ['http://127.0.0.1:8080'],
|
||||
# if you use Lutim behind a reverse proxy like Nginx, you want to set proxy to 1
|
||||
# if you use Lutim directly, let it commented
|
||||
#proxy => 1,
|
||||
},
|
||||
|
||||
################
|
||||
# Lutim settings
|
||||
################
|
||||
|
||||
# put a way to contact you here and uncomment it
|
||||
# mandatory
|
||||
contact => 'John Doe, admin[at]example.com',
|
||||
|
||||
# random string used to encrypt cookies
|
||||
# mandatory
|
||||
secrets => ['fdjsofjoihrei'],
|
||||
|
||||
# choose a theme. See the available themes in `themes` directory
|
||||
# optional, default is 'default'
|
||||
#theme => 'default',
|
||||
|
||||
# length of the images random URL
|
||||
# optional, default is 8
|
||||
#length => 8,
|
||||
|
||||
# length of the encryption key
|
||||
# optional, default is 8
|
||||
#crypto_key_length => 8,
|
||||
|
||||
# how many URLs will be provisioned in a batch ?
|
||||
# optional, default is 5
|
||||
#provis_step => 5,
|
||||
|
||||
# max number of URLs to be provisioned
|
||||
# optional, default is 100
|
||||
#provisioning => 100,
|
||||
|
||||
# anti-flood protection delay, in seconds
|
||||
# users won't be able to ask Lutim to download images more than one per anti_flood_delay seconds
|
||||
# optional, default is 5
|
||||
#anti_flood_delay => 5,
|
||||
|
||||
# twitter account which will appear on twitter cards
|
||||
# see https://dev.twitter.com/docs/cards/validation/validator to register your Lutim instance on twitter
|
||||
# optional, default is @framasky
|
||||
#tweet_card_via => '@framasky',
|
||||
|
||||
# max image size, in octets
|
||||
# you can write it 10*1024*1024
|
||||
# optional, default is 10485760
|
||||
max_file_size => 1048576,
|
||||
|
||||
# if you want to have piwik statistics, provide a piwik image tracker
|
||||
# only the image tracker is allowed, no javascript
|
||||
# optional, no default
|
||||
#piwik_img => 'https://piwik.example.org/piwik.php?idsite=1&rec=1',
|
||||
|
||||
# if you want to include something in the right of the screen, put it here
|
||||
# here's an example to put the logo of your hoster
|
||||
# optional, no default
|
||||
#hosted_by => 'My super hoster <img src="http://hoster.example.com" alt="Hoster logo">',
|
||||
|
||||
# DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED DEPRECATED
|
||||
# Lutim now checks if the X-Forwarded-Proto header is present and equal to https.
|
||||
# set to 1 if you use Lutim behind a secure web server
|
||||
# optional, default is 0
|
||||
#https => 0,
|
||||
|
||||
# broadcast_message which will displayed on all pages of Lutim (but no in json response)
|
||||
# optional, no default
|
||||
broadcast_message => 'test broadcast message',
|
||||
|
||||
# array of authorized domains for API calls.
|
||||
# if you want to authorize everyone to use the API: ['*']
|
||||
# optional, no domains allowed by default
|
||||
#allowed_domains => ['http://1.example.com', 'http://2.example.com'],
|
||||
|
||||
# default time limit for files
|
||||
# valid values are 0, 1, 7, 30 and 365
|
||||
# optional, default is 0 (no limit)
|
||||
default_delay => 30,
|
||||
|
||||
# number of days after which the images will be deleted, even if they were uploaded with "no delay" (or value superior to max_delay)
|
||||
# a warning message will be displayed on homepage
|
||||
# optional, default is 0 (no limit)
|
||||
max_delay => 200,
|
||||
|
||||
# if set to 1, all the images will be encrypted and the encryption option will no be displayed
|
||||
# optional, default is 0
|
||||
#always_encrypt => 0,
|
||||
|
||||
# length of the image's delete token
|
||||
# optional, default is 24
|
||||
#token_length => 24,
|
||||
|
||||
# URL sub-directory in which you want Lutim to be accessible
|
||||
# example: you want to have Lutim under https://example.org/lutim/
|
||||
# => set prefix to '/lutim' or to '/lutim/', it doesn't matter
|
||||
# optional, defaut is /
|
||||
#prefix => '/',
|
||||
|
||||
# choose what database you want to use
|
||||
# valid choices are sqlite and postgresql (all lowercase)
|
||||
# optional, default is sqlite
|
||||
dbtype => 'sqlite',
|
||||
|
||||
# SQLite ONLY - only used if dbtype is set to sqlite
|
||||
# define a path to the SQLite database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is lutim.db
|
||||
db_path => 'testsqlite3.db',
|
||||
|
||||
# PostgreSQL ONLY - only used if dbtype is set to postgresql
|
||||
# these are the credentials to access the PostgreSQL database
|
||||
# mandatory if you choosed postgresql as dbtype
|
||||
#pgdb => {
|
||||
# database => 'lutim',
|
||||
# host => 'localhost',
|
||||
# #user => 'DBUSER',
|
||||
# #pwd => 'DBPASSWORD'
|
||||
#},
|
||||
|
||||
# use Minion instead of directly increase counters
|
||||
# need to launch a minion worker service if enabled
|
||||
# optional, Minion is disabled by default
|
||||
minion => {
|
||||
enabled => 1,
|
||||
# Which Minion backend to use?
|
||||
# valid values are sqlite and postgresql (all lowercase)
|
||||
# mandatory if Minion is enabled, default is sqlite
|
||||
dbtype => 'postgresql',
|
||||
# SQLite ONLY - only used if if you choose sqlite as Minion backend, define the path to the minion database
|
||||
# you can define it relative to lutim directory or set an absolute path
|
||||
# remember that it has to be in a directory writable by Lutim user
|
||||
# optional, default is minion.db
|
||||
db_path => 'minion.db',
|
||||
# PostgreSQL ONLY - only used if you choose postgresql as Minion backend
|
||||
# these are the credentials to access the Minion's PostgreSQL database
|
||||
# mandatory if you choosed postgresql as Minion backend, no default
|
||||
pgdb => {
|
||||
database => 'lutim_miniontest',
|
||||
host => 'localhost',
|
||||
user => 'lutim',
|
||||
pwd => 'lutim'
|
||||
}
|
||||
},
|
||||
|
||||
# define the height of the thumbnails generated at users' will
|
||||
# this is not the height of the thumbnails send after upload,
|
||||
# we're talking about thumbnails generated when someone asked for
|
||||
# https://example.org/lutim/tesrinp?thumb
|
||||
# this works only if you have ImageMagick
|
||||
# optional, default is 100 (pixels)
|
||||
#thumbnail_size => 100,
|
||||
|
||||
# maximum number of files that can be downloaded as a single zip archive
|
||||
# if too many files are asked, it results a timeout, so Lutim split the zip URL
|
||||
# in multiple URLs, each with max_file_size images.
|
||||
# timeout behavior depends heavily on your server ressources (CPU) and if images
|
||||
# are encrypted
|
||||
# optional, default is 15
|
||||
#max_files_in_zip => 15,
|
||||
|
||||
##########################
|
||||
# Lutim cron jobs settings
|
||||
##########################
|
||||
|
||||
# number of days shown in /stats page (used with script/lutim cron stats)
|
||||
# optional, default is 365
|
||||
#stats_day_num => 365,
|
||||
|
||||
# number of days senders' IP addresses are kept in database
|
||||
# after that delay, they will be deleted from database (used with script/lutim cron cleanbdd)
|
||||
# optional, default is 365
|
||||
#keep_ip_during => 365,
|
||||
|
||||
# max size of the files directory, in octets
|
||||
# used by script/lutim cron watch to trigger an action
|
||||
# optional, no default
|
||||
max_total_size => 10*1024*1024*1024,
|
||||
|
||||
# default action when files directory is over max_total_size (used with script/lutim cron watch)
|
||||
# valid values are 'warn', 'stop-upload' and 'delete'
|
||||
# please, see readme
|
||||
# optional, default is 'warn'
|
||||
#policy_when_full => 'warn',
|
||||
|
||||
# images which are not viewed since delete_no_longer_viewed_files days will be deleted by the cron cleanfiles task
|
||||
# if delete_no_longer_viewed_files is not set, the no longer viewed files will NOT be deleted
|
||||
# optional, no default
|
||||
#delete_no_longer_viewed_files => 90
|
||||
};
|
||||
108
t/test.t
Normal file
@@ -0,0 +1,108 @@
|
||||
# vim:set sw=4 ts=4 sts=4 ft=perl expandtab:
|
||||
use Mojo::Base -strict;
|
||||
use Mojo::File;
|
||||
use Mojo::JSON qw(true false);
|
||||
use Mojolicious;
|
||||
|
||||
use Test::More;
|
||||
use Test::Mojo;
|
||||
|
||||
use FindBin qw($Bin);
|
||||
use Digest::file qw(digest_file_hex);
|
||||
|
||||
my ($m, $cfile);
|
||||
|
||||
BEGIN {
|
||||
use lib 'lib';
|
||||
$m = Mojolicious->new;
|
||||
$cfile = Mojo::File->new($Bin, '..' , 'lutim.conf');
|
||||
if (defined $ENV{MOJO_CONFIG}) {
|
||||
$cfile = Mojo::File->new($ENV{MOJO_CONFIG});
|
||||
unless (-e $cfile->to_abs) {
|
||||
$cfile = Mojo::File->new($Bin, '..', $ENV{MOJO_CONFIG});
|
||||
}
|
||||
}
|
||||
my $config = $m->plugin('Config' =>
|
||||
{
|
||||
file => $cfile->to_abs->to_string,
|
||||
default => {
|
||||
dbtype => 'sqlite'
|
||||
}
|
||||
}
|
||||
);
|
||||
$m->plugin('Lutim::Plugin::Helpers');
|
||||
$m->plugin('DebugDumperHelper');
|
||||
}
|
||||
|
||||
# Home page
|
||||
my $t = Test::Mojo->new('Lutim');
|
||||
$t->get_ok('/')
|
||||
->status_is(200)
|
||||
->content_like(qr/Let's Upload That IMage/i);
|
||||
|
||||
# Instance settings informations
|
||||
$t->get_ok('/infos')
|
||||
->status_is(200)
|
||||
->json_has('image_magick')
|
||||
->json_is(
|
||||
'/always_encrypt' => false,
|
||||
'/broadcast_message' => 'test broadcast message',
|
||||
'/contact' => 'John Doe, admin[at]example.com',
|
||||
'/default_delay' => 30,
|
||||
'/max_delay' => 200,
|
||||
'/max_file_size' => 1048576
|
||||
);
|
||||
|
||||
# Post image
|
||||
my $image = Mojo::File->new($Bin, '..', 'themes', 'default', 'public', 'img', 'Lutim.png')->to_string;
|
||||
$t->post_ok('/' => form => { file => { file => $image }, format => 'json' })
|
||||
->status_is(200)
|
||||
->json_has('msg', 'success')
|
||||
->json_is('/success' => true, '/msg/filename' => 'Lutim.png')
|
||||
->json_like('/msg/short' => qr#[-_a-zA-Z0-9]{8}#, '/msg/real_short' => qr#[-_a-zA-Z0-9]{8}#, '/msg/token' => qr#[-_a-zA-Z0-9]{24}#);
|
||||
|
||||
# Post delete-at-first-view image
|
||||
my $raw = $t->ua->post('/' => form => { file => { file => $image }, 'first-view' => 1, format => 'json' })->res;
|
||||
my $short = $raw->json('/msg/short');
|
||||
|
||||
$t->get_ok('/'.$short)
|
||||
->status_is(200);
|
||||
|
||||
$t->get_ok('/'.$short)
|
||||
->status_is(302);
|
||||
|
||||
# Delete image with token
|
||||
$raw = $t->ua->post('/' => form => { file => { file => $image }, format => 'json' })->res;
|
||||
my $rshort = $raw->json('/msg/real_short');
|
||||
my $token = $raw->json('/msg/token');
|
||||
|
||||
$t->get_ok('/'.$rshort)
|
||||
->status_is(200);
|
||||
|
||||
$t->get_ok('/d/'.$rshort.'/'.$token, form => { format => 'json' })
|
||||
->status_is('200')
|
||||
->json_is(
|
||||
{
|
||||
success => true,
|
||||
msg => 'The image Lutim.png has been successfully deleted'
|
||||
}
|
||||
);
|
||||
|
||||
$t->get_ok('/'.$rshort)
|
||||
->status_is(302);
|
||||
|
||||
# Needed if we use Minion with sqlite for increasing counters
|
||||
sleep 8;
|
||||
|
||||
# Get image counter
|
||||
$t->post_ok('/c', form => { short => $rshort, token => $token })
|
||||
->status_is(200)
|
||||
->json_is(
|
||||
{
|
||||
success => true,
|
||||
counter => 1,
|
||||
enabled => false
|
||||
}
|
||||
);
|
||||
|
||||
done_testing();
|
||||
@@ -1,121 +0,0 @@
|
||||
% # 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>
|
||||
<li><%=l 'twitter-link' %> <%= link_to url_for('/')->to_abs.flash('short').'?t' => begin %><%= url_for('/')->to_abs.flash('short').'?t' %><%= 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><%=l 'view-link'%>'
|
||||
+link(msg.short, '')
|
||||
+'</a></li><li><%=l 'download-link' %>'
|
||||
+link(msg.short, 'dl')
|
||||
+'</a></li><li><%=l 'twitter-link' %>'
|
||||
+link(msg.short, 't')
|
||||
+'</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>';
|
||||
}
|
||||
}
|
||||
function bindddz(firstview, deleteday) {
|
||||
$('#drag-and-drop-zone').dmUploader({
|
||||
url: '<%== url_for('add') %>',
|
||||
dataType: 'json',
|
||||
allowedTypes: 'image/*',
|
||||
onUploadSuccess: function(id, data){
|
||||
$(".messages").append(message(data.success, data.msg));
|
||||
},
|
||||
onUploadError: function(id, message){
|
||||
$(".messages").append(message(false, ''));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$('document').ready(function() {
|
||||
$('.jsonly').show();
|
||||
|
||||
var firstview = ($("#first-view").prop('checked')) ? 1 : 0;
|
||||
var deleteday = ($("#delete-day").prop('checked')) ? 1 : 0;
|
||||
|
||||
bindddz(firstview, deleteday);
|
||||
});
|
||||
% end
|
||||
@@ -1,88 +0,0 @@
|
||||
% # 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! ';
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<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'
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div>
|
||||
% if (defined(config('hosted_by'))) {
|
||||
<div class="pull-right">
|
||||
<%== config('hosted_by') %>
|
||||
</div>
|
||||
% }
|
||||
<div>
|
||||
<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>
|
||||
</div>
|
||||
</div>
|
||||
<%= 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>
|
||||
@@ -1,19 +0,0 @@
|
||||
% # vim:set sw=4 ts=4 sts=4 ft=html.epl expandtab:
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>LUTIm</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="twitter:card" content="photo">
|
||||
% if (defined(config('tweet_card_via'))) {
|
||||
<meta name="twitter:site" content="<%= config('tweet_card_via') %>">
|
||||
% }
|
||||
<meta name="twitter:image:src" content="<%= url_for('/')->to_abs().$short %>">
|
||||
</head>
|
||||
<body>
|
||||
<img src="<%= url_for('/').$short %>" alt="<%= $filename %>">
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
12
themes/default/lib/Lutim/I18N.pm
Normal file
@@ -0,0 +1,12 @@
|
||||
package Lutim::I18N;
|
||||
|
||||
use base 'Locale::Maketext';
|
||||
use File::Basename qw/dirname/;
|
||||
use Locale::Maketext::Lexicon {
|
||||
_auto => 1,
|
||||
_decode => 1,
|
||||
_style => 'gettext',
|
||||
'*' => [Gettext => dirname(__FILE__) . '/I18N/*.po']
|
||||
};
|
||||
|
||||
1;
|
||||
489
themes/default/lib/Lutim/I18N/de.po
Normal file
@@ -0,0 +1,489 @@
|
||||
# Lutim language file
|
||||
# Copyright (C) 2014 Luc Didry
|
||||
# This file is distributed under the same license as the Lutim package.
|
||||
#
|
||||
# Translators:
|
||||
# Translators:
|
||||
# Thor77 <thor77@thor77.org>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Lutim\n"
|
||||
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"PO-Revision-Date: 2015-09-18 13:34+0000\n"
|
||||
"Last-Translator: Thor77 <thor77@thor77.org>\n"
|
||||
"Language-Team: German (http://www.transifex.com/fiat-tux/lutim/language/de/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: de\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. (7)
|
||||
#. (30)
|
||||
#. ($delay)
|
||||
#. (config('max_delay')
|
||||
#: lib/Lutim/Command/cron/stats.pm:149 lib/Lutim/Command/cron/stats.pm:150 lib/Lutim/Command/cron/stats.pm:160 lib/Lutim/Command/cron/stats.pm:161 lib/Lutim/Command/cron/stats.pm:177 lib/Lutim/Command/cron/stats.pm:178 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/for_my_delay.html.ep:3 themes/default/templates/partial/lutim.js.ep:138 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/partial/lutim.js.ep:148 themes/default/templates/raw.html.ep:19 themes/default/templates/raw.html.ep:20 themes/default/templates/raw.html.ep:36 themes/default/templates/raw.html.ep:37 themes/default/templates/raw.html.ep:8 themes/default/templates/raw.html.ep:9
|
||||
msgid "%1 days"
|
||||
msgstr "%1 Tage"
|
||||
|
||||
#. ($total)
|
||||
#: themes/default/templates/stats.html.ep:2
|
||||
msgid "%1 sent images on this instance from beginning."
|
||||
msgstr "%1 Bilder wurden bisher über diese Instanz versendet."
|
||||
|
||||
#: themes/default/templates/index.html.ep:190
|
||||
msgid "-or-"
|
||||
msgstr "-oder-"
|
||||
|
||||
#: lib/Lutim.pm:192 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:5 themes/default/templates/raw.html.ep:10 themes/default/templates/raw.html.ep:21 themes/default/templates/raw.html.ep:38
|
||||
msgid "1 year"
|
||||
msgstr "1 Jahr"
|
||||
|
||||
#: lib/Lutim.pm:191 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:159 lib/Lutim/Command/cron/stats.pm:176 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/raw.html.ep:18 themes/default/templates/raw.html.ep:35 themes/default/templates/raw.html.ep:7
|
||||
msgid "24 hours"
|
||||
msgstr "24 Stunden"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:57
|
||||
msgid ": Error while trying to get the counter."
|
||||
msgstr ":Fehler beim Abrufen des Zählers."
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:144 themes/default/templates/raw.html.ep:3
|
||||
msgid "Active images"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:288
|
||||
msgid "An error occured while downloading the image."
|
||||
msgstr "Beim Herunterladen des Bildes ist ein Fehler aufgetreten."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:2
|
||||
msgid "Archives download"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:41 themes/default/templates/myfiles.html.ep:64 themes/default/templates/stats.html.ep:25
|
||||
msgid "Back to homepage"
|
||||
msgstr "Zurück zur Hauptseite"
|
||||
|
||||
#: themes/default/templates/index.html.ep:193 themes/default/templates/index.html.ep:194
|
||||
msgid "Click to open the file browser"
|
||||
msgstr "Klicken um den Dateibrowser zu öffnen"
|
||||
|
||||
#: themes/default/templates/about.html.ep:30
|
||||
msgid "Contributors"
|
||||
msgstr "Mitwirkende"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:214 themes/default/templates/partial/lutim.js.ep:268 themes/default/templates/partial/lutim.js.ep:346
|
||||
msgid "Copy all view links to clipboard"
|
||||
msgstr "Alle Links zum Anschauen in die Zwischenablage kopieren"
|
||||
|
||||
#: themes/default/templates/index.html.ep:18 themes/default/templates/index.html.ep:36 themes/default/templates/index.html.ep:69 themes/default/templates/index.html.ep:77 themes/default/templates/index.html.ep:85 themes/default/templates/index.html.ep:93 themes/default/templates/myfiles.html.ep:20 themes/default/templates/myfiles.html.ep:38 themes/default/templates/partial/common.js.ep:150 themes/default/templates/partial/lutim.js.ep:105 themes/default/templates/partial/lutim.js.ep:120 themes/default/templates/partial/lutim.js.ep:79 themes/default/templates/partial/lutim.js.ep:91
|
||||
msgid "Copy to clipboard"
|
||||
msgstr "In die Zwischenablage kopieren"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:52
|
||||
msgid "Counter"
|
||||
msgstr "Zähler"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:18
|
||||
msgid "Delay repartition chart for disabled images"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/stats.html.ep:15
|
||||
msgid "Delay repartition chart for enabled images"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:115 themes/default/templates/index.html.ep:147 themes/default/templates/index.html.ep:178 themes/default/templates/myfiles.html.ep:53 themes/default/templates/partial/lutim.js.ep:159
|
||||
msgid "Delete at first view?"
|
||||
msgstr "Nach erstem Aufruf löschen?"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:145 themes/default/templates/raw.html.ep:4
|
||||
msgid "Deleted images"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:146 themes/default/templates/raw.html.ep:5
|
||||
msgid "Deleted images in 30 days"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:98 themes/default/templates/myfiles.html.ep:56 themes/default/templates/partial/common.js.ep:142 themes/default/templates/partial/common.js.ep:145
|
||||
msgid "Deletion link"
|
||||
msgstr "Link zum Löschen"
|
||||
|
||||
#: themes/default/templates/gallery.html.ep:6
|
||||
msgid "Download all images"
|
||||
msgstr "Laden Sie alle Bilder"
|
||||
|
||||
#: themes/default/templates/index.html.ep:81 themes/default/templates/index.html.ep:83 themes/default/templates/partial/lutim.js.ep:101 themes/default/templates/partial/lutim.js.ep:97
|
||||
msgid "Download link"
|
||||
msgstr "Link zum Herunterladen"
|
||||
|
||||
#: themes/default/templates/index.html.ep:28 themes/default/templates/index.html.ep:31 themes/default/templates/myfiles.html.ep:30 themes/default/templates/myfiles.html.ep:33
|
||||
msgid "Download zip link"
|
||||
msgstr "Link zum Archivbilder"
|
||||
|
||||
#: themes/default/templates/index.html.ep:189
|
||||
msgid "Drag & drop images here"
|
||||
msgstr "Bilder hierher ziehen"
|
||||
|
||||
#: themes/default/templates/about.html.ep:7
|
||||
msgid "Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you four URLs. One to view the image, an other to directly download it, one you can use on social networks and a last to delete the image when you want."
|
||||
msgstr "Ziehe Bilder in den dafür vorgesehenen Bereich und Lutim wird vier URLs generieren. Eine zum Anschauen, eine zum direkten Herunterladen, eine zum Nutzen in sozialen Netzwerken und eine letzte um das Bild zu löschen."
|
||||
|
||||
#: themes/default/templates/index.html.ep:150 themes/default/templates/index.html.ep:181
|
||||
msgid "Encrypt the image (Lutim does not keep the key)."
|
||||
msgstr "Verschlüssle das Bild (Lutim behält den Key nicht)"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:44
|
||||
msgid "Error while trying to modify the image."
|
||||
msgstr "Beim bearbeiten des Bildes ist ein Fehler aufgetreten."
|
||||
|
||||
#: themes/default/templates/stats.html.ep:10
|
||||
msgid "Evolution of total files"
|
||||
msgstr "Entwicklung der Anzahl an Dateien"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:55
|
||||
msgid "Expires at"
|
||||
msgstr "Läuft ab am"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:50
|
||||
msgid "File name"
|
||||
msgstr "Dateiname"
|
||||
|
||||
#: themes/default/templates/about.html.ep:24
|
||||
msgid "For more details, see the <a href=\"https://framagit.org/luc/lutim\">homepage of the project</a>."
|
||||
msgstr "Besuche für mehr Details die <a href=\"https://framagit.org/luc/lutim\">Homepage des Projekts</a>."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:55
|
||||
msgid "Fork me!"
|
||||
msgstr "Fork me!"
|
||||
|
||||
#: themes/default/templates/index.html.ep:10 themes/default/templates/index.html.ep:13 themes/default/templates/myfiles.html.ep:12 themes/default/templates/myfiles.html.ep:15
|
||||
msgid "Gallery link"
|
||||
msgstr "Link zur Galerie"
|
||||
|
||||
#: themes/default/templates/partial/common.js.ep:104 themes/default/templates/partial/common.js.ep:87
|
||||
msgid "Hit Ctrl+C, then Enter to copy the short link"
|
||||
msgstr "Drücke STRG+C und dann Enter um den Kurz-Link zu kopieren."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:50
|
||||
msgid "Homepage"
|
||||
msgstr "Webseite"
|
||||
|
||||
#: themes/default/templates/about.html.ep:20
|
||||
msgid "How do you pronounce Lutim?"
|
||||
msgstr "Wie spricht man Lutim aus?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:6
|
||||
msgid "How does it work?"
|
||||
msgstr "Wie funktionert das?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:18
|
||||
msgid "How to report an image?"
|
||||
msgstr "Wie kann ich ein Bild melden?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:14
|
||||
msgid "If the files are deleted if you ask it while posting it, their SHA512 footprint are retained."
|
||||
msgstr "Wenn du versuchst, ein Bild während dem Hochladen zu löschen, wird die SHA512-Summe des Bildes behalten."
|
||||
|
||||
#: themes/default/templates/index.html.ep:163 themes/default/templates/index.html.ep:203
|
||||
msgid "Image URL"
|
||||
msgstr "Bild-URL"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:143 themes/default/templates/raw.html.ep:2
|
||||
msgid "Image delay"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:710
|
||||
msgid "Image not found."
|
||||
msgstr "Bild nicht gefunden"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:54
|
||||
msgid "Informations"
|
||||
msgstr "Informationen"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:62
|
||||
msgid "Install webapp"
|
||||
msgstr "Installiere die Webapp"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:61
|
||||
msgid "Instance's statistics"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:11
|
||||
msgid "Is it really anonymous?"
|
||||
msgstr "Ist es wirklich anonym?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:9
|
||||
msgid "Is it really free (as in free beer)?"
|
||||
msgstr "Is es wirklich kostenlos?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:21
|
||||
msgid "Juste like you pronounce the French word <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
msgstr "Genauso wie das französische Wort <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:153 themes/default/templates/index.html.ep:184
|
||||
msgid "Keep EXIF tags"
|
||||
msgstr "Behalte EXIF-Daten"
|
||||
|
||||
#: themes/default/templates/index.html.ep:118 themes/default/templates/index.html.ep:166 themes/default/templates/index.html.ep:206 themes/default/templates/partial/lutim.js.ep:163
|
||||
msgid "Let's go!"
|
||||
msgstr "Los gehts!"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Liberapay button"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:53
|
||||
msgid "License:"
|
||||
msgstr "Lizenz:"
|
||||
|
||||
#: themes/default/templates/index.html.ep:89 themes/default/templates/index.html.ep:91 themes/default/templates/partial/lutim.js.ep:111 themes/default/templates/partial/lutim.js.ep:115
|
||||
msgid "Link for share on social networks"
|
||||
msgstr "Links zum teilen auf sozialen Netzwerken"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:7
|
||||
msgid "Lutim can't zip so many images at once, so it splitted your demand in multiple URLs."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:4
|
||||
msgid "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."
|
||||
msgstr ""
|
||||
"Lutim ist ein freier und anonymer Bilder-Upload-Service.\n"
|
||||
"Es ist auch der Name der freien Software, die diesen Service bietet."
|
||||
|
||||
#: themes/default/templates/about.html.ep:25
|
||||
msgid "Main developers"
|
||||
msgstr "Haupt-Entwickler"
|
||||
|
||||
#: themes/default/templates/index.html.ep:73 themes/default/templates/index.html.ep:75 themes/default/templates/partial/lutim.js.ep:85 themes/default/templates/partial/lutim.js.ep:88
|
||||
msgid "Markdown syntax"
|
||||
msgstr "Markdown Syntax"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:60 themes/default/templates/myfiles.html.ep:2
|
||||
msgid "My images"
|
||||
msgstr "Meine Bilder"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:19
|
||||
msgid "No limit"
|
||||
msgstr "Keine Begrenzung"
|
||||
|
||||
#: themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:198
|
||||
msgid "Only images are allowed"
|
||||
msgstr "Es sind nur Bilder erlaubt"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:6
|
||||
msgid "Only the images sent with this browser will be listed here. The informations are stored in localStorage: if you delete your localStorage data, you'll loose this informations."
|
||||
msgstr "Nur die Bilder, die über diesen Browser versendet wurden, werden hier angezeigt. Die Informationen werden im localStorage gespeichert, wenn du diesen leerst, sind die Informationen verloren."
|
||||
|
||||
#: themes/default/templates/about.html.ep:16
|
||||
msgid "Only the uploader! (well, only if he's the only owner of the images' rights before the upload)"
|
||||
msgstr "Nur der Hochladende (natürlich nur, wenn er vorher auch Rechteinhaber des Bildes war)"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:12
|
||||
msgid "Please click on each URL to download the different zip files."
|
||||
msgstr ""
|
||||
|
||||
#. (config('contact')
|
||||
#: themes/default/templates/about.html.ep:19
|
||||
msgid "Please contact the administrator: %1"
|
||||
msgstr "Kontaktiere den Administrator: %1"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:22
|
||||
msgid "Raw stats"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:158
|
||||
msgid "Send an image"
|
||||
msgstr "Sende ein Bild"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:20
|
||||
msgid "Share it!"
|
||||
msgstr "Teile es!"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:56
|
||||
msgid "Share on Twitter"
|
||||
msgstr "Teile es auf Twitter"
|
||||
|
||||
#: themes/default/templates/index.html.ep:133 themes/default/templates/partial/lutim.js.ep:174
|
||||
msgid "Something bad happened"
|
||||
msgstr "Es ist ein Fehler aufgetreten"
|
||||
|
||||
#. ($c->config('contact')
|
||||
#: lib/Lutim/Controller.pm:717
|
||||
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
|
||||
msgstr "Es ist ein Fehler aufgetreten. Versuche es erneut oder kontaktiere den Administrator (%1)."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Support the author on Liberapay"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Support the author on Tipeee"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:13
|
||||
msgid "The IP address of the image's sender is retained for a delay which depends of the administrator's choice (for the official instance, which is located in France, it's one year)."
|
||||
msgstr "Die IP-Adresse des Nutzers wird für eine bestimmte Zeit gespeichert. Diese kann der Administrator frei wählen (für die offizielle Instanz, die in Frankreich gehostet ist, liegt diese Zeit bei einem Jahr)"
|
||||
|
||||
#: themes/default/templates/about.html.ep:23
|
||||
msgid "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."
|
||||
msgstr "Lutim ist <a href=\"https://de.wikipedia.org/wiki/Freie_Software\">freie Software</a>, was dir erlaubt sie herunterzuladen und sie auf deinem eigenem Server zu installieren. Schau dir die <a href=\"https://www.gnu.org/licenses/agpl-3.0.html\">AGPL</a> an um deine Recht zu sehen."
|
||||
|
||||
#: lib/Lutim/Controller.pm:307
|
||||
msgid "The URL is not valid."
|
||||
msgstr "Die URL ist nicht gültig."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:16
|
||||
msgid "The automatic download process will open a tab in your browser for each link. You need to allow popups for Lutim."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:120 lib/Lutim/Controller.pm:188
|
||||
msgid "The delete token is invalid."
|
||||
msgstr "Das Token zum Löschen ist ungültig."
|
||||
|
||||
#. ($upload->filename)
|
||||
#: lib/Lutim/Controller.pm:445
|
||||
msgid "The file %1 is not an image."
|
||||
msgstr "Die Datei %1 ist kein Bild."
|
||||
|
||||
#. ($tx->res->max_message_size)
|
||||
#. ($c->req->max_message_size)
|
||||
#. (config('max_file_size')
|
||||
#: lib/Lutim/Controller.pm:271 lib/Lutim/Controller.pm:340 themes/default/templates/partial/lutim.js.ep:240
|
||||
msgid "The file exceed the size limit (%1)"
|
||||
msgstr "Die Datei überschreitet die Größenbeschränkung (%1)"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:12
|
||||
msgid "The graph's datas are not updated in real-time."
|
||||
msgstr "Die Daten des Graphs werden nicht in Echtzeit aktualisiert."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:190
|
||||
msgid "The image %1 has already been deleted."
|
||||
msgstr "Das Bild %1 wurde schon gelöscht."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:199 lib/Lutim/Controller.pm:204
|
||||
msgid "The image %1 has been successfully deleted"
|
||||
msgstr "Das Bild %1 wurde erfolgreich gelöscht."
|
||||
|
||||
#: lib/Lutim/Controller.pm:128
|
||||
msgid "The image's delay has been successfully modified"
|
||||
msgstr "Die Zeit bis zum Löschen des Bildes wurde erfolgreich geändert."
|
||||
|
||||
#: themes/default/templates/index.html.ep:45
|
||||
msgid "The images are encrypted on the server (Lutim does not keep the key)."
|
||||
msgstr "Die Bilder werden auf dem Server verschlüsselt (Lutim behält den Key nicht)"
|
||||
|
||||
#: themes/default/templates/about.html.ep:5
|
||||
msgid "The images you post on Lutim can be stored indefinitely or be deleted at first view or after a delay selected from those proposed."
|
||||
msgstr "Die Bilder, die du auf Lutim hochlädst, können entweder nie, nach dem ersten Aufruf oder nach einer bestimmten Zeit gelöscht werden."
|
||||
|
||||
#. ($c->config->{contact})
|
||||
#: lib/Lutim/Controller.pm:442
|
||||
msgid "There is no more available URL. Retry or contact the administrator. %1"
|
||||
msgstr "Es sind keine URLs mehr verfügbar. Versuche es erneut oder kontaktiere den Administrator. %1"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Tipeee button"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:152 themes/default/templates/raw.html.ep:11
|
||||
msgid "Total"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:60 themes/default/templates/partial/lutim.js.ep:14
|
||||
msgid "Tweet it!"
|
||||
msgstr "Twittere es!"
|
||||
|
||||
#. ($short)
|
||||
#: lib/Lutim/Controller.pm:162 lib/Lutim/Controller.pm:233
|
||||
msgid "Unable to find the image %1."
|
||||
msgstr "Konnte das Bild %1 nicht finden."
|
||||
|
||||
#: lib/Lutim/Controller.pm:529 lib/Lutim/Controller.pm:574 lib/Lutim/Controller.pm:616 lib/Lutim/Controller.pm:659 lib/Lutim/Controller.pm:671 lib/Lutim/Controller.pm:682 lib/Lutim/Controller.pm:707 lib/Lutim/Plugin/Helpers.pm:57
|
||||
msgid "Unable to find the image: it has been deleted."
|
||||
msgstr "Dieses Bild wurde gelöscht."
|
||||
|
||||
#: lib/Lutim/Controller.pm:105
|
||||
msgid "Unable to get counter"
|
||||
msgstr "Konnte den Zähler nicht abrufen"
|
||||
|
||||
#: themes/default/templates/about.html.ep:17
|
||||
msgid "Unlike many image sharing services, you don't give us rights on uploaded images."
|
||||
msgstr "Im Gegensatz zu anderen Bild-Hosting-Diensten, überträgst du uns nicht die Rechte an hochgeladenen Bildern."
|
||||
|
||||
#: themes/default/templates/index.html.ep:162 themes/default/templates/index.html.ep:201
|
||||
msgid "Upload an image with its URL"
|
||||
msgstr "Lade ein Bild über seine URL hoch"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:54
|
||||
msgid "Uploaded at"
|
||||
msgstr "Hochgeladen am"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:6
|
||||
msgid "Uploaded files by days"
|
||||
msgstr "Hochgeladene Bilder pro Tag"
|
||||
|
||||
#. ($c->app->config('contact')
|
||||
#: lib/Lutim/Plugin/Helpers.pm:152
|
||||
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
|
||||
msgstr "Hochladen ist momentan deaktiviert. Versuche es später erneut oder kontaktiere den Administrator (%1)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:65 themes/default/templates/index.html.ep:67 themes/default/templates/myfiles.html.ep:51 themes/default/templates/partial/lutim.js.ep:71 themes/default/templates/partial/lutim.js.ep:75
|
||||
msgid "View link"
|
||||
msgstr "Link ansehen"
|
||||
|
||||
#: themes/default/templates/about.html.ep:22
|
||||
msgid "What about the software which provides the service?"
|
||||
msgstr "Welche Software stellt diesen Dienst bereit?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:3
|
||||
msgid "What is Lutim?"
|
||||
msgstr "Was ist Lutim?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:15
|
||||
msgid "Who owns rights on images uploaded on Lutim?"
|
||||
msgstr "Wer hat die Rechte an auf Lutim hochgeladenen Bildern?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:12
|
||||
msgid "Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send an image. Don't panic, it is normally the case of all sites on which you send files!"
|
||||
msgstr "Ja, ist es! Auf der anderen Seite wird deine IP-Adresse, wegen rechtlichen Gründen, beim hochladen gespeichert. Keine Panik, das ist normalerweise der Fall für alle Seiten, an die du Dateien sendest!"
|
||||
|
||||
#: themes/default/templates/about.html.ep:10
|
||||
msgid "Yes, it is! On the other side, if you want to support the developer, you can do it via <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> or via <a href=\"https://liberapay.com/sky/\">Liberapay</a>."
|
||||
msgstr "Ja, ist es! Auf der anderen Seite kannst du den Entwickler via <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> oder <a href=\"https://liberapay.com/sky/\">Liberapay</a> unterstützen."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:6
|
||||
msgid "You asked to download a zip archive for too much files."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:8
|
||||
msgid "You can, optionally, request that the image(s) posted on Lutim to be deleted at first view (or download) or after the delay selected from those proposed."
|
||||
msgstr "Du kannst Bilder, die du auf Lutim hochlädst, entweder nach dem ernsten Ansehen (oder Herunterladen) oder nach einem der vorgeschlagenen Zeiten löschen lassen."
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "and on"
|
||||
msgstr "und auf"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "core developer"
|
||||
msgstr "Haupt-Entwickler"
|
||||
|
||||
#: lib/Lutim.pm:190 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:175 themes/default/templates/index.html.ep:3 themes/default/templates/raw.html.ep:17 themes/default/templates/raw.html.ep:34 themes/default/templates/raw.html.ep:6
|
||||
msgid "no time limit"
|
||||
msgstr "keine Zeit-Begrenzung"
|
||||
|
||||
#: themes/default/templates/about.html.ep:38
|
||||
msgid "occitan translation"
|
||||
msgstr "okzitanisch Übersetzung"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "on"
|
||||
msgstr "auf"
|
||||
|
||||
#: themes/default/templates/about.html.ep:36
|
||||
msgid "spanish translation"
|
||||
msgstr "spanische Übersetzung"
|
||||
|
||||
#: themes/default/templates/about.html.ep:28
|
||||
msgid "webapp developer"
|
||||
msgstr "Webapp-Entwickler"
|
||||
489
themes/default/lib/Lutim/I18N/en.po
Normal file
@@ -0,0 +1,489 @@
|
||||
# Lutim language file
|
||||
# Copyright (C) 2014 Luc Didry
|
||||
# This file is distributed under the same license as the Lutim package.
|
||||
#
|
||||
# Translators:
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Lutim\n"
|
||||
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"PO-Revision-Date: 2015-09-10 23:28+0000\n"
|
||||
"Last-Translator: Luc Didry <luc@didry.org>\n"
|
||||
"Language-Team: English (http://www.transifex.com/fiat-tux/lutim/language/en/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: en\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. (7)
|
||||
#. (30)
|
||||
#. ($delay)
|
||||
#. (config('max_delay')
|
||||
#: lib/Lutim/Command/cron/stats.pm:149 lib/Lutim/Command/cron/stats.pm:150 lib/Lutim/Command/cron/stats.pm:160 lib/Lutim/Command/cron/stats.pm:161 lib/Lutim/Command/cron/stats.pm:177 lib/Lutim/Command/cron/stats.pm:178 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/for_my_delay.html.ep:3 themes/default/templates/partial/lutim.js.ep:138 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/partial/lutim.js.ep:148 themes/default/templates/raw.html.ep:19 themes/default/templates/raw.html.ep:20 themes/default/templates/raw.html.ep:36 themes/default/templates/raw.html.ep:37 themes/default/templates/raw.html.ep:8 themes/default/templates/raw.html.ep:9
|
||||
msgid "%1 days"
|
||||
msgstr ""
|
||||
|
||||
#. ($total)
|
||||
#: themes/default/templates/stats.html.ep:2
|
||||
msgid "%1 sent images on this instance from beginning."
|
||||
msgstr "%1 sent images on this instance from beginning."
|
||||
|
||||
#: themes/default/templates/index.html.ep:190
|
||||
msgid "-or-"
|
||||
msgstr "-or-"
|
||||
|
||||
#: lib/Lutim.pm:192 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:5 themes/default/templates/raw.html.ep:10 themes/default/templates/raw.html.ep:21 themes/default/templates/raw.html.ep:38
|
||||
msgid "1 year"
|
||||
msgstr "1 year"
|
||||
|
||||
#: lib/Lutim.pm:191 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:159 lib/Lutim/Command/cron/stats.pm:176 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/raw.html.ep:18 themes/default/templates/raw.html.ep:35 themes/default/templates/raw.html.ep:7
|
||||
msgid "24 hours"
|
||||
msgstr "24 hours"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:57
|
||||
msgid ": Error while trying to get the counter."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:144 themes/default/templates/raw.html.ep:3
|
||||
msgid "Active images"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:288
|
||||
msgid "An error occured while downloading the image."
|
||||
msgstr "An error occured while downloading the image."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:2
|
||||
msgid "Archives download"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:41 themes/default/templates/myfiles.html.ep:64 themes/default/templates/stats.html.ep:25
|
||||
msgid "Back to homepage"
|
||||
msgstr "Back to homepage"
|
||||
|
||||
#: themes/default/templates/index.html.ep:193 themes/default/templates/index.html.ep:194
|
||||
msgid "Click to open the file browser"
|
||||
msgstr "Click to open the file browser"
|
||||
|
||||
#: themes/default/templates/about.html.ep:30
|
||||
msgid "Contributors"
|
||||
msgstr "Contributors"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:214 themes/default/templates/partial/lutim.js.ep:268 themes/default/templates/partial/lutim.js.ep:346
|
||||
msgid "Copy all view links to clipboard"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:18 themes/default/templates/index.html.ep:36 themes/default/templates/index.html.ep:69 themes/default/templates/index.html.ep:77 themes/default/templates/index.html.ep:85 themes/default/templates/index.html.ep:93 themes/default/templates/myfiles.html.ep:20 themes/default/templates/myfiles.html.ep:38 themes/default/templates/partial/common.js.ep:150 themes/default/templates/partial/lutim.js.ep:105 themes/default/templates/partial/lutim.js.ep:120 themes/default/templates/partial/lutim.js.ep:79 themes/default/templates/partial/lutim.js.ep:91
|
||||
msgid "Copy to clipboard"
|
||||
msgstr "Copy to clipboard"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:52
|
||||
msgid "Counter"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/stats.html.ep:18
|
||||
msgid "Delay repartition chart for disabled images"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/stats.html.ep:15
|
||||
msgid "Delay repartition chart for enabled images"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:115 themes/default/templates/index.html.ep:147 themes/default/templates/index.html.ep:178 themes/default/templates/myfiles.html.ep:53 themes/default/templates/partial/lutim.js.ep:159
|
||||
msgid "Delete at first view?"
|
||||
msgstr "Delete at first view?"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:145 themes/default/templates/raw.html.ep:4
|
||||
msgid "Deleted images"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:146 themes/default/templates/raw.html.ep:5
|
||||
msgid "Deleted images in 30 days"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:98 themes/default/templates/myfiles.html.ep:56 themes/default/templates/partial/common.js.ep:142 themes/default/templates/partial/common.js.ep:145
|
||||
msgid "Deletion link"
|
||||
msgstr "Deletion link"
|
||||
|
||||
#: themes/default/templates/gallery.html.ep:6
|
||||
msgid "Download all images"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:81 themes/default/templates/index.html.ep:83 themes/default/templates/partial/lutim.js.ep:101 themes/default/templates/partial/lutim.js.ep:97
|
||||
msgid "Download link"
|
||||
msgstr "Download link"
|
||||
|
||||
#: themes/default/templates/index.html.ep:28 themes/default/templates/index.html.ep:31 themes/default/templates/myfiles.html.ep:30 themes/default/templates/myfiles.html.ep:33
|
||||
msgid "Download zip link"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:189
|
||||
msgid "Drag & drop images here"
|
||||
msgstr "Drag & drop images here"
|
||||
|
||||
#: themes/default/templates/about.html.ep:7
|
||||
msgid "Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you four URLs. One to view the image, an other to directly download it, one you can use on social networks and a last to delete the image when you want."
|
||||
msgstr "Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you four URLs. One to view the image, an other to directly download it, one you can use on social networks and a last to delete the image when you want."
|
||||
|
||||
#: themes/default/templates/index.html.ep:150 themes/default/templates/index.html.ep:181
|
||||
msgid "Encrypt the image (Lutim does not keep the key)."
|
||||
msgstr "Encrypt the image (Lutim does not keep the key)."
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:44
|
||||
msgid "Error while trying to modify the image."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/stats.html.ep:10
|
||||
msgid "Evolution of total files"
|
||||
msgstr "Evolution of total files"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:55
|
||||
msgid "Expires at"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:50
|
||||
msgid "File name"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:24
|
||||
msgid "For more details, see the <a href=\"https://framagit.org/luc/lutim\">homepage of the project</a>."
|
||||
msgstr "For more details, see the <a href=\"https://framagit.org/luc/lutim\">homepage of the project</a>."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:55
|
||||
msgid "Fork me!"
|
||||
msgstr "Fork me!"
|
||||
|
||||
#: themes/default/templates/index.html.ep:10 themes/default/templates/index.html.ep:13 themes/default/templates/myfiles.html.ep:12 themes/default/templates/myfiles.html.ep:15
|
||||
msgid "Gallery link"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/common.js.ep:104 themes/default/templates/partial/common.js.ep:87
|
||||
msgid "Hit Ctrl+C, then Enter to copy the short link"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:50
|
||||
msgid "Homepage"
|
||||
msgstr "Homepage"
|
||||
|
||||
#: themes/default/templates/about.html.ep:20
|
||||
msgid "How do you pronounce Lutim?"
|
||||
msgstr "How do you pronounce Lutim?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:6
|
||||
msgid "How does it work?"
|
||||
msgstr "How does it work?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:18
|
||||
msgid "How to report an image?"
|
||||
msgstr "How to report an image?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:14
|
||||
msgid "If the files are deleted if you ask it while posting it, their SHA512 footprint are retained."
|
||||
msgstr "If the files are deleted if you ask it while posting it, their SHA512 footprint are retained."
|
||||
|
||||
#: themes/default/templates/index.html.ep:163 themes/default/templates/index.html.ep:203
|
||||
msgid "Image URL"
|
||||
msgstr "Image URL"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:143 themes/default/templates/raw.html.ep:2
|
||||
msgid "Image delay"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:710
|
||||
msgid "Image not found."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:54
|
||||
msgid "Informations"
|
||||
msgstr "Informations"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:62
|
||||
msgid "Install webapp"
|
||||
msgstr "Install webapp"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:61
|
||||
msgid "Instance's statistics"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:11
|
||||
msgid "Is it really anonymous?"
|
||||
msgstr "Is it really anonymous?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:9
|
||||
msgid "Is it really free (as in free beer)?"
|
||||
msgstr "Is it really free (as in free beer)?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:21
|
||||
msgid "Juste like you pronounce the French word <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
msgstr "Juste like you pronounce the French word <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:153 themes/default/templates/index.html.ep:184
|
||||
msgid "Keep EXIF tags"
|
||||
msgstr "Keep EXIF tags"
|
||||
|
||||
#: themes/default/templates/index.html.ep:118 themes/default/templates/index.html.ep:166 themes/default/templates/index.html.ep:206 themes/default/templates/partial/lutim.js.ep:163
|
||||
msgid "Let's go!"
|
||||
msgstr "Let's go!"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Liberapay button"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:53
|
||||
msgid "License:"
|
||||
msgstr "License:"
|
||||
|
||||
#: themes/default/templates/index.html.ep:89 themes/default/templates/index.html.ep:91 themes/default/templates/partial/lutim.js.ep:111 themes/default/templates/partial/lutim.js.ep:115
|
||||
msgid "Link for share on social networks"
|
||||
msgstr "Link for share on social networks"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:7
|
||||
msgid "Lutim can't zip so many images at once, so it splitted your demand in multiple URLs."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:4
|
||||
msgid "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."
|
||||
msgstr "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."
|
||||
|
||||
#: themes/default/templates/about.html.ep:25
|
||||
msgid "Main developers"
|
||||
msgstr "Main developers"
|
||||
|
||||
#: themes/default/templates/index.html.ep:73 themes/default/templates/index.html.ep:75 themes/default/templates/partial/lutim.js.ep:85 themes/default/templates/partial/lutim.js.ep:88
|
||||
msgid "Markdown syntax"
|
||||
msgstr "Markdown syntax"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:60 themes/default/templates/myfiles.html.ep:2
|
||||
msgid "My images"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:19
|
||||
msgid "No limit"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:198
|
||||
msgid "Only images are allowed"
|
||||
msgstr "Only images are allowed"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:6
|
||||
msgid "Only the images sent with this browser will be listed here. The informations are stored in localStorage: if you delete your localStorage data, you'll loose this informations."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:16
|
||||
msgid "Only the uploader! (well, only if he's the only owner of the images' rights before the upload)"
|
||||
msgstr "Only the uploader! (well, only if he's the only owner of the images' rights before the upload)"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:12
|
||||
msgid "Please click on each URL to download the different zip files."
|
||||
msgstr ""
|
||||
|
||||
#. (config('contact')
|
||||
#: themes/default/templates/about.html.ep:19
|
||||
msgid "Please contact the administrator: %1"
|
||||
msgstr "Please contact the administrator: %1"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:22
|
||||
msgid "Raw stats"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:158
|
||||
msgid "Send an image"
|
||||
msgstr "Send an image"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:20
|
||||
msgid "Share it!"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:56
|
||||
msgid "Share on Twitter"
|
||||
msgstr "Share on Twitter"
|
||||
|
||||
#: themes/default/templates/index.html.ep:133 themes/default/templates/partial/lutim.js.ep:174
|
||||
msgid "Something bad happened"
|
||||
msgstr "Something bad happened"
|
||||
|
||||
#. ($c->config('contact')
|
||||
#: lib/Lutim/Controller.pm:717
|
||||
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Support the author on Liberapay"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Support the author on Tipeee"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:13
|
||||
msgid "The IP address of the image's sender is retained for a delay which depends of the administrator's choice (for the official instance, which is located in France, it's one year)."
|
||||
msgstr "The IP address of the image's sender is retained for a delay which depends of the administrator's choice (for the official instance, which is located in France, it's one year)."
|
||||
|
||||
#: themes/default/templates/about.html.ep:23
|
||||
msgid "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."
|
||||
msgstr "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."
|
||||
|
||||
#: lib/Lutim/Controller.pm:307
|
||||
msgid "The URL is not valid."
|
||||
msgstr "The URL is not valid."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:16
|
||||
msgid "The automatic download process will open a tab in your browser for each link. You need to allow popups for Lutim."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:120 lib/Lutim/Controller.pm:188
|
||||
msgid "The delete token is invalid."
|
||||
msgstr "The delete token is invalid."
|
||||
|
||||
#. ($upload->filename)
|
||||
#: lib/Lutim/Controller.pm:445
|
||||
msgid "The file %1 is not an image."
|
||||
msgstr "The file %1 is not an image."
|
||||
|
||||
#. ($tx->res->max_message_size)
|
||||
#. ($c->req->max_message_size)
|
||||
#. (config('max_file_size')
|
||||
#: lib/Lutim/Controller.pm:271 lib/Lutim/Controller.pm:340 themes/default/templates/partial/lutim.js.ep:240
|
||||
msgid "The file exceed the size limit (%1)"
|
||||
msgstr "The file exceed the size limit (%1)"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:12
|
||||
msgid "The graph's datas are not updated in real-time."
|
||||
msgstr "The graph's datas are not updated in real-time."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:190
|
||||
msgid "The image %1 has already been deleted."
|
||||
msgstr "The image %1 has already been deleted."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:199 lib/Lutim/Controller.pm:204
|
||||
msgid "The image %1 has been successfully deleted"
|
||||
msgstr "The image %1 has been successfully deleted"
|
||||
|
||||
#: lib/Lutim/Controller.pm:128
|
||||
msgid "The image's delay has been successfully modified"
|
||||
msgstr "The image's delay has been successfully modified"
|
||||
|
||||
#: themes/default/templates/index.html.ep:45
|
||||
msgid "The images are encrypted on the server (Lutim does not keep the key)."
|
||||
msgstr "The images are encrypted on the server (Lutim does not keep the key)."
|
||||
|
||||
#: themes/default/templates/about.html.ep:5
|
||||
msgid "The images you post on Lutim can be stored indefinitely or be deleted at first view or after a delay selected from those proposed."
|
||||
msgstr "The images you post on Lutim can be stored indefinitely or be deleted at first view or after a delay selected from those proposed."
|
||||
|
||||
#. ($c->config->{contact})
|
||||
#: lib/Lutim/Controller.pm:442
|
||||
msgid "There is no more available URL. Retry or contact the administrator. %1"
|
||||
msgstr "There is no more available URL. Retry or contact the administrator. %1"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Tipeee button"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:152 themes/default/templates/raw.html.ep:11
|
||||
msgid "Total"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:60 themes/default/templates/partial/lutim.js.ep:14
|
||||
msgid "Tweet it!"
|
||||
msgstr "Tweet it!"
|
||||
|
||||
#. ($short)
|
||||
#: lib/Lutim/Controller.pm:162 lib/Lutim/Controller.pm:233
|
||||
msgid "Unable to find the image %1."
|
||||
msgstr "Unable to find the image %1."
|
||||
|
||||
#: lib/Lutim/Controller.pm:529 lib/Lutim/Controller.pm:574 lib/Lutim/Controller.pm:616 lib/Lutim/Controller.pm:659 lib/Lutim/Controller.pm:671 lib/Lutim/Controller.pm:682 lib/Lutim/Controller.pm:707 lib/Lutim/Plugin/Helpers.pm:57
|
||||
msgid "Unable to find the image: it has been deleted."
|
||||
msgstr "Unable to find the image: it has been deleted."
|
||||
|
||||
#: lib/Lutim/Controller.pm:105
|
||||
msgid "Unable to get counter"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:17
|
||||
msgid "Unlike many image sharing services, you don't give us rights on uploaded images."
|
||||
msgstr "Unlike many image sharing services, you don't give us rights on uploaded images."
|
||||
|
||||
#: themes/default/templates/index.html.ep:162 themes/default/templates/index.html.ep:201
|
||||
msgid "Upload an image with its URL"
|
||||
msgstr "Upload an image with its URL"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:54
|
||||
msgid "Uploaded at"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/stats.html.ep:6
|
||||
msgid "Uploaded files by days"
|
||||
msgstr "Uploaded files by days"
|
||||
|
||||
#. ($c->app->config('contact')
|
||||
#: lib/Lutim/Plugin/Helpers.pm:152
|
||||
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
|
||||
msgstr "Uploading is currently disabled, please try later or contact the administrator (%1)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:65 themes/default/templates/index.html.ep:67 themes/default/templates/myfiles.html.ep:51 themes/default/templates/partial/lutim.js.ep:71 themes/default/templates/partial/lutim.js.ep:75
|
||||
msgid "View link"
|
||||
msgstr "View link"
|
||||
|
||||
#: themes/default/templates/about.html.ep:22
|
||||
msgid "What about the software which provides the service?"
|
||||
msgstr "What about the software which provides the service?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:3
|
||||
msgid "What is Lutim?"
|
||||
msgstr "What is Lutim?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:15
|
||||
msgid "Who owns rights on images uploaded on Lutim?"
|
||||
msgstr "Who owns rights on images uploaded on Lutim?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:12
|
||||
msgid "Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send an image. Don't panic, it is normally the case of all sites on which you send files!"
|
||||
msgstr "Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send an image. Don't panic, it is normally the case of all sites on which you send files!"
|
||||
|
||||
#:
|
||||
msgid "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:1JCEtmx9pyzWfitMQj2pKAk8GNgyix7RmA?label=lutim\">BitCoin</a>."
|
||||
msgstr "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:1JCEtmx9pyzWfitMQj2pKAk8GNgyix7RmA?label=lutim\">BitCoin</a>."
|
||||
|
||||
#: themes/default/templates/about.html.ep:10
|
||||
msgid "Yes, it is! On the other side, if you want to support the developer, you can do it via <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> or via <a href=\"https://liberapay.com/sky/\">Liberapay</a>."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/zip.html.ep:6
|
||||
msgid "You asked to download a zip archive for too much files."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:8
|
||||
msgid "You can, optionally, request that the image(s) posted on Lutim to be deleted at first view (or download) or after the delay selected from those proposed."
|
||||
msgstr "You can, optionally, request that the image(s) posted on Lutim to be deleted at first view (or download) or after the delay selected from those proposed."
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "and on"
|
||||
msgstr "and on"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "core developer"
|
||||
msgstr "core developer"
|
||||
|
||||
#: lib/Lutim.pm:190 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:175 themes/default/templates/index.html.ep:3 themes/default/templates/raw.html.ep:17 themes/default/templates/raw.html.ep:34 themes/default/templates/raw.html.ep:6
|
||||
msgid "no time limit"
|
||||
msgstr "no time limit"
|
||||
|
||||
#: themes/default/templates/about.html.ep:38
|
||||
msgid "occitan translation"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "on"
|
||||
msgstr "on"
|
||||
|
||||
#: themes/default/templates/about.html.ep:36
|
||||
msgid "spanish translation"
|
||||
msgstr "spanish translation"
|
||||
|
||||
#: themes/default/templates/about.html.ep:28
|
||||
msgid "webapp developer"
|
||||
msgstr "webapp developer"
|
||||
487
themes/default/lib/Lutim/I18N/es.po
Normal file
@@ -0,0 +1,487 @@
|
||||
# Lutim language file
|
||||
# Copyright (C) 2014 Luc Didry
|
||||
# This file is distributed under the same license as the Lutim package.
|
||||
#
|
||||
# Translators:
|
||||
# Translators:
|
||||
# Luc Didry <luc@didry.org>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Lutim\n"
|
||||
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"PO-Revision-Date: 2015-09-17 22:00+0000\n"
|
||||
"Last-Translator: Luc Didry <luc@didry.org>\n"
|
||||
"Language-Team: Spanish (http://www.transifex.com/fiat-tux/lutim/language/es/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: es\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#. (7)
|
||||
#. (30)
|
||||
#. ($delay)
|
||||
#. (config('max_delay')
|
||||
#: lib/Lutim/Command/cron/stats.pm:149 lib/Lutim/Command/cron/stats.pm:150 lib/Lutim/Command/cron/stats.pm:160 lib/Lutim/Command/cron/stats.pm:161 lib/Lutim/Command/cron/stats.pm:177 lib/Lutim/Command/cron/stats.pm:178 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/for_my_delay.html.ep:3 themes/default/templates/partial/lutim.js.ep:138 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/partial/lutim.js.ep:148 themes/default/templates/raw.html.ep:19 themes/default/templates/raw.html.ep:20 themes/default/templates/raw.html.ep:36 themes/default/templates/raw.html.ep:37 themes/default/templates/raw.html.ep:8 themes/default/templates/raw.html.ep:9
|
||||
msgid "%1 days"
|
||||
msgstr "%1 días"
|
||||
|
||||
#. ($total)
|
||||
#: themes/default/templates/stats.html.ep:2
|
||||
msgid "%1 sent images on this instance from beginning."
|
||||
msgstr "%1 imágenes enviadas a esta instancia desde el inicio."
|
||||
|
||||
#: themes/default/templates/index.html.ep:190
|
||||
msgid "-or-"
|
||||
msgstr "-o-"
|
||||
|
||||
#: lib/Lutim.pm:192 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:5 themes/default/templates/raw.html.ep:10 themes/default/templates/raw.html.ep:21 themes/default/templates/raw.html.ep:38
|
||||
msgid "1 year"
|
||||
msgstr "1 año"
|
||||
|
||||
#: lib/Lutim.pm:191 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:159 lib/Lutim/Command/cron/stats.pm:176 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/raw.html.ep:18 themes/default/templates/raw.html.ep:35 themes/default/templates/raw.html.ep:7
|
||||
msgid "24 hours"
|
||||
msgstr "24 horas"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:57
|
||||
msgid ": Error while trying to get the counter."
|
||||
msgstr ": Error al intentar obtener el contador."
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:144 themes/default/templates/raw.html.ep:3
|
||||
msgid "Active images"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:288
|
||||
msgid "An error occured while downloading the image."
|
||||
msgstr "Error al intentar modificar la imagen."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:2
|
||||
msgid "Archives download"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:41 themes/default/templates/myfiles.html.ep:64 themes/default/templates/stats.html.ep:25
|
||||
msgid "Back to homepage"
|
||||
msgstr "Volver a la página inicial"
|
||||
|
||||
#: themes/default/templates/index.html.ep:193 themes/default/templates/index.html.ep:194
|
||||
msgid "Click to open the file browser"
|
||||
msgstr "Clic para abrir el explorador de archivos"
|
||||
|
||||
#: themes/default/templates/about.html.ep:30
|
||||
msgid "Contributors"
|
||||
msgstr "Contribuidores"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:214 themes/default/templates/partial/lutim.js.ep:268 themes/default/templates/partial/lutim.js.ep:346
|
||||
msgid "Copy all view links to clipboard"
|
||||
msgstr "Copiar todos los enlaces de visualización al portapapeles"
|
||||
|
||||
#: themes/default/templates/index.html.ep:18 themes/default/templates/index.html.ep:36 themes/default/templates/index.html.ep:69 themes/default/templates/index.html.ep:77 themes/default/templates/index.html.ep:85 themes/default/templates/index.html.ep:93 themes/default/templates/myfiles.html.ep:20 themes/default/templates/myfiles.html.ep:38 themes/default/templates/partial/common.js.ep:150 themes/default/templates/partial/lutim.js.ep:105 themes/default/templates/partial/lutim.js.ep:120 themes/default/templates/partial/lutim.js.ep:79 themes/default/templates/partial/lutim.js.ep:91
|
||||
msgid "Copy to clipboard"
|
||||
msgstr "Copiar al portapapeles"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:52
|
||||
msgid "Counter"
|
||||
msgstr "Contador"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:18
|
||||
msgid "Delay repartition chart for disabled images"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/stats.html.ep:15
|
||||
msgid "Delay repartition chart for enabled images"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:115 themes/default/templates/index.html.ep:147 themes/default/templates/index.html.ep:178 themes/default/templates/myfiles.html.ep:53 themes/default/templates/partial/lutim.js.ep:159
|
||||
msgid "Delete at first view?"
|
||||
msgstr "¿Borrar en la primera vista?"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:145 themes/default/templates/raw.html.ep:4
|
||||
msgid "Deleted images"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:146 themes/default/templates/raw.html.ep:5
|
||||
msgid "Deleted images in 30 days"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:98 themes/default/templates/myfiles.html.ep:56 themes/default/templates/partial/common.js.ep:142 themes/default/templates/partial/common.js.ep:145
|
||||
msgid "Deletion link"
|
||||
msgstr "Enlace para borrar"
|
||||
|
||||
#: themes/default/templates/gallery.html.ep:6
|
||||
msgid "Download all images"
|
||||
msgstr "Descargar todas las imágenes"
|
||||
|
||||
#: themes/default/templates/index.html.ep:81 themes/default/templates/index.html.ep:83 themes/default/templates/partial/lutim.js.ep:101 themes/default/templates/partial/lutim.js.ep:97
|
||||
msgid "Download link"
|
||||
msgstr "Enlace de descarga"
|
||||
|
||||
#: themes/default/templates/index.html.ep:28 themes/default/templates/index.html.ep:31 themes/default/templates/myfiles.html.ep:30 themes/default/templates/myfiles.html.ep:33
|
||||
msgid "Download zip link"
|
||||
msgstr "Enlace de descarga del archivo de las imágenes"
|
||||
|
||||
#: themes/default/templates/index.html.ep:189
|
||||
msgid "Drag & drop images here"
|
||||
msgstr "Arrastre y suelte imágenes aquí"
|
||||
|
||||
#: themes/default/templates/about.html.ep:7
|
||||
msgid "Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you four URLs. One to view the image, an other to directly download it, one you can use on social networks and a last to delete the image when you want."
|
||||
msgstr "Arrastre y suelte una imagen en el área apropiada, o use el método tradicional para enviar ficheros, y Lutim proporcionará cuatro URLs. Una para ver la imagen, otra para descargarla directamente, una que upede usar en redes sociales, y una última para borrar la imagen cuando lo desee."
|
||||
|
||||
#: themes/default/templates/index.html.ep:150 themes/default/templates/index.html.ep:181
|
||||
msgid "Encrypt the image (Lutim does not keep the key)."
|
||||
msgstr "Las imágenes se cifran en el servidor (Lutim no guarda la clave)."
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:44
|
||||
msgid "Error while trying to modify the image."
|
||||
msgstr "Error al intentar modificar la imagen."
|
||||
|
||||
#: themes/default/templates/stats.html.ep:10
|
||||
msgid "Evolution of total files"
|
||||
msgstr "Evolución de archivos en total"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:55
|
||||
msgid "Expires at"
|
||||
msgstr "Expira"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:50
|
||||
msgid "File name"
|
||||
msgstr "Nombre de archivo"
|
||||
|
||||
#: themes/default/templates/about.html.ep:24
|
||||
msgid "For more details, see the <a href=\"https://framagit.org/luc/lutim\">homepage of the project</a>."
|
||||
msgstr "Para más detalles, vea la <a href=\"https://framagit.org/luc/lutim\">página del proyecto</a>."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:55
|
||||
msgid "Fork me!"
|
||||
msgstr "¡Clóname!"
|
||||
|
||||
#: themes/default/templates/index.html.ep:10 themes/default/templates/index.html.ep:13 themes/default/templates/myfiles.html.ep:12 themes/default/templates/myfiles.html.ep:15
|
||||
msgid "Gallery link"
|
||||
msgstr "Enlace a la galería"
|
||||
|
||||
#: themes/default/templates/partial/common.js.ep:104 themes/default/templates/partial/common.js.ep:87
|
||||
msgid "Hit Ctrl+C, then Enter to copy the short link"
|
||||
msgstr "Presione Ctrl + C, entonces Ingresar para copiar el enlace"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:50
|
||||
msgid "Homepage"
|
||||
msgstr "Página inicial"
|
||||
|
||||
#: themes/default/templates/about.html.ep:20
|
||||
msgid "How do you pronounce Lutim?"
|
||||
msgstr "¿Cómo se pronuncia Lutim?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:6
|
||||
msgid "How does it work?"
|
||||
msgstr "¿Cómo funciona?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:18
|
||||
msgid "How to report an image?"
|
||||
msgstr "¿Cómo informar sobre una imagen?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:14
|
||||
msgid "If the files are deleted if you ask it while posting it, their SHA512 footprint are retained."
|
||||
msgstr "Si los ficheros se borran por haberlo solicitado al enviarlos, se retiene su huella digital SHA512."
|
||||
|
||||
#: themes/default/templates/index.html.ep:163 themes/default/templates/index.html.ep:203
|
||||
msgid "Image URL"
|
||||
msgstr "URL de la imagen"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:143 themes/default/templates/raw.html.ep:2
|
||||
msgid "Image delay"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:710
|
||||
msgid "Image not found."
|
||||
msgstr "Imagen no encontrada."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:54
|
||||
msgid "Informations"
|
||||
msgstr "Informaciones"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:62
|
||||
msgid "Install webapp"
|
||||
msgstr "Instalar webapp"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:61
|
||||
msgid "Instance's statistics"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:11
|
||||
msgid "Is it really anonymous?"
|
||||
msgstr "¿Es realmente anónimo?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:9
|
||||
msgid "Is it really free (as in free beer)?"
|
||||
msgstr "¿Es realmente gratis?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:21
|
||||
msgid "Juste like you pronounce the French word <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
msgstr "Tal y como se pronuncia la palabra francesa <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:153 themes/default/templates/index.html.ep:184
|
||||
msgid "Keep EXIF tags"
|
||||
msgstr "Mantener las etiquetas EXIF"
|
||||
|
||||
#: themes/default/templates/index.html.ep:118 themes/default/templates/index.html.ep:166 themes/default/templates/index.html.ep:206 themes/default/templates/partial/lutim.js.ep:163
|
||||
msgid "Let's go!"
|
||||
msgstr "¡Vamos allá!"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Liberapay button"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:53
|
||||
msgid "License:"
|
||||
msgstr "Licencia:"
|
||||
|
||||
#: themes/default/templates/index.html.ep:89 themes/default/templates/index.html.ep:91 themes/default/templates/partial/lutim.js.ep:111 themes/default/templates/partial/lutim.js.ep:115
|
||||
msgid "Link for share on social networks"
|
||||
msgstr "Enlace para compartir en redes sociales"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:7
|
||||
msgid "Lutim can't zip so many images at once, so it splitted your demand in multiple URLs."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:4
|
||||
msgid "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."
|
||||
msgstr "Lutim es un servicio de alojamiento de imágenes anónimo y gratuito. También es el nombre del software libre que proporciona este servicio."
|
||||
|
||||
#: themes/default/templates/about.html.ep:25
|
||||
msgid "Main developers"
|
||||
msgstr "Desarrolladores principales"
|
||||
|
||||
#: themes/default/templates/index.html.ep:73 themes/default/templates/index.html.ep:75 themes/default/templates/partial/lutim.js.ep:85 themes/default/templates/partial/lutim.js.ep:88
|
||||
msgid "Markdown syntax"
|
||||
msgstr "Sintaxis de Markdown"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:60 themes/default/templates/myfiles.html.ep:2
|
||||
msgid "My images"
|
||||
msgstr "Mis Imágenes"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:19
|
||||
msgid "No limit"
|
||||
msgstr "Sin fecha de caducidad"
|
||||
|
||||
#: themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:198
|
||||
msgid "Only images are allowed"
|
||||
msgstr "Sólo se admiten imágenes"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:6
|
||||
msgid "Only the images sent with this browser will be listed here. The informations are stored in localStorage: if you delete your localStorage data, you'll loose this informations."
|
||||
msgstr "Sólo se enumeran aquí las imágenes enviadas con este navegador. Las informaciones se almacenan en localStorage: si elimina sus datos localStorage, perderás esta información."
|
||||
|
||||
#: themes/default/templates/about.html.ep:16
|
||||
msgid "Only the uploader! (well, only if he's the only owner of the images' rights before the upload)"
|
||||
msgstr "¡Sólo el usuario! (bueno, sólo si él/ela es el único titular de los derechos de las imágenes antes de subirlas)"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:12
|
||||
msgid "Please click on each URL to download the different zip files."
|
||||
msgstr ""
|
||||
|
||||
#. (config('contact')
|
||||
#: themes/default/templates/about.html.ep:19
|
||||
msgid "Please contact the administrator: %1"
|
||||
msgstr "Por favor, contacte con el administrador: %1"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:22
|
||||
msgid "Raw stats"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:158
|
||||
msgid "Send an image"
|
||||
msgstr "Enviar una imagen"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:20
|
||||
msgid "Share it!"
|
||||
msgstr "¡Compártelo!"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:56
|
||||
msgid "Share on Twitter"
|
||||
msgstr "Compartir en Twitter"
|
||||
|
||||
#: themes/default/templates/index.html.ep:133 themes/default/templates/partial/lutim.js.ep:174
|
||||
msgid "Something bad happened"
|
||||
msgstr "Algo malo ha pasado"
|
||||
|
||||
#. ($c->config('contact')
|
||||
#: lib/Lutim/Controller.pm:717
|
||||
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
|
||||
msgstr "Algo malo ha pasado. Inténtelo de nuevo más tarde o contacte con el administrador (%1)."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Support the author on Liberapay"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Support the author on Tipeee"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:13
|
||||
msgid "The IP address of the image's sender is retained for a delay which depends of the administrator's choice (for the official instance, which is located in France, it's one year)."
|
||||
msgstr "La dirección IP del remitente de la imagen se retiene durante un tiempo, que depende de lo que elija el administrador (para la instancia oficial, que está localizada en Francia, es un año)."
|
||||
|
||||
#: themes/default/templates/about.html.ep:23
|
||||
msgid "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."
|
||||
msgstr "El software Lutim es <a href=\"http://es.wikipedia.org/wiki/Software_libre\">software libre</a>, lo que le permite descargarlo e instalarlo en su propio servidor. Eche un vistazo a la licencia <a href=\"https://www.gnu.org/licenses/agpl-3.0.html\">AGPL</a> para ver qué puede hacer."
|
||||
|
||||
#: lib/Lutim/Controller.pm:307
|
||||
msgid "The URL is not valid."
|
||||
msgstr "La URL no es válida."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:16
|
||||
msgid "The automatic download process will open a tab in your browser for each link. You need to allow popups for Lutim."
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Controller.pm:120 lib/Lutim/Controller.pm:188
|
||||
msgid "The delete token is invalid."
|
||||
msgstr "El código de borrado no es válido."
|
||||
|
||||
#. ($upload->filename)
|
||||
#: lib/Lutim/Controller.pm:445
|
||||
msgid "The file %1 is not an image."
|
||||
msgstr "El archivo %1 no es una imagen."
|
||||
|
||||
#. ($tx->res->max_message_size)
|
||||
#. ($c->req->max_message_size)
|
||||
#. (config('max_file_size')
|
||||
#: lib/Lutim/Controller.pm:271 lib/Lutim/Controller.pm:340 themes/default/templates/partial/lutim.js.ep:240
|
||||
msgid "The file exceed the size limit (%1)"
|
||||
msgstr "El archivo supera el límite de tamaño (%1)"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:12
|
||||
msgid "The graph's datas are not updated in real-time."
|
||||
msgstr "Los datos del gráfico no se actualizan en tiempo real."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:190
|
||||
msgid "The image %1 has already been deleted."
|
||||
msgstr "La imagen %1 ya se ha borrado."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:199 lib/Lutim/Controller.pm:204
|
||||
msgid "The image %1 has been successfully deleted"
|
||||
msgstr "La imagen %1 se ha borrado correctamente"
|
||||
|
||||
#: lib/Lutim/Controller.pm:128
|
||||
msgid "The image's delay has been successfully modified"
|
||||
msgstr "Se ha modificado correctamente el tiempo de la imagen"
|
||||
|
||||
#: themes/default/templates/index.html.ep:45
|
||||
msgid "The images are encrypted on the server (Lutim does not keep the key)."
|
||||
msgstr "Las imágenes se cifran en el servidor (Lutim no guarda la clave)."
|
||||
|
||||
#: themes/default/templates/about.html.ep:5
|
||||
msgid "The images you post on Lutim can be stored indefinitely or be deleted at first view or after a delay selected from those proposed."
|
||||
msgstr "Puede, opcionalmente, solicitar que la imagen publicada en Lutim se elimine con la primera vista (o descarga) o tras un tiempo seleccionado de entre varios propuestos."
|
||||
|
||||
#. ($c->config->{contact})
|
||||
#: lib/Lutim/Controller.pm:442
|
||||
msgid "There is no more available URL. Retry or contact the administrator. %1"
|
||||
msgstr "No más URL disponibles. Inténtelo de nuevo o contacte con el administrador. %1"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Tipeee button"
|
||||
msgstr ""
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:152 themes/default/templates/raw.html.ep:11
|
||||
msgid "Total"
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/index.html.ep:60 themes/default/templates/partial/lutim.js.ep:14
|
||||
msgid "Tweet it!"
|
||||
msgstr "¡Tuitéalo!"
|
||||
|
||||
#. ($short)
|
||||
#: lib/Lutim/Controller.pm:162 lib/Lutim/Controller.pm:233
|
||||
msgid "Unable to find the image %1."
|
||||
msgstr "No se ha podido encontrar la imagen %1."
|
||||
|
||||
#: lib/Lutim/Controller.pm:529 lib/Lutim/Controller.pm:574 lib/Lutim/Controller.pm:616 lib/Lutim/Controller.pm:659 lib/Lutim/Controller.pm:671 lib/Lutim/Controller.pm:682 lib/Lutim/Controller.pm:707 lib/Lutim/Plugin/Helpers.pm:57
|
||||
msgid "Unable to find the image: it has been deleted."
|
||||
msgstr "No se ha podido encontrar la imagen: ha sido borrada."
|
||||
|
||||
#: lib/Lutim/Controller.pm:105
|
||||
msgid "Unable to get counter"
|
||||
msgstr "Imposible recuperar el contador"
|
||||
|
||||
#: themes/default/templates/about.html.ep:17
|
||||
msgid "Unlike many image sharing services, you don't give us rights on uploaded images."
|
||||
msgstr "A diferencia de muchos servicios de compartición de imágenes, usted no cede los derechos de las imágenes que sube."
|
||||
|
||||
#: themes/default/templates/index.html.ep:162 themes/default/templates/index.html.ep:201
|
||||
msgid "Upload an image with its URL"
|
||||
msgstr "Subir una imagen con la URL"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:54
|
||||
msgid "Uploaded at"
|
||||
msgstr "Enviado el"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:6
|
||||
msgid "Uploaded files by days"
|
||||
msgstr "Archivos enviados por día"
|
||||
|
||||
#. ($c->app->config('contact')
|
||||
#: lib/Lutim/Plugin/Helpers.pm:152
|
||||
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
|
||||
msgstr "La carga está deshabilitada en estos momentos, por favor inténtelo más tarde o contacte con el administrador (%1)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:65 themes/default/templates/index.html.ep:67 themes/default/templates/myfiles.html.ep:51 themes/default/templates/partial/lutim.js.ep:71 themes/default/templates/partial/lutim.js.ep:75
|
||||
msgid "View link"
|
||||
msgstr "Enlace de visualización"
|
||||
|
||||
#: themes/default/templates/about.html.ep:22
|
||||
msgid "What about the software which provides the service?"
|
||||
msgstr "¿Y qué hay sobre el software que proporciona el servicio?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:3
|
||||
msgid "What is Lutim?"
|
||||
msgstr "¿Qué es Lutim?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:15
|
||||
msgid "Who owns rights on images uploaded on Lutim?"
|
||||
msgstr "¿Quién posee los derechos de las imágenes que se suben a Lutim?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:12
|
||||
msgid "Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send an image. Don't panic, it is normally the case of all sites on which you send files!"
|
||||
msgstr "¡Sí, lo es! Por otro lado, por razones legales, se almacena la dirección IP cuando se envía una imagen. Que no cunda el pánico, ¡es el caso habitual para todos los sitios a los cuales se envían ficheros!"
|
||||
|
||||
#: themes/default/templates/about.html.ep:10
|
||||
msgid "Yes, it is! On the other side, if you want to support the developer, you can do it via <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> or via <a href=\"https://liberapay.com/sky/\">Liberapay</a>."
|
||||
msgstr "¡Sí, lo es! Por otro lado, si quiere ayudar a apoyar al desarrollador, puede hacerlo vía <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> o con <a href=\"https://liberapay.com/sky/\">Liberapay</a>."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:6
|
||||
msgid "You asked to download a zip archive for too much files."
|
||||
msgstr ""
|
||||
|
||||
#: themes/default/templates/about.html.ep:8
|
||||
msgid "You can, optionally, request that the image(s) posted on Lutim to be deleted at first view (or download) or after the delay selected from those proposed."
|
||||
msgstr "Puede, opcionalmente, solicitar que la imagen publicada en Lutim se elimine con la primera vista (o descarga) o tras un tiempo seleccionado de entre varios propuestos."
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "and on"
|
||||
msgstr "y en"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "core developer"
|
||||
msgstr "desarrollador principal"
|
||||
|
||||
#: lib/Lutim.pm:190 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:175 themes/default/templates/index.html.ep:3 themes/default/templates/raw.html.ep:17 themes/default/templates/raw.html.ep:34 themes/default/templates/raw.html.ep:6
|
||||
msgid "no time limit"
|
||||
msgstr "Sin tiempo límite"
|
||||
|
||||
#: themes/default/templates/about.html.ep:38
|
||||
msgid "occitan translation"
|
||||
msgstr "traducción al occitano"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "on"
|
||||
msgstr "en"
|
||||
|
||||
#: themes/default/templates/about.html.ep:36
|
||||
msgid "spanish translation"
|
||||
msgstr "traducción al español"
|
||||
|
||||
#: themes/default/templates/about.html.ep:28
|
||||
msgid "webapp developer"
|
||||
msgstr "desarrollador de la webapp"
|
||||
489
themes/default/lib/Lutim/I18N/fr.po
Normal file
@@ -0,0 +1,489 @@
|
||||
# Lutim language file
|
||||
# Copyright (C) 2014 Luc Didry
|
||||
# This file is distributed under the same license as the Lutim package.
|
||||
#
|
||||
# Translators:
|
||||
# Translators:
|
||||
# Luc Didry <luc@didry.org>, 2015
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Lutim\n"
|
||||
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"PO-Revision-Date: 2017-06-05 15:54+0000\n"
|
||||
"Last-Translator: Luc Didry <luc@didry.org>\n"
|
||||
"Language-Team: French (http://www.transifex.com/fiat-tux/lutim/language/fr/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: fr\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#. (7)
|
||||
#. (30)
|
||||
#. ($delay)
|
||||
#. (config('max_delay')
|
||||
#: lib/Lutim/Command/cron/stats.pm:149 lib/Lutim/Command/cron/stats.pm:150 lib/Lutim/Command/cron/stats.pm:160 lib/Lutim/Command/cron/stats.pm:161 lib/Lutim/Command/cron/stats.pm:177 lib/Lutim/Command/cron/stats.pm:178 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/for_my_delay.html.ep:3 themes/default/templates/partial/lutim.js.ep:138 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/partial/lutim.js.ep:148 themes/default/templates/raw.html.ep:19 themes/default/templates/raw.html.ep:20 themes/default/templates/raw.html.ep:36 themes/default/templates/raw.html.ep:37 themes/default/templates/raw.html.ep:8 themes/default/templates/raw.html.ep:9
|
||||
msgid "%1 days"
|
||||
msgstr "%1 jours"
|
||||
|
||||
#. ($total)
|
||||
#: themes/default/templates/stats.html.ep:2
|
||||
msgid "%1 sent images on this instance from beginning."
|
||||
msgstr "%1 images envoyées sur cette instance depuis le début."
|
||||
|
||||
#: themes/default/templates/index.html.ep:190
|
||||
msgid "-or-"
|
||||
msgstr "-ou-"
|
||||
|
||||
#: lib/Lutim.pm:192 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:5 themes/default/templates/raw.html.ep:10 themes/default/templates/raw.html.ep:21 themes/default/templates/raw.html.ep:38
|
||||
msgid "1 year"
|
||||
msgstr "1 an"
|
||||
|
||||
#: lib/Lutim.pm:191 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:159 lib/Lutim/Command/cron/stats.pm:176 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/raw.html.ep:18 themes/default/templates/raw.html.ep:35 themes/default/templates/raw.html.ep:7
|
||||
msgid "24 hours"
|
||||
msgstr "24 heures"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:57
|
||||
msgid ": Error while trying to get the counter."
|
||||
msgstr " : Erreur en essayant de récupérer le compteur."
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:144 themes/default/templates/raw.html.ep:3
|
||||
msgid "Active images"
|
||||
msgstr "Images actives"
|
||||
|
||||
#: lib/Lutim/Controller.pm:288
|
||||
msgid "An error occured while downloading the image."
|
||||
msgstr "Une erreur est survenue lors du téléchargement de l’image."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:2
|
||||
msgid "Archives download"
|
||||
msgstr "Téléchargement d’archives"
|
||||
|
||||
#: themes/default/templates/about.html.ep:41 themes/default/templates/myfiles.html.ep:64 themes/default/templates/stats.html.ep:25
|
||||
msgid "Back to homepage"
|
||||
msgstr "Retour à la page d’accueil"
|
||||
|
||||
#: themes/default/templates/index.html.ep:193 themes/default/templates/index.html.ep:194
|
||||
msgid "Click to open the file browser"
|
||||
msgstr "Cliquez pour utiliser le navigateur de fichier"
|
||||
|
||||
#: themes/default/templates/about.html.ep:30
|
||||
msgid "Contributors"
|
||||
msgstr "Contributeurs"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:214 themes/default/templates/partial/lutim.js.ep:268 themes/default/templates/partial/lutim.js.ep:346
|
||||
msgid "Copy all view links to clipboard"
|
||||
msgstr "Copier tous les liens de visualisation dans le presse-papier"
|
||||
|
||||
#: themes/default/templates/index.html.ep:18 themes/default/templates/index.html.ep:36 themes/default/templates/index.html.ep:69 themes/default/templates/index.html.ep:77 themes/default/templates/index.html.ep:85 themes/default/templates/index.html.ep:93 themes/default/templates/myfiles.html.ep:20 themes/default/templates/myfiles.html.ep:38 themes/default/templates/partial/common.js.ep:150 themes/default/templates/partial/lutim.js.ep:105 themes/default/templates/partial/lutim.js.ep:120 themes/default/templates/partial/lutim.js.ep:79 themes/default/templates/partial/lutim.js.ep:91
|
||||
msgid "Copy to clipboard"
|
||||
msgstr "Copier dans le presse-papier"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:52
|
||||
msgid "Counter"
|
||||
msgstr "Compteur"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:18
|
||||
msgid "Delay repartition chart for disabled images"
|
||||
msgstr "Graphe de répartition des délais pour les images supprimées"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:15
|
||||
msgid "Delay repartition chart for enabled images"
|
||||
msgstr "Graphe de répartition des délais pour les images actives"
|
||||
|
||||
#: themes/default/templates/index.html.ep:115 themes/default/templates/index.html.ep:147 themes/default/templates/index.html.ep:178 themes/default/templates/myfiles.html.ep:53 themes/default/templates/partial/lutim.js.ep:159
|
||||
msgid "Delete at first view?"
|
||||
msgstr "Supprimer au premier accès ?"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:145 themes/default/templates/raw.html.ep:4
|
||||
msgid "Deleted images"
|
||||
msgstr "Images supprimées"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:146 themes/default/templates/raw.html.ep:5
|
||||
msgid "Deleted images in 30 days"
|
||||
msgstr "Images supprimées dans 30 jours"
|
||||
|
||||
#: themes/default/templates/index.html.ep:98 themes/default/templates/myfiles.html.ep:56 themes/default/templates/partial/common.js.ep:142 themes/default/templates/partial/common.js.ep:145
|
||||
msgid "Deletion link"
|
||||
msgstr "Lien de suppression"
|
||||
|
||||
#: themes/default/templates/gallery.html.ep:6
|
||||
msgid "Download all images"
|
||||
msgstr "Télécharger toutes les images"
|
||||
|
||||
#: themes/default/templates/index.html.ep:81 themes/default/templates/index.html.ep:83 themes/default/templates/partial/lutim.js.ep:101 themes/default/templates/partial/lutim.js.ep:97
|
||||
msgid "Download link"
|
||||
msgstr "Lien de téléchargement"
|
||||
|
||||
#: themes/default/templates/index.html.ep:28 themes/default/templates/index.html.ep:31 themes/default/templates/myfiles.html.ep:30 themes/default/templates/myfiles.html.ep:33
|
||||
msgid "Download zip link"
|
||||
msgstr "Lien de téléchargement de l’archive des images"
|
||||
|
||||
#: themes/default/templates/index.html.ep:189
|
||||
msgid "Drag & drop images here"
|
||||
msgstr "Déposez vos images ici"
|
||||
|
||||
#: themes/default/templates/about.html.ep:7
|
||||
msgid "Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you four URLs. One to view the image, an other to directly download it, one you can use on social networks and a last to delete the image when you want."
|
||||
msgstr "Faites glisser des images dans la zone prévue à cet effet ou sélectionnez un fichier de façon classique et Lutim vous fournira quatre URLs en retour. Une pour afficher l’image, une autre pour la télécharger directement, une pour l’utiliser sur les réseaux sociaux et une dernière pour supprimer votre image quand vous le souhaitez"
|
||||
|
||||
#: themes/default/templates/index.html.ep:150 themes/default/templates/index.html.ep:181
|
||||
msgid "Encrypt the image (Lutim does not keep the key)."
|
||||
msgstr "Chiffrer l’image (Lutim ne stocke pas la clé)."
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:44
|
||||
msgid "Error while trying to modify the image."
|
||||
msgstr "Une erreur est survenue en essayant de modifier l’image."
|
||||
|
||||
#: themes/default/templates/stats.html.ep:10
|
||||
msgid "Evolution of total files"
|
||||
msgstr "Évolution du nombre total de fichiers"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:55
|
||||
msgid "Expires at"
|
||||
msgstr "Expire le"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:50
|
||||
msgid "File name"
|
||||
msgstr "Nom du fichier"
|
||||
|
||||
#: themes/default/templates/about.html.ep:24
|
||||
msgid "For more details, see the <a href=\"https://framagit.org/luc/lutim\">homepage of the project</a>."
|
||||
msgstr "Pour plus de détails, consultez la page <a href=\"https://framagit.org/luc/lutim\">Github</a> du projet."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:55
|
||||
msgid "Fork me!"
|
||||
msgstr "Créez un fork !"
|
||||
|
||||
#: themes/default/templates/index.html.ep:10 themes/default/templates/index.html.ep:13 themes/default/templates/myfiles.html.ep:12 themes/default/templates/myfiles.html.ep:15
|
||||
msgid "Gallery link"
|
||||
msgstr "Lien vers la galerie"
|
||||
|
||||
#: themes/default/templates/partial/common.js.ep:104 themes/default/templates/partial/common.js.ep:87
|
||||
msgid "Hit Ctrl+C, then Enter to copy the short link"
|
||||
msgstr "Faites Ctrl+C puis appuyez sur la touche Entrée pour copier le lien"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:50
|
||||
msgid "Homepage"
|
||||
msgstr "Accueil"
|
||||
|
||||
#: themes/default/templates/about.html.ep:20
|
||||
msgid "How do you pronounce Lutim?"
|
||||
msgstr "Comment doit-on prononcer Lutim ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:6
|
||||
msgid "How does it work?"
|
||||
msgstr "Comment ça marche ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:18
|
||||
msgid "How to report an image?"
|
||||
msgstr "Comment peut-on faire pour signaler une image ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:14
|
||||
msgid "If the files are deleted if you ask it while posting it, their SHA512 footprint are retained."
|
||||
msgstr "Si les fichiers sont bien supprimés si vous en avez exprimé le choix, leur empreinte SHA512 est toutefois conservée."
|
||||
|
||||
#: themes/default/templates/index.html.ep:163 themes/default/templates/index.html.ep:203
|
||||
msgid "Image URL"
|
||||
msgstr "URL de l’image"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:143 themes/default/templates/raw.html.ep:2
|
||||
msgid "Image delay"
|
||||
msgstr "Durée de rétention de l’image"
|
||||
|
||||
#: lib/Lutim/Controller.pm:710
|
||||
msgid "Image not found."
|
||||
msgstr "Image non trouvée."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:54
|
||||
msgid "Informations"
|
||||
msgstr "Informations"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:62
|
||||
msgid "Install webapp"
|
||||
msgstr "Installer la webapp"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:61
|
||||
msgid "Instance's statistics"
|
||||
msgstr "Statistiques de l’instance"
|
||||
|
||||
#: themes/default/templates/about.html.ep:11
|
||||
msgid "Is it really anonymous?"
|
||||
msgstr "C’est vraiment anonyme ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:9
|
||||
msgid "Is it really free (as in free beer)?"
|
||||
msgstr "C’est vraiment gratuit ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:21
|
||||
msgid "Juste like you pronounce the French word <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
msgstr "Comme on prononce <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:153 themes/default/templates/index.html.ep:184
|
||||
msgid "Keep EXIF tags"
|
||||
msgstr "Conserver les données EXIF"
|
||||
|
||||
#: themes/default/templates/index.html.ep:118 themes/default/templates/index.html.ep:166 themes/default/templates/index.html.ep:206 themes/default/templates/partial/lutim.js.ep:163
|
||||
msgid "Let's go!"
|
||||
msgstr "Allons-y !"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Liberapay button"
|
||||
msgstr "Bouton Liberapay"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:53
|
||||
msgid "License:"
|
||||
msgstr "Licence :"
|
||||
|
||||
#: themes/default/templates/index.html.ep:89 themes/default/templates/index.html.ep:91 themes/default/templates/partial/lutim.js.ep:111 themes/default/templates/partial/lutim.js.ep:115
|
||||
msgid "Link for share on social networks"
|
||||
msgstr "Lien pour partager sur les réseaux sociaux"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:7
|
||||
msgid "Lutim can't zip so many images at once, so it splitted your demand in multiple URLs."
|
||||
msgstr "Lutim ne peut zipper autant d’images à la fois, votre demande a donc été découpée en plusieurs URL."
|
||||
|
||||
#: themes/default/templates/about.html.ep:4
|
||||
msgid "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."
|
||||
msgstr "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."
|
||||
|
||||
#: themes/default/templates/about.html.ep:25
|
||||
msgid "Main developers"
|
||||
msgstr "Développeurs de l’application"
|
||||
|
||||
#: themes/default/templates/index.html.ep:73 themes/default/templates/index.html.ep:75 themes/default/templates/partial/lutim.js.ep:85 themes/default/templates/partial/lutim.js.ep:88
|
||||
msgid "Markdown syntax"
|
||||
msgstr "Syntaxe Markdown"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:60 themes/default/templates/myfiles.html.ep:2
|
||||
msgid "My images"
|
||||
msgstr "Mes images"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:19
|
||||
msgid "No limit"
|
||||
msgstr "Pas de date d’expiration"
|
||||
|
||||
#: themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:198
|
||||
msgid "Only images are allowed"
|
||||
msgstr "Seules les images sont acceptées"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:6
|
||||
msgid "Only the images sent with this browser will be listed here. The informations are stored in localStorage: if you delete your localStorage data, you'll loose this informations."
|
||||
msgstr "Seules les images envoyées avec ce navigateur seront listées ici. Les informations sont stockées en localStorage : si vous supprimez vos données localStorage, vous perdrez ces informations."
|
||||
|
||||
#: themes/default/templates/about.html.ep:16
|
||||
msgid "Only the uploader! (well, only if he's the only owner of the images' rights before the upload)"
|
||||
msgstr "Seulement l’envoyeur ! (enfin, seulement s’il possède des droits exclusifs sur les images avant de les envoyer)"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:12
|
||||
msgid "Please click on each URL to download the different zip files."
|
||||
msgstr "Veuillez cliquer sur chaque URL pour télécharger les différents fichiers zip."
|
||||
|
||||
#. (config('contact')
|
||||
#: themes/default/templates/about.html.ep:19
|
||||
msgid "Please contact the administrator: %1"
|
||||
msgstr "Veuillez contacter l’administrateur : %1"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:22
|
||||
msgid "Raw stats"
|
||||
msgstr "Statistiques brutes"
|
||||
|
||||
#: themes/default/templates/index.html.ep:158
|
||||
msgid "Send an image"
|
||||
msgstr "Envoyer une image"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:20
|
||||
msgid "Share it!"
|
||||
msgstr "Partagez !"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:56
|
||||
msgid "Share on Twitter"
|
||||
msgstr "Partager sur Twitter"
|
||||
|
||||
#: themes/default/templates/index.html.ep:133 themes/default/templates/partial/lutim.js.ep:174
|
||||
msgid "Something bad happened"
|
||||
msgstr "Un problème est survenu"
|
||||
|
||||
#. ($c->config('contact')
|
||||
#: lib/Lutim/Controller.pm:717
|
||||
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
|
||||
msgstr "Quelque chose s’est mal passé lors de la création de l’archive. Veuillez réessayer plus tard ou contactez l’administrateur (%1)."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Support the author on Liberapay"
|
||||
msgstr "Supporter l’auteur sur Liberapay"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Support the author on Tipeee"
|
||||
msgstr "Supporter l’auteur sur Tipeee"
|
||||
|
||||
#: themes/default/templates/about.html.ep:13
|
||||
msgid "The IP address of the image's sender is retained for a delay which depends of the administrator's choice (for the official instance, which is located in France, it's one year)."
|
||||
msgstr ""
|
||||
"L’IP de la personne ayant déposé l’image est stockée pendant un délai dépendant de l’administrateur de l’instance (pour l’instance officielle, dont le serveur est en France, c’est un délai\n"
|
||||
" d’un an)."
|
||||
|
||||
#: themes/default/templates/about.html.ep:23
|
||||
msgid "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."
|
||||
msgstr "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"
|
||||
|
||||
#: lib/Lutim/Controller.pm:307
|
||||
msgid "The URL is not valid."
|
||||
msgstr "L’URL n’est pas valide."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:16
|
||||
msgid "The automatic download process will open a tab in your browser for each link. You need to allow popups for Lutim."
|
||||
msgstr "Le processus de téléchargement automatique va ouvrir un onglet dans votre navigateur pour chaque lien. Vous devez autoriser les fenêtres popup pour Lutim."
|
||||
|
||||
#: lib/Lutim/Controller.pm:120 lib/Lutim/Controller.pm:188
|
||||
msgid "The delete token is invalid."
|
||||
msgstr "Le jeton de suppression est invalide."
|
||||
|
||||
#. ($upload->filename)
|
||||
#: lib/Lutim/Controller.pm:445
|
||||
msgid "The file %1 is not an image."
|
||||
msgstr "Le fichier %1 n’est pas une image."
|
||||
|
||||
#. ($tx->res->max_message_size)
|
||||
#. ($c->req->max_message_size)
|
||||
#. (config('max_file_size')
|
||||
#: lib/Lutim/Controller.pm:271 lib/Lutim/Controller.pm:340 themes/default/templates/partial/lutim.js.ep:240
|
||||
msgid "The file exceed the size limit (%1)"
|
||||
msgstr "Le fichier dépasse la limite de taille (%1)"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:12
|
||||
msgid "The graph's datas are not updated in real-time."
|
||||
msgstr "Les données du graphique ne sont pas mises à jour en temps réél."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:190
|
||||
msgid "The image %1 has already been deleted."
|
||||
msgstr "L’image %1 a déjà été supprimée."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:199 lib/Lutim/Controller.pm:204
|
||||
msgid "The image %1 has been successfully deleted"
|
||||
msgstr "L’image %1 a été supprimée avec succès."
|
||||
|
||||
#: lib/Lutim/Controller.pm:128
|
||||
msgid "The image's delay has been successfully modified"
|
||||
msgstr "Le délai de l’image a été modifié avec succès."
|
||||
|
||||
#: themes/default/templates/index.html.ep:45
|
||||
msgid "The images are encrypted on the server (Lutim does not keep the key)."
|
||||
msgstr "Les images sont chiffrées sur le serveur (Lutim ne stocke pas la clé)."
|
||||
|
||||
#: themes/default/templates/about.html.ep:5
|
||||
msgid "The images you post on Lutim can be stored indefinitely or be deleted at first view or after a delay selected from those proposed."
|
||||
msgstr "Les images déposées sur Lutim peuvent être stockées indéfiniment, ou s’effacer dès le premier affichage ou au bout du délai choisi parmi ceux proposés."
|
||||
|
||||
#. ($c->config->{contact})
|
||||
#: lib/Lutim/Controller.pm:442
|
||||
msgid "There is no more available URL. Retry or contact the administrator. %1"
|
||||
msgstr "Il n’y a plus d’URL disponible. Veuillez réessayer ou contacter l’administrateur. %1."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Tipeee button"
|
||||
msgstr "Bouton Tipeee"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:152 themes/default/templates/raw.html.ep:11
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
|
||||
#: themes/default/templates/index.html.ep:60 themes/default/templates/partial/lutim.js.ep:14
|
||||
msgid "Tweet it!"
|
||||
msgstr "Tweetez !"
|
||||
|
||||
#. ($short)
|
||||
#: lib/Lutim/Controller.pm:162 lib/Lutim/Controller.pm:233
|
||||
msgid "Unable to find the image %1."
|
||||
msgstr "Impossible de trouver l’image %1."
|
||||
|
||||
#: lib/Lutim/Controller.pm:529 lib/Lutim/Controller.pm:574 lib/Lutim/Controller.pm:616 lib/Lutim/Controller.pm:659 lib/Lutim/Controller.pm:671 lib/Lutim/Controller.pm:682 lib/Lutim/Controller.pm:707 lib/Lutim/Plugin/Helpers.pm:57
|
||||
msgid "Unable to find the image: it has been deleted."
|
||||
msgstr "Impossible de trouver l’image : elle a été supprimée."
|
||||
|
||||
#: lib/Lutim/Controller.pm:105
|
||||
msgid "Unable to get counter"
|
||||
msgstr "Impossible de récupérer le compteur"
|
||||
|
||||
#: themes/default/templates/about.html.ep:17
|
||||
msgid "Unlike many image sharing services, you don't give us rights on uploaded images."
|
||||
msgstr "Au contraire de la majorité des services de partages d’image, vous ne nous cédez aucun droit sur les images envoyées."
|
||||
|
||||
#: themes/default/templates/index.html.ep:162 themes/default/templates/index.html.ep:201
|
||||
msgid "Upload an image with its URL"
|
||||
msgstr "Déposer une image par son URL"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:54
|
||||
msgid "Uploaded at"
|
||||
msgstr "Envoyé le"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:6
|
||||
msgid "Uploaded files by days"
|
||||
msgstr "Fichiers envoyés, par jour"
|
||||
|
||||
#. ($c->app->config('contact')
|
||||
#: lib/Lutim/Plugin/Helpers.pm:152
|
||||
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
|
||||
msgstr "L’envoi d’images est actuellement désactivé, veuillez réessayer plus tard ou contacter l’administrateur (%1)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:65 themes/default/templates/index.html.ep:67 themes/default/templates/myfiles.html.ep:51 themes/default/templates/partial/lutim.js.ep:71 themes/default/templates/partial/lutim.js.ep:75
|
||||
msgid "View link"
|
||||
msgstr "Lien d’affichage"
|
||||
|
||||
#: themes/default/templates/about.html.ep:22
|
||||
msgid "What about the software which provides the service?"
|
||||
msgstr "Et à propos du logiciel qui fournit le service ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:3
|
||||
msgid "What is Lutim?"
|
||||
msgstr "Qu’est-ce que Lutim ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:15
|
||||
msgid "Who owns rights on images uploaded on Lutim?"
|
||||
msgstr "Qui possède des droits sur les images envoyées sur Lutim ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:12
|
||||
msgid "Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send an image. Don't panic, it is normally the case of all sites on which you send files!"
|
||||
msgstr "Oui, ça l’est ! Par contre, pour des raisons légales, votre adresse IP sera enregistrée lorsque vous enverrez une image. Ne vous affolez pas, c’est de toute façon normalement le cas de tous les sites sur lesquels vous envoyez des fichiers !"
|
||||
|
||||
#: themes/default/templates/about.html.ep:10
|
||||
msgid "Yes, it is! On the other side, if you want to support the developer, you can do it via <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> or via <a href=\"https://liberapay.com/sky/\">Liberapay</a>."
|
||||
msgstr "Oui, ça l’est ! Par contre, si vous avez envie de soutenir le développeur, vous pouvez faire un microdon avec <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> ou via <a href=\"https://liberapay.com/sky/\">Liberapay</a>."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:6
|
||||
msgid "You asked to download a zip archive for too much files."
|
||||
msgstr "Vous avez demandé de télécharger une archive zip pour trop de fichiers."
|
||||
|
||||
#: themes/default/templates/about.html.ep:8
|
||||
msgid "You can, optionally, request that the image(s) posted on Lutim to be deleted at first view (or download) or after the delay selected from those proposed."
|
||||
msgstr "Vous pouvez, de façon facultative, 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 d’un délai choisi parmi ceux proposés."
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "and on"
|
||||
msgstr "et sur"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "core developer"
|
||||
msgstr "développeur principal"
|
||||
|
||||
#: lib/Lutim.pm:190 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:175 themes/default/templates/index.html.ep:3 themes/default/templates/raw.html.ep:17 themes/default/templates/raw.html.ep:34 themes/default/templates/raw.html.ep:6
|
||||
msgid "no time limit"
|
||||
msgstr "Pas de limitation de durée"
|
||||
|
||||
#: themes/default/templates/about.html.ep:38
|
||||
msgid "occitan translation"
|
||||
msgstr "traduction occitane"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "on"
|
||||
msgstr "sur"
|
||||
|
||||
#: themes/default/templates/about.html.ep:36
|
||||
msgid "spanish translation"
|
||||
msgstr "traduction espagnole"
|
||||
|
||||
#: themes/default/templates/about.html.ep:28
|
||||
msgid "webapp developer"
|
||||
msgstr "développeur de la webapp"
|
||||
486
themes/default/lib/Lutim/I18N/oc.po
Normal file
@@ -0,0 +1,486 @@
|
||||
# Lutim language file
|
||||
# Copyright (C) 2014 Luc Didry
|
||||
# This file is distributed under the same license as the Lutim package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Lutim\n"
|
||||
"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Quentin Pagès\n"
|
||||
"Language-Team: Occitan (http://www.transifex.com/fiat-tux/lutim/language/oc/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: oc\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
|
||||
#. (7)
|
||||
#. (30)
|
||||
#. ($delay)
|
||||
#. (config('max_delay')
|
||||
#: lib/Lutim/Command/cron/stats.pm:149 lib/Lutim/Command/cron/stats.pm:150 lib/Lutim/Command/cron/stats.pm:160 lib/Lutim/Command/cron/stats.pm:161 lib/Lutim/Command/cron/stats.pm:177 lib/Lutim/Command/cron/stats.pm:178 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/for_my_delay.html.ep:13 themes/default/templates/partial/for_my_delay.html.ep:3 themes/default/templates/partial/lutim.js.ep:138 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/partial/lutim.js.ep:148 themes/default/templates/raw.html.ep:19 themes/default/templates/raw.html.ep:20 themes/default/templates/raw.html.ep:36 themes/default/templates/raw.html.ep:37 themes/default/templates/raw.html.ep:8 themes/default/templates/raw.html.ep:9
|
||||
msgid "%1 days"
|
||||
msgstr "%1 jorns"
|
||||
|
||||
#. ($total)
|
||||
#: themes/default/templates/stats.html.ep:2
|
||||
msgid "%1 sent images on this instance from beginning."
|
||||
msgstr "%1 imatges mandats sus aquesta instància dempuèi lo començament."
|
||||
|
||||
#: themes/default/templates/index.html.ep:190
|
||||
msgid "-or-"
|
||||
msgstr "-o-"
|
||||
|
||||
#: lib/Lutim.pm:192 lib/Lutim/Command/cron/stats.pm:151 lib/Lutim/Command/cron/stats.pm:162 lib/Lutim/Command/cron/stats.pm:179 themes/default/templates/index.html.ep:5 themes/default/templates/raw.html.ep:10 themes/default/templates/raw.html.ep:21 themes/default/templates/raw.html.ep:38
|
||||
msgid "1 year"
|
||||
msgstr "1 an"
|
||||
|
||||
#: lib/Lutim.pm:191 lib/Lutim/Command/cron/stats.pm:148 lib/Lutim/Command/cron/stats.pm:159 lib/Lutim/Command/cron/stats.pm:176 themes/default/templates/index.html.ep:4 themes/default/templates/partial/for_my_delay.html.ep:12 themes/default/templates/partial/lutim.js.ep:147 themes/default/templates/raw.html.ep:18 themes/default/templates/raw.html.ep:35 themes/default/templates/raw.html.ep:7
|
||||
msgid "24 hours"
|
||||
msgstr "24 oras"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:57
|
||||
msgid ": Error while trying to get the counter."
|
||||
msgstr " : Error al moment de recuperar lo comptador."
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:144 themes/default/templates/raw.html.ep:3
|
||||
msgid "Active images"
|
||||
msgstr "Imatges actius"
|
||||
|
||||
#: lib/Lutim/Controller.pm:288
|
||||
msgid "An error occured while downloading the image."
|
||||
msgstr "Una error es apareguda pendent lo telecargament de l'imatge."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:2
|
||||
msgid "Archives download"
|
||||
msgstr "Telecargar los archius"
|
||||
|
||||
#: themes/default/templates/about.html.ep:41 themes/default/templates/myfiles.html.ep:64 themes/default/templates/stats.html.ep:25
|
||||
msgid "Back to homepage"
|
||||
msgstr "Tornar a la pagina d'acuèlh"
|
||||
|
||||
#: themes/default/templates/index.html.ep:193 themes/default/templates/index.html.ep:194
|
||||
msgid "Click to open the file browser"
|
||||
msgstr "Clicatz per utilizar lo navigator de fichièr"
|
||||
|
||||
#: themes/default/templates/about.html.ep:30
|
||||
msgid "Contributors"
|
||||
msgstr "Contribudors"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:214 themes/default/templates/partial/lutim.js.ep:268 themes/default/templates/partial/lutim.js.ep:346
|
||||
msgid "Copy all view links to clipboard"
|
||||
msgstr "Copiar totes los ligams de visualizacion dins lo quichapapièrs"
|
||||
|
||||
#: themes/default/templates/index.html.ep:18 themes/default/templates/index.html.ep:36 themes/default/templates/index.html.ep:69 themes/default/templates/index.html.ep:77 themes/default/templates/index.html.ep:85 themes/default/templates/index.html.ep:93 themes/default/templates/myfiles.html.ep:20 themes/default/templates/myfiles.html.ep:38 themes/default/templates/partial/common.js.ep:150 themes/default/templates/partial/lutim.js.ep:105 themes/default/templates/partial/lutim.js.ep:120 themes/default/templates/partial/lutim.js.ep:79 themes/default/templates/partial/lutim.js.ep:91
|
||||
msgid "Copy to clipboard"
|
||||
msgstr "Copiar dins lo quichapapièrs"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:52
|
||||
msgid "Counter"
|
||||
msgstr "Comptador"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:18
|
||||
msgid "Delay repartition chart for disabled images"
|
||||
msgstr "Grafic de despartiment dels delais pels imatges desactivats"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:15
|
||||
msgid "Delay repartition chart for enabled images"
|
||||
msgstr "Grafic de despartiment dels delais pels imatges activats"
|
||||
|
||||
#: themes/default/templates/index.html.ep:115 themes/default/templates/index.html.ep:147 themes/default/templates/index.html.ep:178 themes/default/templates/myfiles.html.ep:53 themes/default/templates/partial/lutim.js.ep:159
|
||||
msgid "Delete at first view?"
|
||||
msgstr "Suprimir al primièr accès ?"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:145 themes/default/templates/raw.html.ep:4
|
||||
msgid "Deleted images"
|
||||
msgstr "Imatges suprimits"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:146 themes/default/templates/raw.html.ep:5
|
||||
msgid "Deleted images in 30 days"
|
||||
msgstr "Imatges per èsser suprimits dins 30 jorns"
|
||||
|
||||
#: themes/default/templates/index.html.ep:98 themes/default/templates/myfiles.html.ep:56 themes/default/templates/partial/common.js.ep:142 themes/default/templates/partial/common.js.ep:145
|
||||
msgid "Deletion link"
|
||||
msgstr "Ligam de supression"
|
||||
|
||||
#: themes/default/templates/gallery.html.ep:6
|
||||
msgid "Download all images"
|
||||
msgstr "Telecargar totes los imatges"
|
||||
|
||||
#: themes/default/templates/index.html.ep:81 themes/default/templates/index.html.ep:83 themes/default/templates/partial/lutim.js.ep:101 themes/default/templates/partial/lutim.js.ep:97
|
||||
msgid "Download link"
|
||||
msgstr "Ligam de telecargament"
|
||||
|
||||
#: themes/default/templates/index.html.ep:28 themes/default/templates/index.html.ep:31 themes/default/templates/myfiles.html.ep:30 themes/default/templates/myfiles.html.ep:33
|
||||
msgid "Download zip link"
|
||||
msgstr "Ligam de telecargament de l'archiu dels imatges"
|
||||
|
||||
#: themes/default/templates/index.html.ep:189
|
||||
msgid "Drag & drop images here"
|
||||
msgstr "Lisatz e depausatz vòstres imatges aquí"
|
||||
|
||||
#: themes/default/templates/about.html.ep:7
|
||||
msgid "Drag and drop an image in the appropriate area or use the traditional way to send files and Lutim will provide you four URLs. One to view the image, an other to directly download it, one you can use on social networks and a last to delete the image when you want."
|
||||
msgstr "Depausatz vòstres imatges dins la zòna prevista per aquò o seleccionatz un fichièr d'un biais classic e Lutim vos donarà quatre URLs en torna. Una per afichar l'imatge, una mai per lo telecargar dirèctament, una per l'utilizar suls malhums socials e una darrièra per suprimir vòstre imatge quand volguèssetz."
|
||||
|
||||
#: themes/default/templates/index.html.ep:150 themes/default/templates/index.html.ep:181
|
||||
msgid "Encrypt the image (Lutim does not keep the key)."
|
||||
msgstr "Chifrar l'imatge (Lutim garda pas la clau)."
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:44
|
||||
msgid "Error while trying to modify the image."
|
||||
msgstr "Una error es apareguda al moment de modificar l'imatge."
|
||||
|
||||
#: themes/default/templates/stats.html.ep:10
|
||||
msgid "Evolution of total files"
|
||||
msgstr "Evolucion del nombre total de fichièrs"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:55
|
||||
msgid "Expires at"
|
||||
msgstr "S'acaba lo"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:50
|
||||
msgid "File name"
|
||||
msgstr "Nom del fichièr"
|
||||
|
||||
#: themes/default/templates/about.html.ep:24
|
||||
msgid "For more details, see the <a href=\"https://framagit.org/luc/lutim\">homepage of the project</a>."
|
||||
msgstr "Per mai de detalhs, consultatz la pagina <a href=\"https://framagit.org/luc/lutim\">Github</a> del projècte."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:55
|
||||
msgid "Fork me!"
|
||||
msgstr "Tustatz-me !"
|
||||
|
||||
#: themes/default/templates/index.html.ep:10 themes/default/templates/index.html.ep:13 themes/default/templates/myfiles.html.ep:12 themes/default/templates/myfiles.html.ep:15
|
||||
msgid "Gallery link"
|
||||
msgstr "Ligam cap a la galariá"
|
||||
|
||||
#: themes/default/templates/partial/common.js.ep:104 themes/default/templates/partial/common.js.ep:87
|
||||
msgid "Hit Ctrl+C, then Enter to copy the short link"
|
||||
msgstr "Fasètz Ctrl+C puèi picatz Entrada per copiar lo ligam"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:50
|
||||
msgid "Homepage"
|
||||
msgstr "Acuèlh"
|
||||
|
||||
#: themes/default/templates/about.html.ep:20
|
||||
msgid "How do you pronounce Lutim?"
|
||||
msgstr "Cossí cal prononciar Lutim ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:6
|
||||
msgid "How does it work?"
|
||||
msgstr "Cossí aquò marcha ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:18
|
||||
msgid "How to report an image?"
|
||||
msgstr "Qué far per senhalar un imatge ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:14
|
||||
msgid "If the files are deleted if you ask it while posting it, their SHA512 footprint are retained."
|
||||
msgstr "Se los fichièrs son ben estats suprimits se o avètz demandat, lors signaturas SHA512 son gardadas."
|
||||
|
||||
#: themes/default/templates/index.html.ep:163 themes/default/templates/index.html.ep:203
|
||||
msgid "Image URL"
|
||||
msgstr "URL de l'imatge"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:143 themes/default/templates/raw.html.ep:2
|
||||
msgid "Image delay"
|
||||
msgstr "Delai de l'imatge"
|
||||
|
||||
#: lib/Lutim/Controller.pm:710
|
||||
msgid "Image not found."
|
||||
msgstr "Imatge pas trobat."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:54
|
||||
msgid "Informations"
|
||||
msgstr "Informacions"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:62
|
||||
msgid "Install webapp"
|
||||
msgstr "Installar la webapp"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:61
|
||||
msgid "Instance's statistics"
|
||||
msgstr "Estatisticas de l'instància"
|
||||
|
||||
#: themes/default/templates/about.html.ep:11
|
||||
msgid "Is it really anonymous?"
|
||||
msgstr "Es vertadièrament anonim ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:9
|
||||
msgid "Is it really free (as in free beer)?"
|
||||
msgstr "Es vertadièrament gratuit ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:21
|
||||
msgid "Juste like you pronounce the French word <a href=\"https://fr.wikipedia.org/wiki/Lutin\">lutin</a> (/ly.tɛ̃/)."
|
||||
msgstr "Òm pronóncia coma en occitan lengadocian, LU-TI-N, amb una M finala que sona N, o coma la paraula francesa lutin (/ly.tɛ̃/)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:153 themes/default/templates/index.html.ep:184
|
||||
msgid "Keep EXIF tags"
|
||||
msgstr "Conservar las donadas EXIF"
|
||||
|
||||
#: themes/default/templates/index.html.ep:118 themes/default/templates/index.html.ep:166 themes/default/templates/index.html.ep:206 themes/default/templates/partial/lutim.js.ep:163
|
||||
msgid "Let's go!"
|
||||
msgstr "Zo !"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Liberapay button"
|
||||
msgstr "Boton Liberapay"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:53
|
||||
msgid "License:"
|
||||
msgstr "Licéncia :"
|
||||
|
||||
#: themes/default/templates/index.html.ep:89 themes/default/templates/index.html.ep:91 themes/default/templates/partial/lutim.js.ep:111 themes/default/templates/partial/lutim.js.ep:115
|
||||
msgid "Link for share on social networks"
|
||||
msgstr "Ligam per partejar suls malhums socials"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:7
|
||||
msgid "Lutim can't zip so many images at once, so it splitted your demand in multiple URLs."
|
||||
msgstr "Lutim pòt pas comprimir tan d'imatge d'un còp, a doncas trocejat vòstra demanda en multiplas URLs"
|
||||
|
||||
#: themes/default/templates/about.html.ep:4
|
||||
msgid "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."
|
||||
msgstr "Lutim es un servici gratuit e anonim d’albergament d’imatges. S’agís tanben del nom del logicial (liure) que fornís aqueste servici."
|
||||
|
||||
#: themes/default/templates/about.html.ep:25
|
||||
msgid "Main developers"
|
||||
msgstr "Desvolopaires de l'aplicacion"
|
||||
|
||||
#: themes/default/templates/index.html.ep:73 themes/default/templates/index.html.ep:75 themes/default/templates/partial/lutim.js.ep:85 themes/default/templates/partial/lutim.js.ep:88
|
||||
msgid "Markdown syntax"
|
||||
msgstr "Sintaxi Markdown"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:60 themes/default/templates/myfiles.html.ep:2
|
||||
msgid "My images"
|
||||
msgstr "Mos imatges"
|
||||
|
||||
#: themes/default/templates/partial/myfiles.js.ep:19
|
||||
msgid "No limit"
|
||||
msgstr "Pas cap de data d'expiracion"
|
||||
|
||||
#: themes/default/templates/index.html.ep:165 themes/default/templates/index.html.ep:198
|
||||
msgid "Only images are allowed"
|
||||
msgstr "Solament son acceptats los imatges"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:6
|
||||
msgid "Only the images sent with this browser will be listed here. The informations are stored in localStorage: if you delete your localStorage data, you'll loose this informations."
|
||||
msgstr "Solament los imatges mandats amb aqueste navigador seràn listats aquí. Las informacions son gardadas en localStorage : se escafatz vòstras donadas localStorage, perdretz aquelas informacions."
|
||||
|
||||
#: themes/default/templates/about.html.ep:16
|
||||
msgid "Only the uploader! (well, only if he's the only owner of the images' rights before the upload)"
|
||||
msgstr "Solament lo qu'a mandat ! (ben, solament se ten los dreits exclusius dels imatges abans de los mandar)"
|
||||
|
||||
#: themes/default/templates/zip.html.ep:12
|
||||
msgid "Please click on each URL to download the different zip files."
|
||||
msgstr "Mercés de clicar sus cada URL per telecargar los diferents archius ZIP."
|
||||
|
||||
#. (config('contact')
|
||||
#: themes/default/templates/about.html.ep:19
|
||||
msgid "Please contact the administrator: %1"
|
||||
msgstr "Mercés de contactar l'administrator : %1"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:22
|
||||
msgid "Raw stats"
|
||||
msgstr "Estatisticas brutas"
|
||||
|
||||
#: themes/default/templates/index.html.ep:158
|
||||
msgid "Send an image"
|
||||
msgstr "Mandar un imatge"
|
||||
|
||||
#: themes/default/templates/partial/lutim.js.ep:20
|
||||
msgid "Share it!"
|
||||
msgstr "Partejatz-lo !"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:56
|
||||
msgid "Share on Twitter"
|
||||
msgstr "Partejar sus Twitter"
|
||||
|
||||
#: themes/default/templates/index.html.ep:133 themes/default/templates/partial/lutim.js.ep:174
|
||||
msgid "Something bad happened"
|
||||
msgstr "Un problèma es aparegut"
|
||||
|
||||
#. ($c->config('contact')
|
||||
#: lib/Lutim/Controller.pm:717
|
||||
msgid "Something went wrong when creating the zip file. Try again later or contact the administrator (%1)."
|
||||
msgstr "Quicòm a trucat pendent la creacion de l'archiu. Mercés de tornar ensajar pus tard o de contactar l'administrator (%1)."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:58
|
||||
msgid "Support the author on Liberapay"
|
||||
msgstr "Sostenir l'autor sus Liberapay"
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Support the author on Tipeee"
|
||||
msgstr "Sostenir l'autor sus Tipeee"
|
||||
|
||||
#: themes/default/templates/about.html.ep:13
|
||||
msgid "The IP address of the image's sender is retained for a delay which depends of the administrator's choice (for the official instance, which is located in France, it's one year)."
|
||||
msgstr "L’IP de la persona que mandèt l'imatge es gardada pendent un delai que depend de l'administrator de l'instància (per l'instància oficiala que lo servidor es en França, es un delai d'un an)."
|
||||
|
||||
#: themes/default/templates/about.html.ep:23
|
||||
msgid "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."
|
||||
msgstr "Lo logicial Lutim es un <a href=\"https://oc.wikipedia.org/wiki/Logicial_liure\">logicial liure</a>, que permet de lo telecargar e de l’installar sus vòstre pròpri servidor. Gaitatz l’<a href=\"https://www.gnu.org/licenses/agpl-3.0.html\">AGPL</a> per veire que son vòstres dreits"
|
||||
|
||||
#: lib/Lutim/Controller.pm:307
|
||||
msgid "The URL is not valid."
|
||||
msgstr "L'URL n'es pas valida."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:16
|
||||
msgid "The automatic download process will open a tab in your browser for each link. You need to allow popups for Lutim."
|
||||
msgstr "Lo processús automatic de telecargament obrirà un onglet dins lo navigato per cada ligam. Vos cal autorizar las popups per Lutim."
|
||||
|
||||
#: lib/Lutim/Controller.pm:120 lib/Lutim/Controller.pm:188
|
||||
msgid "The delete token is invalid."
|
||||
msgstr "Lo geton de supression es invalida."
|
||||
|
||||
#. ($upload->filename)
|
||||
#: lib/Lutim/Controller.pm:445
|
||||
msgid "The file %1 is not an image."
|
||||
msgstr "Lo fichièr %1 es pas un imatge."
|
||||
|
||||
#. ($tx->res->max_message_size)
|
||||
#. ($c->req->max_message_size)
|
||||
#. (config('max_file_size')
|
||||
#: lib/Lutim/Controller.pm:271 lib/Lutim/Controller.pm:340 themes/default/templates/partial/lutim.js.ep:240
|
||||
msgid "The file exceed the size limit (%1)"
|
||||
msgstr "Lo fichièr depassa lo limit de talha (%1)"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:12
|
||||
msgid "The graph's datas are not updated in real-time."
|
||||
msgstr "Las donadas del grafic son pas mesas a jorn en temps real."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:190
|
||||
msgid "The image %1 has already been deleted."
|
||||
msgstr "L'imatge %1 es ja estat suprimit."
|
||||
|
||||
#. ($image->filename)
|
||||
#: lib/Lutim/Controller.pm:199 lib/Lutim/Controller.pm:204
|
||||
msgid "The image %1 has been successfully deleted"
|
||||
msgstr "L'imatge %1 es estat suprimit amb succès."
|
||||
|
||||
#: lib/Lutim/Controller.pm:128
|
||||
msgid "The image's delay has been successfully modified"
|
||||
msgstr "Lo delai de l'imatge es plan estat modificat."
|
||||
|
||||
#: themes/default/templates/index.html.ep:45
|
||||
msgid "The images are encrypted on the server (Lutim does not keep the key)."
|
||||
msgstr "Los imatges son chifrats sul servidor (Lutim garda pas la clau)."
|
||||
|
||||
#: themes/default/templates/about.html.ep:5
|
||||
msgid "The images you post on Lutim can be stored indefinitely or be deleted at first view or after a delay selected from those proposed."
|
||||
msgstr "Los imatges depausats sus Lutim pòdon èsser gardats sens fin, o s’escafar tre lo primièr afichatge o al cap d'un delai causit entre los prepausats."
|
||||
|
||||
#. ($c->config->{contact})
|
||||
#: lib/Lutim/Controller.pm:442
|
||||
msgid "There is no more available URL. Retry or contact the administrator. %1"
|
||||
msgstr "I a pas mai d'URL disponibla. Mercés de tornar ensajar o de contactar l'administrator. %1."
|
||||
|
||||
#: themes/default/templates/layouts/default.html.ep:57
|
||||
msgid "Tipeee button"
|
||||
msgstr "Boton Tipeee"
|
||||
|
||||
#: lib/Lutim/Command/cron/stats.pm:152 themes/default/templates/raw.html.ep:11
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
|
||||
#: themes/default/templates/index.html.ep:60 themes/default/templates/partial/lutim.js.ep:14
|
||||
msgid "Tweet it!"
|
||||
msgstr "Tweetejatz-lo !"
|
||||
|
||||
#. ($short)
|
||||
#: lib/Lutim/Controller.pm:162 lib/Lutim/Controller.pm:233
|
||||
msgid "Unable to find the image %1."
|
||||
msgstr "Impossible de trobar l'imatge %1."
|
||||
|
||||
#: lib/Lutim/Controller.pm:529 lib/Lutim/Controller.pm:574 lib/Lutim/Controller.pm:616 lib/Lutim/Controller.pm:659 lib/Lutim/Controller.pm:671 lib/Lutim/Controller.pm:682 lib/Lutim/Controller.pm:707 lib/Lutim/Plugin/Helpers.pm:57
|
||||
msgid "Unable to find the image: it has been deleted."
|
||||
msgstr "Impossible de trobar l'imatge : es estat suprimit."
|
||||
|
||||
#: lib/Lutim/Controller.pm:105
|
||||
msgid "Unable to get counter"
|
||||
msgstr "Impossible de recuperar lo comptador"
|
||||
|
||||
#: themes/default/templates/about.html.ep:17
|
||||
msgid "Unlike many image sharing services, you don't give us rights on uploaded images."
|
||||
msgstr "A l'invèrse de la màger part dels servicis de partiment d'imatge, daissatz pas cap de dreit suls imatges que mandatz."
|
||||
|
||||
#: themes/default/templates/index.html.ep:162 themes/default/templates/index.html.ep:201
|
||||
msgid "Upload an image with its URL"
|
||||
msgstr "Depausar un imatge per son URL"
|
||||
|
||||
#: themes/default/templates/myfiles.html.ep:54
|
||||
msgid "Uploaded at"
|
||||
msgstr "Mandat lo"
|
||||
|
||||
#: themes/default/templates/stats.html.ep:6
|
||||
msgid "Uploaded files by days"
|
||||
msgstr "Fichièrs mandats per jorn"
|
||||
|
||||
#. ($c->app->config('contact')
|
||||
#: lib/Lutim/Plugin/Helpers.pm:152
|
||||
msgid "Uploading is currently disabled, please try later or contact the administrator (%1)."
|
||||
msgstr "La mesa en linha es desactivada pel moment, mercés de tornar ensajar mai tard o de contactar l'administrator (%1)."
|
||||
|
||||
#: themes/default/templates/index.html.ep:65 themes/default/templates/index.html.ep:67 themes/default/templates/myfiles.html.ep:51 themes/default/templates/partial/lutim.js.ep:71 themes/default/templates/partial/lutim.js.ep:75
|
||||
msgid "View link"
|
||||
msgstr "Ligam d'afichatge"
|
||||
|
||||
#: themes/default/templates/about.html.ep:22
|
||||
msgid "What about the software which provides the service?"
|
||||
msgstr "E a prepaus del logicial que fornís lo servici ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:3
|
||||
msgid "What is Lutim?"
|
||||
msgstr "Qu’es aquò Lutim ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:15
|
||||
msgid "Who owns rights on images uploaded on Lutim?"
|
||||
msgstr "Qual a los dreits suls imatges mandats sus Lutim ?"
|
||||
|
||||
#: themes/default/templates/about.html.ep:12
|
||||
msgid "Yes, it is! On the other side, for legal reasons, your IP address will be stored when you send an image. Don't panic, it is normally the case of all sites on which you send files!"
|
||||
msgstr "Òc, es aquò ! Al contrari, per de rasons legalas, vòstra adreça IP serà enregistrada quand mandaretz un imatge. Perdetz pas lo cap, normalament es çò normal pels demai dels sites suls quals mandatz de fichièrs !"
|
||||
|
||||
#: themes/default/templates/about.html.ep:10
|
||||
msgid "Yes, it is! On the other side, if you want to support the developer, you can do it via <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> or via <a href=\"https://liberapay.com/sky/\">Liberapay</a>."
|
||||
msgstr "Òc, o es ! Al contrari, s'avètz enveja de sosténer lo desvolopaire, podètz far un microdon amb <a href=\"https://www.tipeee.com/fiat-tux\">Tipeee</a> o via <a href=\"https://liberapay.com/sky/\">Liberapay</a>."
|
||||
|
||||
#: themes/default/templates/zip.html.ep:6
|
||||
msgid "You asked to download a zip archive for too much files."
|
||||
msgstr "Avètz demandat de telecargar tròp d'imatges d'un còp dins un archiu ZIP."
|
||||
|
||||
#: themes/default/templates/about.html.ep:8
|
||||
msgid "You can, optionally, request that the image(s) posted on Lutim to be deleted at first view (or download) or after the delay selected from those proposed."
|
||||
msgstr "Podètz, d'un biais facultatiu, demandar que l'imatge o los imatges depausats sus Lutim sián suprimits aprèp lor primièr afichatge (o telecargament) o al cap d'un delai causit entre las prepausadas."
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "and on"
|
||||
msgstr "e sus"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "core developer"
|
||||
msgstr "desvolopaire màger"
|
||||
|
||||
#: lib/Lutim.pm:190 lib/Lutim/Command/cron/stats.pm:147 lib/Lutim/Command/cron/stats.pm:158 lib/Lutim/Command/cron/stats.pm:175 themes/default/templates/index.html.ep:3 themes/default/templates/raw.html.ep:17 themes/default/templates/raw.html.ep:34 themes/default/templates/raw.html.ep:6
|
||||
msgid "no time limit"
|
||||
msgstr "Pas cap de limitacion de durada"
|
||||
|
||||
#: themes/default/templates/about.html.ep:38
|
||||
msgid "occitan translation"
|
||||
msgstr "traduccion en occitan"
|
||||
|
||||
#: themes/default/templates/about.html.ep:27
|
||||
msgid "on"
|
||||
msgstr "sus"
|
||||
|
||||
#: themes/default/templates/about.html.ep:36
|
||||
msgid "spanish translation"
|
||||
msgstr "traduccion en espanhòl"
|
||||
|
||||
#: themes/default/templates/about.html.ep:28
|
||||
msgid "webapp developer"
|
||||
msgstr "desvolopaire de la webapp"
|
||||
14
themes/default/public/css/bootstrap.min.css
vendored
Normal file
15
themes/default/public/css/fontello-codes.css
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
.icon-ok:before { content: '\e800'; } /* '' */
|
||||
.icon-eye:before { content: '\e801'; } /* '' */
|
||||
.icon-download:before { content: '\e802'; } /* '' */
|
||||
.icon-share:before { content: '\e803'; } /* '' */
|
||||
.icon-trash:before { content: '\e804'; } /* '' */
|
||||
.icon-bitcoin:before { content: '\e805'; } /* '' */
|
||||
.icon-git:before { content: '\e806'; } /* '' */
|
||||
.icon-twitter:before { content: '\e807'; } /* '' */
|
||||
.icon-clipboard:before { content: '\e808'; } /* '' */
|
||||
.icon-spinner:before { content: '\e809'; } /* '' */
|
||||
.icon-flattr:before { content: '\e80a'; } /* '' */
|
||||
.icon-cancel:before { content: '\e80b'; } /* '' */
|
||||
.icon-picture:before { content: '\e80c'; } /* '' */
|
||||
.icon-file-archive:before { content: '\e80d'; } /* '' */
|
||||
68
themes/default/public/css/fontello-embedded.css
vendored
Normal file
15
themes/default/public/css/fontello-ie7-codes.css
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
|
||||
.icon-ok { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-share { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-trash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-git { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-clipboard { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-flattr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-file-archive { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
26
themes/default/public/css/fontello-ie7.css
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
[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-ok { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-eye { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-download { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-share { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-trash { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-bitcoin { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-git { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-twitter { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-clipboard { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-spinner { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-flattr { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-cancel { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-picture { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
.icon-file-archive { *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = ' '); }
|
||||
71
themes/default/public/css/fontello.css
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
@font-face {
|
||||
font-family: 'fontello';
|
||||
src: url('../font/fontello.eot?79499210');
|
||||
src: url('../font/fontello.eot?79499210#iefix') format('embedded-opentype'),
|
||||
url('../font/fontello.woff2?79499210') format('woff2'),
|
||||
url('../font/fontello.woff?79499210') format('woff'),
|
||||
url('../font/fontello.ttf?79499210') format('truetype'),
|
||||
url('../font/fontello.svg?79499210#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?79499210#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%; */
|
||||
|
||||
/* Font smoothing. That was taken from TWBS */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
/* Uncomment for 3D effect */
|
||||
/* text-shadow: 1px 1px 1px rgba(127, 127, 127, 0.3); */
|
||||
}
|
||||
|
||||
.icon-ok:before { content: '\e800'; } /* '' */
|
||||
.icon-eye:before { content: '\e801'; } /* '' */
|
||||
.icon-download:before { content: '\e802'; } /* '' */
|
||||
.icon-share:before { content: '\e803'; } /* '' */
|
||||
.icon-trash:before { content: '\e804'; } /* '' */
|
||||
.icon-bitcoin:before { content: '\e805'; } /* '' */
|
||||
.icon-git:before { content: '\e806'; } /* '' */
|
||||
.icon-twitter:before { content: '\e807'; } /* '' */
|
||||
.icon-clipboard:before { content: '\e808'; } /* '' */
|
||||
.icon-spinner:before { content: '\e809'; } /* '' */
|
||||
.icon-flattr:before { content: '\e80a'; } /* '' */
|
||||
.icon-cancel:before { content: '\e80b'; } /* '' */
|
||||
.icon-picture:before { content: '\e80c'; } /* '' */
|
||||
.icon-file-archive:before { content: '\e80d'; } /* '' */
|
||||
6
themes/default/public/css/hennypenny.css
Normal file
@@ -0,0 +1,6 @@
|
||||
@font-face {
|
||||
font-family: 'Henny_Penny';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Henny Penny'), local('HennyPenny-Regular'), url(../font/hennypenny.ttf) format('truetype');
|
||||
}
|
||||
85
themes/default/public/css/lutim.css
Normal file
@@ -0,0 +1,85 @@
|
||||
@media (max-width: 767px) {
|
||||
body {
|
||||
padding-top: 5px;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
body {
|
||||
padding-top: 40px;
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 15px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.jsonly {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.thumbnail {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.hennypenny {
|
||||
font-family: 'Henny_Penny', cursive;
|
||||
font-size: 42px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
margin-right: 10px;
|
||||
}
|
||||
label.always-encrypt {
|
||||
display: none;
|
||||
}
|
||||
.link_nocol,
|
||||
.link_nocol:hover{
|
||||
color: #000000;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#install-app img {
|
||||
height: 22px;
|
||||
}
|
||||
#install-app {
|
||||
display: none;
|
||||
}
|
||||
.form-control[readonly] {
|
||||
background-color: #FFFFFF;
|
||||
}
|
||||
.alert .form-group {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
#copy-all {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
#gallery-url {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.adjust-addon {
|
||||
width: 42px;
|
||||
}
|
||||
.adjust-addon .btn {
|
||||
width: 43px;
|
||||
}
|
||||
#tipeee-img {
|
||||
margin-top: -4px;
|
||||
}
|
||||
#liberapay-img {
|
||||
height: 21px;
|
||||
line-height: 21px;
|
||||
margin-top: -5.33333px;
|
||||
}
|
||||
.pasteZone {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100px;
|
||||
z-index: -999;
|
||||
height: 10000vh;
|
||||
width: 0;
|
||||
display: hidden;
|
||||
}
|
||||
31
themes/default/public/css/markdown.css
Normal file
@@ -0,0 +1,31 @@
|
||||
@font-face {
|
||||
font-family: 'markdown';
|
||||
src:url('../../font/markdown.eot?-6fnbp5');
|
||||
src:url('../../font/markdown.eot?#iefix-6fnbp5') format('embedded-opentype'),
|
||||
url('../../font/markdown.woff?-6fnbp5') format('woff'),
|
||||
url('../../font/markdown.ttf?-6fnbp5') format('truetype'),
|
||||
url('../../font/markdown.svg?-6fnbp5#markdown') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
[class^="markdown-"], [class*=" markdown-"] {
|
||||
font-family: 'markdown';
|
||||
speak: none;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-variant: normal;
|
||||
text-transform: none;
|
||||
line-height: 1;
|
||||
|
||||
/* Better Font Rendering =========== */
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.markdown-mark:before {
|
||||
content: "\e600";
|
||||
}
|
||||
.markdown-mark-solid:before {
|
||||
content: "\e601";
|
||||
}
|
||||
2
themes/default/public/css/morris-0.4.3.min.css
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
.morris-hover{position:absolute;z-index:1000;}.morris-hover.morris-default-style{border-radius:10px;padding:6px;color:#666;background:rgba(255, 255, 255, 0.8);border:solid 2px rgba(230, 230, 230, 0.8);font-family:sans-serif;font-size:12px;text-align:center;}.morris-hover.morris-default-style .morris-hover-row-label{font-weight:bold;margin:0.25em 0;}
|
||||
.morris-hover.morris-default-style .morris-hover-point{white-space:nowrap;margin:0.1em 0;}
|
||||
@@ -26,6 +26,18 @@
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
@media (max-width:768px){
|
||||
.uploader div.browser label {
|
||||
max-width:95%;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:768px){
|
||||
.uploader div.browser label {
|
||||
width:300px;
|
||||
}
|
||||
}
|
||||
|
||||
.uploader div.browser label {
|
||||
background-color: #5a7bc2;
|
||||
padding: 5px 15px;
|
||||
@@ -38,7 +50,6 @@
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
width: 300px;
|
||||
margin: 20px auto 0px auto;
|
||||
|
||||
box-shadow: 2px 2px 2px #888888;
|
||||
57
themes/default/public/font/LICENSE.txt
Normal file
@@ -0,0 +1,57 @@
|
||||
Font license info
|
||||
|
||||
|
||||
## Font Awesome
|
||||
|
||||
Copyright (C) 2012 by Dave Gandy
|
||||
|
||||
Author: Dave Gandy
|
||||
License: SIL ()
|
||||
Homepage: http://fortawesome.github.com/Font-Awesome/
|
||||
|
||||
|
||||
## Typicons
|
||||
|
||||
(c) Stephen Hutchings 2012
|
||||
|
||||
Author: Stephen Hutchings
|
||||
License: SIL (http://scripts.sil.org/OFL)
|
||||
Homepage: http://typicons.com/
|
||||
|
||||
|
||||
## MFG Labs
|
||||
|
||||
Copyright (C) 2012 by Daniel Bruce
|
||||
|
||||
Author: MFG Labs
|
||||
License: SIL (http://scripts.sil.org/OFL)
|
||||
Homepage: http://www.mfglabs.com/
|
||||
|
||||
|
||||
## Zocial
|
||||
|
||||
Copyright (C) 2012 by Sam Collins
|
||||
|
||||
Author: Sam Collins
|
||||
License: MIT (http://opensource.org/licenses/mit-license.php)
|
||||
Homepage: http://zocial.smcllns.com/
|
||||
|
||||
|
||||
## Elusive
|
||||
|
||||
Copyright (C) 2013 by Aristeides Stathopoulos
|
||||
|
||||
Author: Aristeides Stathopoulos
|
||||
License: SIL (http://scripts.sil.org/OFL)
|
||||
Homepage: http://aristeides.com/
|
||||
|
||||
|
||||
## Web Symbols
|
||||
|
||||
Copyright (c) 2011 by Just Be Nice studio. All rights reserved.
|
||||
|
||||
Author: Just Be Nice studio
|
||||
License: SIL (http://scripts.sil.org/OFL)
|
||||
Homepage: http://www.justbenicestudio.com/
|
||||
|
||||
|
||||
BIN
themes/default/public/font/fontello.eot
Normal file
38
themes/default/public/font/fontello.svg
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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) 2016 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="ok" unicode="" d="M932 534q0-22-15-38l-404-404-76-76q-16-15-38-15t-38 15l-76 76-202 202q-15 16-15 38t15 38l76 76q16 16 38 16t38-16l164-165 366 367q16 16 38 16t38-16l76-76q15-16 15-38z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="eye" unicode="" d="M929 314q-85 132-213 197 34-58 34-125 0-104-73-177t-177-73-177 73-73 177q0 67 34 125-128-65-213-197 75-114 187-182t242-68 242 68 187 182z m-402 215q0 11-8 19t-19 7q-70 0-120-50t-50-119q0-11 8-19t19-8 19 8 8 19q0 48 34 82t82 34q11 0 19 8t8 19z m473-215q0-19-11-38-78-129-210-206t-279-77-279 77-210 206q-11 19-11 38t11 39q78 128 210 205t279 78 279-78 210-205q11-20 11-39z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="download" unicode="" d="M714 100q0 15-10 25t-25 11-26-11-10-25 10-25 26-11 25 11 10 25z m143 0q0 15-10 25t-26 11-25-11-10-25 10-25 25-11 26 11 10 25z m72 125v-179q0-22-16-37t-38-16h-821q-23 0-38 16t-16 37v179q0 22 16 38t38 16h259l75-76q33-32 76-32t76 32l76 76h259q22 0 38-16t16-38z m-182 318q10-23-8-40l-250-250q-10-10-25-10t-25 10l-250 250q-17 17-8 40 10 21 33 21h143v250q0 15 11 25t25 11h143q14 0 25-11t10-25v-250h143q24 0 33-21z" horiz-adv-x="928.6" />
|
||||
|
||||
<glyph glyph-name="share" unicode="" d="M679 279q74 0 126-53t52-126-52-126-126-53-127 53-52 126q0 7 1 19l-201 100q-51-48-121-48-75 0-127 53t-52 126 52 126 127 53q70 0 121-48l201 100q-1 12-1 19 0 74 52 126t127 53 126-53 52-126-52-126-126-53q-71 0-122 48l-201-100q1-12 1-19t-1-19l201-100q51 48 122 48z" horiz-adv-x="857.1" />
|
||||
|
||||
<glyph glyph-name="trash" unicode="" d="M286 439v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m143 0v-321q0-8-5-13t-13-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q8 0 13-5t5-13z m142 0v-321q0-8-5-13t-12-5h-36q-8 0-13 5t-5 13v321q0 8 5 13t13 5h36q7 0 12-5t5-13z m72-404v529h-500v-529q0-12 4-22t8-15 6-5h464q2 0 6 5t8 15 4 22z m-375 601h250l-27 65q-4 5-9 6h-177q-6-1-10-6z m518-18v-36q0-8-5-13t-13-5h-54v-529q0-46-26-80t-63-34h-464q-37 0-63 33t-27 79v531h-53q-8 0-13 5t-5 13v36q0 8 5 13t13 5h172l39 93q9 21 31 35t44 15h178q22 0 44-15t30-35l39-93h173q8 0 13-5t5-13z" horiz-adv-x="785.7" />
|
||||
|
||||
<glyph glyph-name="bitcoin" unicode="" d="M651 493q10-102-73-144 65-16 98-58t25-119q-4-40-18-70t-36-49-54-33-68-19-81-9v-142h-86v140q-45 0-68 1v-141h-86v142q-10 0-30 1t-31 0h-112l18 102h62q27 0 32 28v225h9q-4 0-9 0v160q-7 38-50 38h-62v92l119-1q35 0 54 1v141h86v-138q45 1 68 1v137h86v-141q44-4 78-13t63-25 46-43 20-64z m-120-304q0 20-8 35t-21 26-32 17-36 10-42 5-38 2-36 0-27-1v-189q5 0 21 0t27 0 29 1 33 2 32 5 31 8 26 11 22 17 14 22 5 29z m-39 265q0 19-7 33t-17 23-27 16-31 9-34 5-33 1-30 0-22-1v-171q3 0 20 0t26 0 27 1 31 3 29 6 27 10 21 15 15 22 5 28z" horiz-adv-x="714.3" />
|
||||
|
||||
<glyph glyph-name="git" unicode="" d="M332 5q0 56-92 56-88 0-88-58 0-57 96-57 84 0 84 59z m-33 421q0 35-17 57t-49 23q-69 0-69-81 0-75 69-75 66 0 66 76z m150 181v-112q-20-7-44-13 9-24 9-47 0-70-41-120t-110-63q-22-5-33-15t-11-33q0-17 13-28t32-18 44-12 48-15 44-21 32-35 13-55q0-170-203-170-38 0-72 7t-65 23-49 46-18 71q0 92 102 125v3q-38 22-38 70 0 61 35 76v3q-40 13-66 60t-27 92q0 78 53 130t131 51q54 0 100-26 54 0 121 26z m178-491h-124q2 25 2 74v340q0 53-2 72h124q-3-19-3-70v-342q0-49 3-74z m335 124v-110q-40-22-97-22-35 0-60 12t-39 27-22 44-10 51-2 58v196h1v2q-4 0-11 0t-10 1q-12 0-33-3v106h54v42q0 30-4 50h127q-3-23-3-92h95v-106q-8 0-24 1t-24 1h-47v-204q0-73 48-73 34 0 61 19z m-321 528q0-32-22-57t-54-24q-32 0-54 24t-23 57q0 33 22 57t55 25q33 0 54-25t22-57z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="twitter" unicode="" d="M904 622q-37-54-90-93 0-8 0-23 0-73-21-145t-64-139-103-117-144-82-181-30q-151 0-276 81 19-2 43-2 126 0 224 77-59 1-105 36t-64 89q19-3 34-3 24 0 48 6-63 13-104 62t-41 115v2q38-21 82-23-37 25-59 64t-22 86q0 49 25 91 68-83 164-133t208-55q-5 21-5 41 0 75 53 127t127 53q79 0 132-57 61 12 114 44-20-64-79-100 52 6 104 28z" horiz-adv-x="928.6" />
|
||||
|
||||
<glyph glyph-name="clipboard" unicode="" d="M678 819q65 0 110-46t46-110l0-625q0-65-46-111t-110-46l-522 0q-65 0-110 46t-46 111l0 625q0 65 46 110t110 46l522 0z m-418-104l0-52q0-21 16-37t37-16l208 0q22 0 37 16t15 37l0 52-313 0z m469-677l0 625q0 21-15 37t-36 15l-53 0 0-52q0-43-30-73t-74-31l-208 0q-43 0-74 31t-30 73l0 52-53 0q-21 0-37-15t-15-37l0-625q0-21 15-37t37-16l522 0q21 0 36 16t15 37z m-104 52l-416 0q-26 0-26 25 0 12 7 19t19 8l416 0q11 0 19-8t7-19q0-25-26-25z m0 157l-416 0q-11 0-19 7t-7 19q0 25 26 25l416 0q26 0 26-25 0-11-7-19t-19-7z m0 156l-416 0q-26 0-26 25 0 11 7 19t19 7l416 0q11 0 19-7t7-19q0-25-26-25z" horiz-adv-x="834" />
|
||||
|
||||
<glyph glyph-name="spinner" unicode="" d="M469 614v204q129 0 237-61t169-170 62-237h-204q0 72-36 133t-95 96-133 35z" horiz-adv-x="937.5" />
|
||||
|
||||
<glyph glyph-name="flattr" unicode="" d="M0-37l0 514q0 179 85 278t259 99l548 0q-5-5-52-53t-100-101-109-109-95-93-42-37q-15 0-15 16l0 156-48 0q-59 0-94-6t-63-26-39-57-12-96l0-262z m67-117q5 5 53 53t100 101 109 110 95 93 41 36q15 0 15-16l0-156 48 0q116 0 162 36t45 149l0 262 224 223 0-514q0-179-84-278t-260-99l-548 0z" horiz-adv-x="959" />
|
||||
|
||||
<glyph glyph-name="cancel" unicode="" d="M0 71l279 279-279 279 221 221 279-279 279 279 221-221-279-279 279-279-221-221-279 279-279-279z" horiz-adv-x="1000" />
|
||||
|
||||
<glyph glyph-name="picture" unicode="" d="M1360 849v-1000h-1360v1000h1360z m-1240-880h1120v760h-1120v-760z m1000 560q0-33-23-56t-57-24-56 24-24 56 24 57 56 23 57-23 23-57z m43-473q2-1 1-4t-4-3h-956q-4 0-4 4v2q18 36 135 280t144 299q1 2 4 3t3-2l311-386 152 122h7l1-2q39-50 102-155t104-158z" horiz-adv-x="1360" />
|
||||
|
||||
<glyph glyph-name="file-archive" unicode="" d="M357 636v71h-71v-71h71z m72-72v72h-72v-72h72z m-72-71v71h-71v-71h71z m72-72v72h-72v-72h72z m390 217q16-16 27-42t11-50v-642q0-23-15-38t-38-16h-750q-23 0-38 16t-16 38v892q0 23 16 38t38 16h500q22 0 49-11t42-27z m-248 136v-210h210q-5 16-12 23l-175 175q-6 7-23 12z m215-853v572h-232q-23 0-38 15t-16 38v233h-71v-72h-72v72h-286v-858h715z m-350 403l60-195q4-15 4-29 0-46-40-77t-103-30-102 30-41 77q0 14 5 29 12 35 67 221v71h71v-71h44q13 0 22-7t13-19z m-79-260q30 0 51 11t21 25-21 25-51 11-50-11-21-25 21-25 50-11z" horiz-adv-x="857.1" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.4 KiB |
BIN
themes/default/public/font/fontello.ttf
Normal file
BIN
themes/default/public/font/fontello.woff
Normal file
BIN
themes/default/public/font/fontello.woff2
Normal file
BIN
themes/default/public/font/hennypenny.ttf
Normal file
BIN
themes/default/public/font/markdown.eot
Normal file
31
themes/default/public/font/markdown.svg
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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>
|
||||
<json>
|
||||
{
|
||||
"fontFamily": "markdown",
|
||||
"majorVersion": 1,
|
||||
"minorVersion": 0,
|
||||
"fontURL": "https://github.com/dcurtis/markdown-mark",
|
||||
"designer": "Dustin Curtis",
|
||||
"designerURL": "http://twitter.com/dcurtis",
|
||||
"license": "CC0 UNIVERSAL PUBLIC DOMAIN DEDICATION LICENSE",
|
||||
"licenseURL": "https://raw.githubusercontent.com/dcurtis/markdown-mark/master/LICENSE",
|
||||
"version": "Version 1.0",
|
||||
"fontId": "markdown",
|
||||
"psName": "markdown",
|
||||
"subFamily": "Regular",
|
||||
"fullName": "markdown",
|
||||
"description": "Generated by IcoMoon"
|
||||
}
|
||||
</json>
|
||||
</metadata>
|
||||
<defs>
|
||||
<font id="markdown" horiz-adv-x="512">
|
||||
<font-face units-per-em="512" ascent="480" descent="-32" />
|
||||
<missing-glyph horiz-adv-x="512" />
|
||||
<glyph unicode=" " d="" horiz-adv-x="256" />
|
||||
<glyph unicode="" d="M120 88v272h80l80-100 80 100h80v-272h-80v156l-80-100-80 100v-156h-80zM620 88l-120 132h80v140h80v-140h80l-120-132zM0 428.021v-408.042c0-28.714 23.299-51.979 52.029-51.979h727.943c28.727 0 52.029 23.266 52.029 51.979v408.042c0 28.714-23.299 51.979-52.029 51.979h-727.943c-28.727 0-52.029-23.266-52.029-51.979zM779.971 440c6.651 0 12.029-5.369 12.029-11.979v-408.042c0-6.608-5.379-11.979-12.029-11.979h-727.943c-6.651 0-12.029 5.369-12.029 11.979v408.042c0 6.608 5.379 11.979 12.029 11.979h727.943z" horiz-adv-x="832" />
|
||||
<glyph unicode="" d="M0 428.021v-408.042c0-28.714 23.299-51.979 52.029-51.979h727.943c28.727 0 52.029 23.266 52.029 51.979v408.042c0 28.714-23.299 51.979-52.029 51.979h-727.943c-28.727 0-52.029-23.266-52.029-51.979zM120 88v272h80l80-100 80 100h80v-272h-80v156l-80-100-80 100v-156h-80zM620 88l-120 132h80v140h80v-140h80l-120-132z" horiz-adv-x="832" />
|
||||
</font></defs></svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
BIN
themes/default/public/font/markdown.ttf
Normal file
BIN
themes/default/public/font/markdown.woff
Normal file
1354
themes/default/public/gallery/css/unite-gallery.css
Normal file
BIN
themes/default/public/gallery/images/button-close.png
Normal file
|
After Width: | Height: | Size: 7.0 KiB |
BIN
themes/default/public/gallery/images/cover-grid.png
Normal file
|
After Width: | Height: | Size: 933 B |
BIN
themes/default/public/gallery/images/icon-link32.png
Normal file
|
After Width: | Height: | Size: 909 B |
BIN
themes/default/public/gallery/images/icon-play32.png
Normal file
|
After Width: | Height: | Size: 688 B |
BIN
themes/default/public/gallery/images/icon-zoom32.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
themes/default/public/gallery/images/lightbox-arrow-left.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
themes/default/public/gallery/images/lightbox-arrow-right.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
BIN
themes/default/public/gallery/images/lightbox-icon-close.png
Normal file
|
After Width: | Height: | Size: 946 B |
BIN
themes/default/public/gallery/images/loader-black1.gif
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
themes/default/public/gallery/images/loader-black2.gif
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
themes/default/public/gallery/images/loader-black3.gif
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
themes/default/public/gallery/images/loader-black4.gif
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
themes/default/public/gallery/images/loader-black5.gif
Normal file
|
After Width: | Height: | Size: 8.2 KiB |