Compare commits

...

234 commits

Author SHA1 Message Date
Sergio Brighenti
a00fd5a5e2
Merge pull request #579 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2024-08-15 15:10:15 +02:00
Oğuz Ersen
0fe1748077
Translated using Weblate (Turkish)
Currently translated at 100.0% (162 of 162 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/tr/
2024-08-04 20:28:59 +00:00
Hani Rouatbi
c58a114ac9
Translated using Weblate (Arabic)
Currently translated at 100.0% (162 of 162 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ar/
2024-08-04 20:28:58 +00:00
Sectly
23f6b18ffe
Translated using Weblate (Dutch)
Currently translated at 100.0% (162 of 162 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/nl/
2024-08-04 20:28:58 +00:00
bittin1ddc447d824349b2
4ad4b20762
Translated using Weblate (Swedish)
Currently translated at 100.0% (162 of 162 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/sv/
2024-08-04 20:28:57 +00:00
gallegonovato
1c2801e2f0
Translated using Weblate (Spanish)
Currently translated at 100.0% (162 of 162 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/es/
2024-08-04 20:28:56 +00:00
Sergio Brighenti
a918c95a56
Merge pull request #578 from sergix44/dependabot/npm_and_yarn/braces-3.0.3
Bump braces from 3.0.2 to 3.0.3
2024-08-04 22:28:51 +02:00
Sergio Brighenti
fa85310d1d
Merge pull request #586 from samrzhevsky/master
Fix page count calculation
2024-08-04 22:28:21 +02:00
samrzhevsky
8fabc57f04
Fix page count calculation 2024-07-27 23:39:38 +03:00
dependabot[bot]
cd28fe11af
Bump braces from 3.0.2 to 3.0.3
Bumps [braces](https://github.com/micromatch/braces) from 3.0.2 to 3.0.3.
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)

---
updated-dependencies:
- dependency-name: braces
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-06-16 14:57:30 +00:00
Sergio Brighenti
687c503efd
Merge pull request #561 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2024-06-15 21:59:26 +02:00
Vin
c6f087e092
Translated using Weblate (Russian)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ru/
2024-06-15 21:57:04 +02:00
tabby
4718d8a0b1
Translated using Weblate (Korean)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ko/
2024-06-15 21:57:04 +02:00
ssantos
bb97621041
Translated using Weblate (Portuguese)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/pt/
2024-06-15 21:57:04 +02:00
Eryk Michalak
49e3110273
Translated using Weblate (Polish)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/pl/
2024-06-15 21:57:04 +02:00
Mikachu
41b26f45b7
Translated using Weblate (Dutch)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/nl/
2024-06-15 21:57:04 +02:00
Gaming Tibor
f2ae33bcd7
Translated using Weblate (Hungarian)
Currently translated at 99.3% (160 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/hu/
2024-06-15 21:57:04 +02:00
LeonMtn05
96972b8222
Translated using Weblate (German)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/de/
2024-06-15 21:57:04 +02:00
Sergio Brighenti
06562d194b
Merge pull request #572 from lsgd/master
Enable upload from clipboard
2024-06-15 21:57:01 +02:00
Lukas Schulze
a600a21753 Add link to remove tags filter 2024-04-30 16:15:41 +02:00
lsgd
1193c96966
Merge branch 'sergix44:master' into master 2024-04-30 15:49:54 +02:00
Lukas Schulze
4946750beb enable upload via clipboard paste 2024-04-30 15:49:01 +02:00
Sergio Brighenti
cc8ed75ec6 Update changelog 2024-01-14 14:24:40 +01:00
Sergio Brighenti
9dbf1400f6 Update lock 2024-01-14 14:16:56 +01:00
Sergio Brighenti
dd5e30abe2 Update list preview icon color 2024-01-14 14:15:16 +01:00
Sergio Brighenti
59c6691585
Merge pull request #553 from lsgd/master
Add link to file preview which opens the file itself
2024-01-14 14:04:28 +01:00
Sergio Brighenti
bd3ca55e20
Merge pull request #556 from sergix44/dependabot/composer/aws/aws-sdk-php-3.294.5
Bump aws/aws-sdk-php from 3.271.3 to 3.294.5
2024-01-04 00:06:30 +01:00
Sergio Brighenti
04a6770f19
Merge pull request #546 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2024-01-04 00:05:25 +01:00
ssantos
a8f26558a6
Translated using Weblate (Portuguese)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/pt/
2024-01-04 00:04:44 +01:00
Oğuz Ersen
853ed10e1c
Translated using Weblate (Turkish)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/tr/
2024-01-04 00:04:44 +01:00
Xin Mu
25ed553ed1
Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/zh_Hans/
2024-01-04 00:04:44 +01:00
Kalle Laine
ab211c571a
Translated using Weblate (Finnish)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fi/
2024-01-04 00:04:44 +01:00
Reza Almanda
3f9bc8ae7c
Translated using Weblate (Indonesian)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/id/
2024-01-04 00:04:44 +01:00
Caspar Coen Graafstal
2c33f19785
Translated using Weblate (Dutch)
Currently translated at 98.7% (159 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/nl/
2024-01-04 00:04:44 +01:00
春末丶冬初
57a66f83bd
Translated using Weblate (Chinese (Simplified))
Currently translated at 98.1% (158 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/zh_Hans/
2024-01-04 00:04:44 +01:00
J. Lavoie
41870dce76
Translated using Weblate (French (Canada))
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fr_CA/
2024-01-04 00:04:44 +01:00
J. Lavoie
f5fba276fd
Translated using Weblate (French)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fr/
2024-01-04 00:04:44 +01:00
J. Lavoie
b2403baf0b
Translated using Weblate (German)
Currently translated at 99.3% (160 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/de/
2024-01-04 00:04:44 +01:00
J. Lavoie
634d301e80
Translated using Weblate (Italian)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/it/
2024-01-04 00:04:44 +01:00
a
a0f82ae4ab
Translated using Weblate (Russian)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ru/
2024-01-04 00:04:44 +01:00
Luna Jernberg
a5e63dcd33
Translated using Weblate (Swedish)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/sv/
2024-01-04 00:04:44 +01:00
gallegonovato
8cda536340
Translated using Weblate (Spanish)
Currently translated at 100.0% (161 of 161 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/es/
2024-01-04 00:04:44 +01:00
Sergio Brighenti
5d99a96f84
Merge pull request #554 from SrS2225a/master
Add support for kde integration
2024-01-04 00:04:40 +01:00
dependabot[bot]
68a428b33f
Bump aws/aws-sdk-php from 3.271.3 to 3.294.5
Bumps [aws/aws-sdk-php](https://github.com/aws/aws-sdk-php) from 3.271.3 to 3.294.5.
- [Release notes](https://github.com/aws/aws-sdk-php/releases)
- [Commits](https://github.com/aws/aws-sdk-php/compare/3.271.3...3.294.5)

---
updated-dependencies:
- dependency-name: aws/aws-sdk-php
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-22 00:11:25 +00:00
SrS2225a
76eecb298b added support for kde intergration 2023-12-17 13:44:29 -08:00
Sergio Brighenti
903f87e693
Merge pull request #547 from samrzhevsky/master
LDAP fixes
2023-12-17 10:45:49 +01:00
Lukas Schulze
eee497669e Add link to file preview which opens the file itself 2023-12-10 20:22:49 +01:00
samrzhevsky
e7a0a99fe6
LDAP fixes
1. Changed `ldap_connect` error handling. `ldap_error` expects `LDAP\Connection`, and `ldap_connect` returns `false` if the syntax check fails
2. Fixed deprecation: passing null to parameter (`$ignore`) of type string
3. Fixed PHPDoc types for compatibility with PHP 8.1+
2023-08-28 00:31:22 +03:00
Sergio Brighenti
ee55a9ea3a
Merge pull request #539 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2023-08-14 22:46:06 +02:00
Sergio Brighenti
7f07ecdfad
Merge pull request #507 from SrS2225a/master
Support For Vanity Urls
2023-08-14 22:45:48 +02:00
SrS2225a
a11a9307ea corrected styleCI issues for sql querys 2023-08-13 23:40:06 -07:00
SrS2225a
32b8a16c40 readded missing function createVanity 2023-08-13 23:29:41 -07:00
SrS2225a
c8c540ff50 fixed grunt conflicts and corrected the lang key 2023-08-13 22:45:37 -07:00
SrS2225a
c8fac0a578 Merge branch 'master' of https://github.com/SergiX44/XBackBone
# Conflicts:
#	app/Controllers/MediaController.php
2023-08-13 22:00:19 -07:00
J. Lavoie
35a2e59c6c
Translated using Weblate (French (Canada))
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fr_CA/
2023-06-29 23:49:23 +02:00
J. Lavoie
95b4435e6f
Translated using Weblate (Italian)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/it/
2023-06-29 23:49:22 +02:00
Sergio Brighenti
0951638dc8
Merge pull request #533 from cursey/feature/upload-response-raw-url 2023-05-31 09:54:11 +02:00
cursey
d3fde3e298
Upload: Response now includes raw_url as well 2023-05-29 21:57:55 -07:00
Sergio Brighenti
c7a6dd1c16 update version 2023-05-27 17:09:22 +02:00
Sergio Brighenti
327005833c update changelog 2023-05-27 17:06:28 +02:00
Sergio Brighenti
49c7b60137
Merge pull request #532 from nebulade/patch-1 2023-05-25 10:39:29 +02:00
Johannes Zellner
4d791aad06
Make AuthController.php compatible with php8.1+
php api changed https://www.php.net/manual/en/class.ldap-result.php
2023-05-25 10:12:42 +02:00
Sergio Brighenti
9c85698c28 drop azure blob storage 2023-05-24 00:50:57 +02:00
Sergio Brighenti
91d05884b9
Merge pull request #513 from SergiX44/support_php_82 2023-05-23 23:03:21 +02:00
Sergio Brighenti
707d32ff25
Merge pull request #522 from weblate/weblate-xbackbone-xbackbone 2023-05-23 23:00:32 +02:00
Sergio Brighenti
3702753ade
Merge pull request #529 from SergiX44/analysis-JG7k4o 2023-05-23 23:00:17 +02:00
StyleCI Bot
5e6ba5a0b3
Apply fixes from StyleCI
[ci skip] [skip ci]
2023-05-23 21:00:00 +00:00
Sergio Brighenti
7a4be04917 fix failing test 2023-05-23 22:59:55 +02:00
Reza Almanda
4cf84fdafe
Translated using Weblate (Indonesian)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/id/
2023-05-23 21:42:28 +02:00
Daniel Benyšek
d86d3826d5
Translated using Weblate (Czech)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/cs/
2023-05-23 21:42:28 +02:00
Alexey Gudym
04e42bd456
Translated using Weblate (Russian)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ru/
2023-05-23 21:42:28 +02:00
Sergio Brighenti
c3ebf4d39b
Merge pull request #526 from SergiX44/dependabot/composer/guzzlehttp/psr7-1.9.1 2023-05-23 21:42:23 +02:00
Sergio Brighenti
e05600ec26
Merge pull request #527 from SergiX44/analysis-a60gDB 2023-04-19 23:52:54 +02:00
StyleCI Bot
ae5e2cffb3
Apply fixes from StyleCI
[ci skip] [skip ci]
2023-04-19 21:23:06 +00:00
dependabot[bot]
45dc6ff87b
Bump guzzlehttp/psr7 from 1.9.0 to 1.9.1
Bumps [guzzlehttp/psr7](https://github.com/guzzle/psr7) from 1.9.0 to 1.9.1.
- [Release notes](https://github.com/guzzle/psr7/releases)
- [Changelog](https://github.com/guzzle/psr7/blob/1.9.1/CHANGELOG.md)
- [Commits](https://github.com/guzzle/psr7/compare/1.9.0...1.9.1)

---
updated-dependencies:
- dependency-name: guzzlehttp/psr7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-04-19 21:22:57 +00:00
SrS2225a
69d6ae298e style ci fix 2023-01-17 21:39:40 -08:00
SrS2225a
acaceea3f1 added fixes per request by author 2023-01-17 21:17:52 -08:00
Sergio Brighenti
589720d81b update lock file 2023-01-16 21:06:05 +01:00
Sergio Brighenti
46502074a0 swap implementation psr7
drop direct impl call
2023-01-16 21:03:36 +01:00
Sergio Brighenti
020ad75238 update deps 2023-01-16 18:41:26 +01:00
Sergio Brighenti
02be446c2e
Merge pull request #503 from weblate/weblate-xbackbone-xbackbone 2022-12-31 16:54:35 +01:00
SrS2225a
58744bd092 fixed code styling issues 2022-12-30 21:44:51 -08:00
Özgür
2a789d0f8a
Translated using Weblate (Turkish)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/tr/
2022-12-29 01:14:02 +01:00
Oğuz Ersen
e8c3b75b99
Translated using Weblate (Turkish)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/tr/
2022-12-29 01:14:02 +01:00
Sergio Brighenti
b790d21e01
Merge pull request #502 from SergiX44/dependabot/npm_and_yarn/qs-6.11.0 2022-12-29 01:13:58 +01:00
Sergio Brighenti
237e2f7a57
Merge pull request #501 from samrzhevsky/master 2022-12-29 00:58:19 +01:00
SrS2225a
4deedda3b6 bug fixes for vanity links 2022-12-19 19:42:08 -08:00
SrS2225a
d6dce885d2 added support for vanity links 2022-12-18 21:54:18 -08:00
SrS2225a
d823230c35 Merge branch 'master' of https://github.com/SrS2225a/XBackBone 2022-12-18 21:53:08 -08:00
SrS2225a
634956cb2d added support for vanity links 2022-12-18 21:22:15 -08:00
dependabot[bot]
6a05a5dac8
Bump qs from 6.10.1 to 6.11.0
Bumps [qs](https://github.com/ljharb/qs) from 6.10.1 to 6.11.0.
- [Release notes](https://github.com/ljharb/qs/releases)
- [Changelog](https://github.com/ljharb/qs/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ljharb/qs/compare/v6.10.1...v6.11.0)

---
updated-dependencies:
- dependency-name: qs
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-12-06 14:36:59 +00:00
Sam Rzhevsky
9bddf5940b
Fix filter by tag
Fixed filter by non-existent tag
2022-11-30 21:13:58 +03:00
Sergio Brighenti
b4f720cf21 update changelog 2022-11-27 22:44:17 +01:00
Sergio Brighenti
2bce85ea6a upgraded phpunit 2022-11-27 22:37:22 +01:00
Sergio Brighenti
e2c3aaf89a update deps 2022-11-27 22:34:42 +01:00
Sergio Brighenti
a9c492c99d
Merge pull request #499 from samrzhevsky/master 2022-11-27 22:31:43 +01:00
Sam Rzhevsky
3bb2b7b4ea
Logging fix
PHP Notice: Undefined property: stdClass::$name in app/Controllers/ExportController.php on line 28
2022-11-27 21:37:37 +03:00
Sergio Brighenti
2ddaac8e5a
Merge pull request #496 from FingerlessGlov3s/patch-2
remove duplicate lines
2022-11-08 10:39:27 +01:00
FingerlessGloves
e4e67657d8
remove duplicate lines
meta tags are oddly repeated
2022-11-02 23:18:01 +00:00
Sergio Brighenti
1e0e549938
Merge pull request #495 from FingerlessGlov3s/patch-1
Fixes redirect bug for reverse proxy
2022-11-02 21:04:50 +01:00
FingerlessGloves
9caee0dc5b
Fixes redirect bug for reverse proxy
If you are logged out of XBackbone, and browse to `/upload` for example the direction holds the request URI, which isn't an issue unless you've got a reverse proxy in front of it.
For example, if the app is running in a container on port 8080, and Traefik is doing the reverse proxying, when you try login after being redirected to the login page, the redirectTo session contains the internal port number, which causes you to be redirected to `https://mydomain.com:8080/upload` instead of the correct `https://mydomain.com/upload`
2022-10-31 22:39:32 +00:00
Sergio Brighenti
99c9f50294
Merge pull request #480 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2022-10-26 10:05:38 +02:00
Ho_ Tsuyosi (스넾)
48ba6f009e
Translated using Weblate (Japanese)
Currently translated at 66.2% (106 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ja/
2022-10-26 10:05:28 +02:00
Zsolt Nagy
8379eb41ef
Translated using Weblate (Hungarian)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/hu/
2022-10-26 10:05:28 +02:00
PVPMaster0001
90ac32621a
Translated using Weblate (Finnish)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fi/
2022-10-26 10:05:28 +02:00
PVPMaster0001
80152ac31a
Translated using Weblate (Japanese)
Currently translated at 53.1% (85 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ja/
2022-10-26 10:05:28 +02:00
Denis Branisteanu
3aac808525
Translated using Weblate (Romanian)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ro/
2022-10-26 10:05:28 +02:00
Denis Branisteanu
57122a8f96
Translated using Weblate (Romanian)
Currently translated at 6.2% (10 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ro/
2022-10-26 10:05:28 +02:00
Denis Branisteanu
e155a33f86
Added translation using Weblate (Romanian) 2022-10-26 10:05:28 +02:00
Hien
46341b4e03
Translated using Weblate (Vietnamese)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/vi/
2022-10-26 10:05:28 +02:00
Özgür
a1b3ab47ab
Translated using Weblate (Turkish)
Currently translated at 91.2% (146 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/tr/
2022-10-26 10:05:28 +02:00
Özgür
904795029c
Translated using Weblate (Turkish)
Currently translated at 41.8% (67 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/tr/
2022-10-26 10:05:28 +02:00
Sergio Brighenti
1eebc961ab
Merge pull request #479 from SergiX44/dependabot/composer/guzzlehttp/guzzle-7.4.5
Bump guzzlehttp/guzzle from 7.4.4 to 7.4.5
2022-10-26 10:05:24 +02:00
Sergio Brighenti
0f6cc027f7
Merge pull request #490 from SergiX44/dependabot/composer/twig/twig-2.15.3
Bump twig/twig from 2.15.1 to 2.15.3
2022-10-26 10:05:16 +02:00
dependabot[bot]
c83539245b
Bump twig/twig from 2.15.1 to 2.15.3
Bumps [twig/twig](https://github.com/twigphp/Twig) from 2.15.1 to 2.15.3.
- [Release notes](https://github.com/twigphp/Twig/releases)
- [Changelog](https://github.com/twigphp/Twig/blob/v2.15.3/CHANGELOG)
- [Commits](https://github.com/twigphp/Twig/compare/v2.15.1...v2.15.3)

---
updated-dependencies:
- dependency-name: twig/twig
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-09-30 20:25:52 +00:00
Sergio Brighenti
7af93ae136
Merge pull request #484 from FunctionDJ/patch-1
Update minimum PHP version in docs
2022-08-04 14:44:00 +02:00
Function
96b61b5834
Update minimum PHP version in docs 2022-08-04 13:45:04 +02:00
dependabot[bot]
d6d4fbcf94
Bump guzzlehttp/guzzle from 7.4.4 to 7.4.5
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.4.4 to 7.4.5.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/master/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.4.4...7.4.5)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-21 21:00:12 +00:00
Sergio Brighenti
edc20c30f7 update changelog 2022-06-20 18:13:15 +02:00
Sergio Brighenti
66c708ab77
Update CHANGELOG.md 2022-06-20 18:11:49 +02:00
Sergio Brighenti
469ed2068c fix 2022-06-20 17:36:00 +02:00
Sergio Brighenti
8242ef5443 compress the release zip 2022-06-20 13:56:50 +02:00
Sergio Brighenti
0f1c458e76 fix resize 2022-06-20 13:06:05 +02:00
Sergio Brighenti
87a1b8517a remove workflow 2022-06-19 23:42:33 +02:00
Sergio Brighenti
5399133b65 updated changelog 2022-06-19 23:37:55 +02:00
Sergio Brighenti
59124e994a bump minimum php version 2022-06-19 23:30:14 +02:00
Sergio Brighenti
15e2c3512c
Merge pull request #474 from SergiX44/analysis-o7r0ep
Apply fixes from StyleCI
2022-06-19 23:21:46 +02:00
StyleCI Bot
7f4f262249
Apply fixes from StyleCI
[ci skip] [skip ci]
2022-06-19 21:21:38 +00:00
Sergio Brighenti
1979c3f318 fixed discord video embedding 2022-06-19 23:21:27 +02:00
Sergio Brighenti
8bf64a6537 fix deprecation issue 2022-06-19 22:00:36 +02:00
Sergio Brighenti
d21f678843 fix issue with post max size = 0
fixes #453
2022-06-19 20:20:21 +02:00
Sergio Brighenti
67fdb89ce3 update deps 2022-06-19 20:17:07 +02:00
Sergio Brighenti
badb0c681d
Merge pull request #470 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2022-06-19 14:39:48 +02:00
flakka2022
dfc3ab3bce
Translated using Weblate (Persian)
Currently translated at 16.2% (26 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fa/
2022-06-18 03:20:42 +02:00
flakka2022
87b7f245c9
Added translation using Weblate (Persian) 2022-06-17 02:32:48 +02:00
春末丶冬初
e8a9cfea92
Translated using Weblate (Chinese (Simplified))
Currently translated at 95.0% (152 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/zh_Hans/
2022-06-15 13:31:21 +02:00
Hien
6d43b62677
Translated using Weblate (Vietnamese)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/vi/
2022-06-15 12:18:18 +02:00
Hien
79ed8eeb5e
Added translation using Weblate (Vietnamese) 2022-06-14 06:42:37 +02:00
Sergio Brighenti
2ec7457fcd
Merge pull request #468 from cloudron-io/ldap_auto_create
ldap: ensure missing ldap user is auto-created
2022-06-12 18:12:55 +02:00
Sergio Brighenti
659b31548e
Merge pull request #467 from cloudron-io/ldap_docs
improve ldap docs
2022-06-12 17:44:04 +02:00
Girish Ramakrishnan
538f3d6bd8 ldap: ensure missing ldap user is auto-created 2022-06-12 08:35:22 -07:00
Girish Ramakrishnan
1a418d46e9 ldap docs: remove superfluous brackets in search filter
should also fix #376
2022-06-11 19:33:46 -07:00
Sergio Brighenti
83ec0b5201
Merge pull request #464 from SergiX44/dependabot/composer/guzzlehttp/guzzle-7.4.4
Bump guzzlehttp/guzzle from 7.4.1 to 7.4.4
2022-06-11 13:45:31 +02:00
Sergio Brighenti
ec6b692cc8
Merge pull request #463 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2022-06-11 13:45:23 +02:00
dependabot[bot]
aa2d85f5ee
Bump guzzlehttp/guzzle from 7.4.1 to 7.4.4
Bumps [guzzlehttp/guzzle](https://github.com/guzzle/guzzle) from 7.4.1 to 7.4.4.
- [Release notes](https://github.com/guzzle/guzzle/releases)
- [Changelog](https://github.com/guzzle/guzzle/blob/master/CHANGELOG.md)
- [Commits](https://github.com/guzzle/guzzle/compare/7.4.1...7.4.4)

---
updated-dependencies:
- dependency-name: guzzlehttp/guzzle
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-06-10 06:44:33 +00:00
Kowski
a6bfc32869
Translated using Weblate (Serbian)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/sr/
2022-06-06 11:26:47 +02:00
Kowski
188dce1a56
Added translation using Weblate (Serbian) 2022-06-06 10:38:05 +02:00
Sergio Brighenti
94638ae941
Merge pull request #461 from SergiX44/dependabot/npm_and_yarn/grunt-1.5.3
Bump grunt from 1.5.2 to 1.5.3
2022-06-01 14:30:13 +02:00
dependabot[bot]
f1728d7e91
Bump grunt from 1.5.2 to 1.5.3
Bumps [grunt](https://github.com/gruntjs/grunt) from 1.5.2 to 1.5.3.
- [Release notes](https://github.com/gruntjs/grunt/releases)
- [Changelog](https://github.com/gruntjs/grunt/blob/main/CHANGELOG)
- [Commits](https://github.com/gruntjs/grunt/compare/v1.5.2...v1.5.3)

---
updated-dependencies:
- dependency-name: grunt
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-26 00:12:41 +00:00
Sergio Brighenti
6a4b49f617
Merge pull request #456 from SergiX44/dependabot/npm_and_yarn/async-2.6.4
Bump async from 2.6.3 to 2.6.4
2022-05-17 21:42:56 +02:00
dependabot[bot]
b856ffd530
Bump async from 2.6.3 to 2.6.4
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-10 21:32:34 +00:00
Sergio Brighenti
1e12a57a0d
Merge pull request #455 from SergiX44/dependabot/npm_and_yarn/grunt-1.5.2
Bump grunt from 1.4.1 to 1.5.2
2022-05-10 23:20:30 +02:00
Sergio Brighenti
9f64b15f91
Merge pull request #454 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2022-05-10 23:20:20 +02:00
dependabot[bot]
daf3665414
Bump grunt from 1.4.1 to 1.5.2
Bumps [grunt](https://github.com/gruntjs/grunt) from 1.4.1 to 1.5.2.
- [Release notes](https://github.com/gruntjs/grunt/releases)
- [Changelog](https://github.com/gruntjs/grunt/blob/main/CHANGELOG)
- [Commits](https://github.com/gruntjs/grunt/compare/v1.4.1...v1.5.2)

---
updated-dependencies:
- dependency-name: grunt
  dependency-type: direct:development
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-27 06:27:02 +00:00
Myunker 1MP4C7 Eredzhebov
9c172ce417
Translated using Weblate (Bulgarian)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/bg/
2022-04-26 11:14:42 +02:00
Sergio Brighenti
d123eda772
Merge pull request #452 from R0GGER/patch-1
Fix for issue #450
2022-04-17 14:21:59 +02:00
R0GGER
c830a31157
Fix for issue #450 2022-04-16 22:56:38 +02:00
Sergio Brighenti
714a5e9d6a
Merge pull request #449 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2022-04-10 22:57:56 +02:00
Rubens
e995a2e539
Translated using Weblate (Catalan)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ca/
2022-04-10 22:57:49 +02:00
Rubens
063ecff83f
Added translation using Weblate (Catalan) 2022-04-10 22:57:49 +02:00
Sergio Brighenti
bfed200dcd
Merge pull request #446 from SergiX44/dependabot/composer/guzzlehttp/psr7-1.8.4
Bump guzzlehttp/psr7 from 1.8.3 to 1.8.4
2022-04-10 22:57:46 +02:00
dependabot[bot]
edb1ced704
Bump guzzlehttp/psr7 from 1.8.3 to 1.8.4
Bumps [guzzlehttp/psr7](https://github.com/guzzle/psr7) from 1.8.3 to 1.8.4.
- [Release notes](https://github.com/guzzle/psr7/releases)
- [Changelog](https://github.com/guzzle/psr7/blob/1.8.4/CHANGELOG.md)
- [Commits](https://github.com/guzzle/psr7/compare/1.8.3...1.8.4)

---
updated-dependencies:
- dependency-name: guzzlehttp/psr7
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-29 22:16:12 +00:00
Sergio Brighenti
8fc0a35749
Merge pull request #440 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2022-03-10 18:43:01 +01:00
Jaakko Törrö
6ce9041639
Translated using Weblate (Finnish)
Currently translated at 78.7% (126 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fi/
2022-02-18 23:55:58 +01:00
kubab6
d4aca7d3a5
Translated using Weblate (Polish)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/pl/
2022-02-18 23:55:58 +01:00
Allan Nordhøy
114504bde0
Translated using Weblate (Norwegian Bokmål)
Currently translated at 92.5% (148 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/nb_NO/
2022-02-12 19:54:36 +01:00
SergiX44
7634741676 implemented cache for remote filesystems
fixes #424
2022-02-08 22:24:16 +01:00
SergiX44
dea92d9ada fix test 2022-01-30 11:58:43 +01:00
Sergio Brighenti
1390ee76c6
Merge pull request #431 from weblate/weblate-xbackbone-xbackbone
Translations update from Hosted Weblate
2022-01-30 11:52:11 +01:00
Emilion DK
8f4f523b22
Translated using Weblate (Danish)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/da/
2022-01-17 12:56:08 +01:00
SAMI SAFHI
6134667b32
Translated using Weblate (Arabic)
Currently translated at 63.1% (101 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ar/
2022-01-02 10:52:20 +01:00
春末丶冬初
c16567d0a6
Translated using Weblate (Chinese (Simplified))
Currently translated at 93.7% (150 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/zh_Hans/
2021-12-29 14:53:11 +01:00
春末丶冬初
13979d9117
Translated using Weblate (Chinese (Simplified))
Currently translated at 3.7% (6 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/zh_Hans/
2021-12-28 13:52:38 +01:00
春末丶冬初
31ebf49944
Added translation using Weblate (Chinese (Simplified)) 2021-12-28 13:48:45 +01:00
Sergio Brighenti
a273235b0c
Add files via upload 2021-10-25 12:30:53 +02:00
SergiX44
2ae95bc409 release: 3.5.1 2021-10-22 19:50:34 +02:00
Sergio Brighenti
8894d2bb1c
Merge pull request #398 from TheDevFreak/patch-1
fix for discord UA change.
2021-10-16 21:08:36 +02:00
TheDevFreak
37b2f5a423
fix for discord UA change. 2021-10-16 17:44:57 +01:00
Sergio Brighenti
e0f18fa873
Merge pull request #395 from SergiX44/update_dependencies
update deps
2021-10-06 10:04:31 +02:00
SergiX44
23a44363c3 fix dependencies vulns 2021-10-06 09:58:48 +02:00
SergiX44
3f0f491e6e fix dependencies vulns 2021-10-06 09:53:57 +02:00
Sergio Brighenti
8469e05b02
Merge pull request #393 from weblate/weblate-xbackbone-xbackbone
Translations update from Weblate
2021-10-05 19:17:32 +02:00
Kami
ffe8d03b19
Translated using Weblate (Spanish)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/es/
2021-10-02 15:38:39 +02:00
Sergio Brighenti
11c0d578e6 update docs 2021-09-05 18:03:26 +02:00
Sergio Brighenti
26131aa1fa translations update 2021-09-05 18:01:51 +02:00
Sergio Brighenti
1954a3a18f
Merge pull request #379 from weblate/weblate-xbackbone-xbackbone
Translations update from Weblate
2021-09-05 18:00:45 +02:00
오로라
cfd1ff343b
Translated using Weblate (Korean)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ko/
2021-09-05 17:56:53 +02:00
오로라
d71bf25dbc
Translated using Weblate (Korean)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ko/
2021-09-05 17:56:53 +02:00
오로라
bb5ea36564
Translated using Weblate (Korean)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ko/
2021-09-05 17:56:53 +02:00
ssantos
c2dd20176f
Translated using Weblate (Portuguese)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/pt/
2021-09-05 17:56:53 +02:00
오로라
dec28fa0e5
Translated using Weblate (Korean)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/ko/
2021-09-05 17:56:53 +02:00
오로라
2cd0147888
Added translation using Weblate (Korean) 2021-09-05 17:56:53 +02:00
Sergio Brighenti
6523e87520 dropped theme cli command 2021-09-05 17:56:46 +02:00
Sergio Brighenti
a4077b7844
Merge pull request #377 from weblate/weblate-xbackbone-xbackbone
Translations update from Weblate
2021-08-24 23:38:16 +02:00
Gediminas Murauskas
0a48ebcab6
Translated using Weblate (Lithuanian)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/lt/
2021-08-20 22:35:03 +02:00
Gediminas Murauskas
52028f5f98
Translated using Weblate (Lithuanian)
Currently translated at 45.0% (72 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/lt/
2021-08-19 21:20:32 +02:00
J. Lavoie
434a5d89b2
Translated using Weblate (French (Canada))
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fr_CA/
2021-08-19 21:20:31 +02:00
J. Lavoie
9da5582ff6
Translated using Weblate (French)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/fr/
2021-08-19 21:20:30 +02:00
J. Lavoie
addde5972a
Translated using Weblate (Spanish)
Currently translated at 96.8% (155 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/es/
2021-08-19 21:20:30 +02:00
J. Lavoie
01d3147af8
Translated using Weblate (German)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/de/
2021-08-19 21:20:30 +02:00
Gediminas Murauskas
662a746809
Added translation using Weblate (Lithuanian) 2021-08-19 19:50:50 +02:00
Sergio Brighenti
a9790f2e25
Merge pull request #374 from weblate/weblate-xbackbone-xbackbone
Translations update from Weblate
2021-08-18 08:59:34 +02:00
Luna Jernberg
a8ced21fef
Translated using Weblate (Swedish)
Currently translated at 100.0% (160 of 160 strings)

Translation: XBackBone/XBackBone
Translate-URL: https://hosted.weblate.org/projects/xbackbone/xbackbone/sv/
2021-08-18 08:57:26 +02:00
SergiX44
d8501f2b33 changed url building 2021-08-18 08:57:21 +02:00
Sergio Brighenti
ef0d3c1708
Update test_suite.yml 2021-08-16 14:11:16 +02:00
SergiX44
7c8a8a3920 update lock 2021-08-16 14:03:16 +02:00
Sergio Brighenti
bf47596765
Merge pull request #372 from SergiX44/analysis-orb6Z5
Apply fixes from StyleCI
2021-08-16 13:56:27 +02:00
Sergio Brighenti
ee796c7ded Apply fixes from StyleCI
[ci skip] [skip ci]
2021-08-16 11:56:07 +00:00
SergiX44
3d248c8cb4 support for theme-park.dev 2021-08-16 13:55:47 +02:00
Sergio Brighenti
6ca60757ae
Merge pull request #371 from SergiX44/analysis-L3eD7n
Apply fixes from StyleCI
2021-08-15 21:34:15 +02:00
Sergio Brighenti
f508686e20 Apply fixes from StyleCI
[ci skip] [skip ci]
2021-08-15 19:34:00 +00:00
SergiX44
54284424ff expose configuration option for s3 2021-08-15 21:33:52 +02:00
Sergio Brighenti
2be6d1994d
Merge pull request #370 from SergiX44/analysis-peb5ok
Apply fixes from StyleCI
2021-08-13 09:38:51 +02:00
Sergio Brighenti
fbcdc8f20e Apply fixes from StyleCI
[ci skip] [skip ci]
2021-08-13 07:17:35 +00:00
SergiX44
bfbbf89d79 refactoring 2021-08-13 09:17:24 +02:00
SergiX44
bddcf34c6d Fix default theme 2021-08-12 22:30:26 +02:00
SergiX44
aeeddfed80 update docs 2021-08-12 22:07:53 +02:00
SergiX44
4d494f3f6c update docs 2021-08-12 18:07:05 +02:00
Sergio Brighenti
d7d2b5801c
Merge pull request #366 from olegkaspersky/master
Fixed missing commas in configurations
2021-08-11 18:21:27 +02:00
Sergio Brighenti
748aa807ca
Merge pull request #367 from SergiX44/analysis-1b7dYN
Apply fixes from StyleCI
2021-08-11 18:20:46 +02:00
Sergio Brighenti
52883982ad Apply fixes from StyleCI
[ci skip] [skip ci]
2021-08-11 16:17:59 +00:00
SergiX44
aa402c9e9d release 3.4.1 2021-08-11 18:17:48 +02:00
olegkaspersky
492ad5e8ea
Update configuration.md 2021-08-11 15:17:49 +03:00
olegkaspersky
085704a3b5
Fixed missing commas in configs 2021-08-11 15:17:28 +03:00
SergiX44
f7d8174cb3 improved check for embeds 2021-08-10 23:52:55 +02:00
SergiX44
bcd5959c9a update lock file 2021-08-10 21:47:56 +02:00
SergiX44
405b42e178 missing extension 2021-08-10 21:42:36 +02:00
SergiX44
09e326326b update lock 2021-08-10 21:40:30 +02:00
Sergio Brighenti
d9aa867c9c
Update test_suite.yml 2021-08-10 17:25:18 +02:00
SergiX44
1fc7da479c update lock 2021-08-10 17:14:44 +02:00
SergiX44
db204f8c48 Merge remote-tracking branch 'origin/master' 2021-08-10 13:51:07 +02:00
SergiX44
11e5a52519 changed copy raw mode added toggle for embed 2021-08-10 13:50:58 +02:00
Sergio Brighenti
e5422f9e7d
Merge pull request #364 from olegkaspersky/patch-1
commas
2021-08-10 09:41:27 +02:00
olegkaspersky
f5922fc12c
commas 2021-08-09 20:17:51 +03:00
90 changed files with 6517 additions and 2462 deletions

View file

@ -12,20 +12,16 @@ jobs:
strategy:
matrix:
operating-system: [ubuntu-latest]
php-versions: ["7.2", "7.3", "7.4", "8.0"]
php-versions: ["7.3", "7.4", "8.0", "8.1", "8.2"]
steps:
- uses: actions/checkout@v2
- name: Validate composer.json and composer.lock
run: composer validate
run: composer validate --no-check-version
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
run: composer install --no-progress
- name: Run test suite
run: vendor/bin/phpunit --no-coverage
- name: Send docker repo update
run: |
curl -H "Content-Type: application/json" --data '{"docker_tag": "master"}' -X POST https://registry.hub.docker.com/u/pe46dro/xbackbone-docker/trigger/505df075-f5b6-48bf-a22c-ce678f477929/

View file

@ -1,8 +1,8 @@
Options -Indexes
Options -Indexes +SymLinksIfOwnerMatch
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^(app|bin|bootstrap|resources|storage|vendor|logs|CHANGELOG.md)(/.*|)$ - [NC,F]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php [QSA,L]
</IfModule>
</IfModule>

View file

@ -3,6 +3,78 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
## Unreleased
## [3.7.0] - 2024-01-14
### Added
- Added support for vanity urls.
- Added KDE integration for linux script.
### Changed
- Updated translations.
- File preview is now clickable to open the file.
### Fixed
- Fixes for LDAP authentication.
## [3.6.3] - 2023-05-27
### Fixed
- Fix LDAP for php >= 8.1
## [3.6.2] - 2023-05-24
### Changed
- Support for PHP 8.2
### Removed
- Azure blob storage driver
## [3.6.1] - 2022-11-27
### Changed
- Upgraded dependencies
- Updated translations
### Fixed
- Fixed error in export data (#499)
- Fixed issues with reverse proxies (#495)
- Fixed duplicated twitter tags
## [3.6.0] - 2022-06-20
### Changed
- Improved embedding on discord of large videos.
- Releases are now compressed for faster downloads
- Updated translations
### Fixed
- Fixed deprecation notices on php >= 8
- Fixed embed UA for Discord.
- Fixed error with post_max_size = 0
### Removed
- Support for php 7.2
## [3.5.1] - 2021-10-22
### Changed
- Fixed embed UA for Discord.
- Updated translations.
## [3.5.0] - 2021-09-05
### Added
- Support for theme-park.dev themes.
- Updated translations.
### Fixed
- Wrong css when reapplying the default theme.
### Removed
- Dropped theme cli command.
## [3.4.1] - 2021-08-11
### Added
- Toggle to disable embeds.
### Changed
- Raw url copying now contains also the file extension.
## [3.4.0] - 2021-08-01
### Added
- Added image support for OG for Discord only.

View file

@ -128,33 +128,6 @@ module.exports = function (grunt) {
],
},
},
zip: {
[releaseFilename]: [
'app/**/*',
'bin/**/*',
'bootstrap/**/*',
'install/**/*',
'logs/**/',
'resources/cache',
'resources/sessions',
'resources/database',
'resources/lang/**/*',
'resources/templates/**/*',
'resources/schemas/**/*',
'resources/lang/**/*',
'resources/uploaders/**/*',
'static/**/*',
'vendor/**/*',
'.htaccess',
'config.example.php',
'index.php',
'composer.json',
'composer.lock',
'LICENSE',
'favicon.ico',
'CHANGELOG.md'
]
},
shell: {
phpstan: {
@ -163,7 +136,47 @@ module.exports = function (grunt) {
composer_no_dev: {
command: 'composer install --no-dev --prefer-dist'
}
}
},
compress: {
main: {
options: {
archive: releaseFilename,
mode: 'zip',
level: 9,
},
files: [{
expand: true,
cwd: './',
src: [
'app/**/*',
'bin/**/*',
'bootstrap/**/*',
'install/**/*',
'logs/**/',
'resources/cache',
'resources/sessions',
'resources/database',
'resources/lang/**/*',
'resources/templates/**/*',
'resources/schemas/**/*',
'resources/lang/**/*',
'resources/uploaders/**/*',
'static/**/*',
'vendor/**/*',
'.htaccess',
'config.example.php',
'index.php',
'composer.json',
'composer.lock',
'LICENSE',
'favicon.ico',
'CHANGELOG.md'
],
dest: '/'
}]
}
},
});
@ -172,5 +185,5 @@ module.exports = function (grunt) {
grunt.registerTask('test', ['jshint']);
grunt.registerTask('phpstan', ['shell:phpstan']);
grunt.registerTask('composer_no_dev', ['shell:composer_no_dev']);
grunt.registerTask('build-release', ['default', 'composer_no_dev', 'zip']);
grunt.registerTask('build-release', ['default', 'composer_no_dev', 'compress']);
};

View file

@ -3,6 +3,7 @@
namespace App\Controllers;
use App\Database\Migrator;
use App\Web\Theme;
use League\Flysystem\FileNotFoundException;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
@ -26,18 +27,22 @@ class AdminController extends Controller
$settings[$setting->key] = $setting->value;
}
$settings['default_user_quota'] = humanFileSize($this->getSetting('default_user_quota', stringToBytes('1G')), 0, true);
$settings['default_user_quota'] = humanFileSize(
$this->getSetting('default_user_quota', stringToBytes('1G')),
0,
true
);
return view()->render($response, 'dashboard/system.twig', [
'usersCount' => $usersCount = $this->database->query('SELECT COUNT(*) AS `count` FROM `users`')->fetch()->count,
'mediasCount' => $mediasCount = $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads`')->fetch()->count,
'orphanFilesCount' => $orphanFilesCount = $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `user_id` IS NULL')->fetch()->count,
'totalSize' => humanFileSize($totalSize = $this->database->query('SELECT SUM(`current_disk_quota`) AS `sum` FROM `users`')->fetch()->sum ?? 0),
'usersCount' => $this->database->query('SELECT COUNT(*) AS `count` FROM `users`')->fetch()->count,
'mediasCount' => $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads`')->fetch()->count,
'orphanFilesCount' => $this->database->query('SELECT COUNT(*) AS `count` FROM `uploads` WHERE `user_id` IS NULL')->fetch()->count,
'totalSize' => humanFileSize($this->database->query('SELECT SUM(`current_disk_quota`) AS `sum` FROM `users`')->fetch()->sum ?? 0),
'post_max_size' => ini_get('post_max_size'),
'upload_max_filesize' => ini_get('upload_max_filesize'),
'installed_lang' => $this->lang->getList(),
'forced_lang' => $request->getAttribute('forced_lang'),
'php_version' => phpversion(),
'php_version' => PHP_VERSION,
'max_memory' => ini_get('memory_limit'),
'settings' => $settings,
]);
@ -77,13 +82,15 @@ class AdminController extends Controller
*/
public function getThemes(Response $response): Response
{
$apiJson = json_decode(file_get_contents('https://bootswatch.com/api/4.json'));
$themes = make(Theme::class)->availableThemes();
$out = [];
$out['Default - Bootstrap 4 default theme'] = 'https://bootswatch.com/_vendor/bootstrap/dist/css/bootstrap.min.css';
foreach ($apiJson->themes as $theme) {
$out["{$theme->name} - {$theme->description}"] = $theme->cssMin;
foreach ($themes as $vendor => $list) {
$out["-- {$vendor} --"] = null;
foreach ($list as $name => $url) {
$out[$name] = "{$vendor}|{$url}";
}
}
return json($response, $out);

View file

@ -27,7 +27,7 @@ abstract class AuthController extends Controller
/**
* Connects to LDAP server and logs in with service account (if configured)
* @return resource|false
* @return \LDAP\Connection|resource|false
*/
public function ldapConnect()
{
@ -39,7 +39,7 @@ abstract class AuthController extends Controller
$ldapSchema=(@is_string($this->config['ldap']['schema'])) ?
strtolower($this->config['ldap']['schema']) : 'ldap';
$ldapURI="$ldapSchema://".$this->config['ldap']['host'].':'.$this->config['ldap']['port'];
// Connecting to LDAP server
$this->logger->debug("Connecting to $ldapURI");
$server = ldap_connect($ldapURI);
@ -48,18 +48,18 @@ abstract class AuthController extends Controller
ldap_set_option($server, LDAP_OPT_REFERRALS, 0);
ldap_set_option($server, LDAP_OPT_NETWORK_TIMEOUT, 10);
} else {
$this->logger->error(ldap_error($server));
$this->logger->error('LDAP-URI was not parseable');
return false;
}
// Upgrade to StartTLS
$useStartTLS = @is_bool($this->config['ldap']['useStartTLS']) ? $this->config['ldap']['useStartTLS'] : false;
if (($useStartTLS === true) && (ldap_start_tls($server) === false)) {
$this->logger-debug(ldap_error($server));
$this->logger->debug(ldap_error($server));
$this->logger->error("Failed to establish secure LDAP swith StartTLS");
return false;
}
// Authenticating LDAP service account (if configured)
$serviceAccountFQDN= (@is_string($this->config['ldap']['service_account_dn'])) ?
$this->config['ldap']['service_account_dn'] : null;
@ -77,7 +77,7 @@ abstract class AuthController extends Controller
/**
* Returns User's LDAP DN
* @param string $username
* @param resource $server LDAP Server Resource
* @param \LDAP\Connection|resource $server LDAP Server Resource
* @return string|null
*/
protected function getLdapRdn(string $username, $server)
@ -85,7 +85,7 @@ abstract class AuthController extends Controller
//Dynamic LDAP User Binding
if (@is_string($this->config['ldap']['search_filter'])) {
//Replace ???? with username
$searchFilter = str_replace('????', ldap_escape($username, null, LDAP_ESCAPE_FILTER), $this->config['ldap']['search_filter']);
$searchFilter = str_replace('????', ldap_escape($username, '', LDAP_ESCAPE_FILTER), $this->config['ldap']['search_filter']);
$ldapAddributes = array('dn');
$this->logger->debug("LDAP Search filter: $searchFilter");
$ldapSearchResp = ldap_search(
@ -94,7 +94,7 @@ abstract class AuthController extends Controller
$searchFilter,
$ldapAddributes
);
if (!is_resource($ldapSearchResp)) {
if (!$ldapSearchResp) {
$this->logger->debug(ldap_error($server));
$this->logger->error("User LDAP search for user $username failed");
return null;
@ -112,7 +112,7 @@ abstract class AuthController extends Controller
if ($this->config['ldap']['user_domain'] !== null) {
$bindString .= ','.$this->config['ldap']['user_domain'];
}
if ($this->config['ldap']['base_domain'] !== null) {
$bindString .= ','.$this->config['ldap']['base_domain'];
}

View file

@ -2,7 +2,7 @@
namespace App\Controllers\Auth;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\UserRepository;
use App\Web\ValidationHelper;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
@ -51,7 +51,7 @@ class LoginController extends AuthController
$password = param($request, 'password');
$user = $this->database->query('SELECT `id`, `email`, `username`, `password`,`is_admin`, `active`, `current_disk_quota`, `max_disk_quota`, `ldap`, `copy_raw` FROM `users` WHERE `username` = ? OR `email` = ? LIMIT 1', [$username, $username])->fetch();
if ($this->config['ldap']['enabled'] && ($user->ldap ?? true)) {
if ($this->config['ldap']['enabled'] && (!$user || $user->ldap ?? true)) {
$user = $this->ldapLogin($request, $username, param($request, 'password'), $user);
}
@ -128,13 +128,13 @@ class LoginController extends AuthController
$this->session->alert(lang('ldap_cant_connect'), 'warning');
return $dbUser;
}
//Get LDAP user's (R)DN
$userDN=$this->getLdapRdn($username, $server);
if (!is_string($userDN)) {
return null;
}
//Bind as user to validate password
if (@ldap_bind($server, $userDN, $password)) {
$this->logger->debug("$userDN authenticated against LDAP sucessfully");
@ -145,7 +145,7 @@ class LoginController extends AuthController
}
return null;
}
if (!$dbUser) {
$email = $username;
if (!filter_var($username, FILTER_VALIDATE_EMAIL)) {
@ -162,18 +162,18 @@ class LoginController extends AuthController
$entry = ldap_first_entry($server, $search);
$email = @ldap_get_values($server, $entry, 'mail')[0] ?? platform_mail($username.rand(0, 100)); // if the mail is not set, generate a placeholder
}
/** @var UserQuery $userQuery */
$userQuery = make(UserQuery::class);
/** @var UserRepository $userQuery */
$userQuery = make(UserRepository::class);
$userQuery->create($email, $username, $password, 0, 1, (int) $this->getSetting('default_user_quota', -1), null, 1);
return $userQuery->get($request, $this->database->getPdo()->lastInsertId());
}
if ($server) {
ldap_close($server);
}
if (!password_verify($password, $dbUser->password)) {
$userQuery = make(UserQuery::class);
$userQuery = make(UserRepository::class);
$userQuery->update($dbUser->id, $dbUser->email, $username, $password, $dbUser->is_admin, $dbUser->active, $dbUser->max_disk_quota, $dbUser->ldap);
return $userQuery->get($request, $dbUser->id);
}

View file

@ -11,7 +11,6 @@ use Slim\Exception\HttpNotFoundException;
class PasswordRecoveryController extends AuthController
{
/**
* @param Response $response
* @return Response

View file

@ -4,7 +4,7 @@
namespace App\Controllers\Auth;
use App\Controllers\Controller;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\UserRepository;
use App\Web\Mail;
use App\Web\ValidationHelper;
use Psr\Http\Message\ResponseInterface as Response;
@ -13,7 +13,6 @@ use Slim\Exception\HttpNotFoundException;
class RegisterController extends AuthController
{
/**
* @param Request $request
* @param Response $response
@ -67,7 +66,7 @@ class RegisterController extends AuthController
$activateToken = bin2hex(random_bytes(16));
make(UserQuery::class)->create(
make(UserRepository::class)->create(
param($request, 'email'),
param($request, 'username'),
param($request, 'password'),

View file

@ -2,7 +2,7 @@
namespace App\Controllers;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\UserRepository;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Exception\HttpNotFoundException;
@ -20,9 +20,9 @@ class ClientController extends Controller
*/
public function getShareXConfig(Request $request, Response $response, int $id): Response
{
$user = make(UserQuery::class)->get($request, $id, true);
$user = make(UserRepository::class)->get($request, $id, true);
if ($user->token === null || $user->token === '') {
if (!$user->token) {
$this->session->alert(lang('no_upload_token'), 'danger');
return redirect($response, $request->getHeaderLine('Referer'));
@ -96,9 +96,9 @@ class ClientController extends Controller
*/
public function getBashScript(Request $request, Response $response, int $id): Response
{
$user = make(UserQuery::class)->get($request, $id, true);
$user = make(UserRepository::class)->get($request, $id, true);
if ($user->token === null || $user->token === '') {
if (!$user->token) {
$this->session->alert(lang('no_upload_token'), 'danger');
return redirect($response, $request->getHeaderLine('Referer'));
@ -114,4 +114,35 @@ class ClientController extends Controller
]
);
}
/**
* @param Request $request
* @param Response $response
* @param int $id
*
* @return Response
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError
* @throws \Twig\Error\SyntaxError
*/
public function getKDEScript(Request $request, Response $response, int $id): Response
{
$user = make(UserRepository::class)->get($request, $id, true);
if (!$user->token) {
$this->session->alert(lang('no_upload_token'), 'danger');
return redirect($response, $request->getHeaderLine('Referer'));
}
return view()->render(
$response->withHeader('Content-Disposition', 'attachment;filename="xbackbone_uploader_'.$user->username.'.sh"'),
'scripts/xbackbone_kde_uploader.sh.twig',
[
'username' => $user->username,
'upload_url' => route('upload'),
'token' => $user->token,
]
);
}
}

View file

@ -3,7 +3,7 @@
namespace App\Controllers;
use App\Database\DB;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\UserRepository;
use App\Web\Lang;
use App\Web\Session;
use App\Web\ValidationHelper;
@ -89,7 +89,7 @@ abstract class Controller
*/
protected function updateUserQuota(Request $request, $userId, $fileSize, $dec = false)
{
$user = make(UserQuery::class)->get($request, $userId);
$user = make(UserRepository::class)->get($request, $userId);
if ($dec) {
$tot = max($user->current_disk_quota - $fileSize, 0);

View file

@ -2,8 +2,8 @@
namespace App\Controllers;
use App\Database\Queries\MediaQuery;
use App\Database\Queries\TagQuery;
use App\Database\Repositories\MediaRepository;
use App\Database\Repositories\TagRepository;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
@ -41,28 +41,28 @@ class DashboardController extends Controller
switch (param($request, 'sort', 'time')) {
case 'size':
$order = MediaQuery::ORDER_SIZE;
$order = MediaRepository::ORDER_SIZE;
break;
case 'name':
$order = MediaQuery::ORDER_NAME;
$order = MediaRepository::ORDER_NAME;
break;
default:
case 'time':
$order = MediaQuery::ORDER_TIME;
$order = MediaRepository::ORDER_TIME;
break;
}
$isAdmin = (bool) $this->session->get('admin', false);
/** @var MediaQuery $query */
$query = make(MediaQuery::class, ['isAdmin' => $isAdmin])
/** @var MediaRepository $query */
$query = make(MediaRepository::class, ['isAdmin' => $isAdmin])
->orderBy($order, param($request, 'order', 'DESC'))
->withUserId($this->session->get('user_id'))
->search(param($request, 'search', null))
->filterByTag(param($request, 'tag'))
->run($page);
$tags = make(TagQuery::class, [
$tags = make(TagRepository::class, [
'isAdmin' => $isAdmin,
'userId' => $this->session->get('user_id')
])->all();

View file

@ -3,7 +3,7 @@
namespace App\Controllers;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\UserRepository;
use League\Flysystem\FileNotFoundException;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
@ -21,11 +21,11 @@ class ExportController extends Controller
*/
public function downloadData(Request $request, Response $response, int $id): Response
{
$user = make(UserQuery::class)->get($request, $id, true);
$user = make(UserRepository::class)->get($request, $id, true);
$medias = $this->database->query('SELECT `uploads`.`filename`, `uploads`.`storage_path` FROM `uploads` WHERE `user_id` = ?', $user->id);
$this->logger->info("User $user->id, $user->name, exporting data...");
$this->logger->info("User $user->id, $user->username, exporting data...");
set_time_limit(0);
ob_end_clean();

View file

@ -2,8 +2,8 @@
namespace App\Controllers;
use App\Database\Queries\UserQuery;
use GuzzleHttp\Psr7\Stream;
use App\Database\Repositories\UserRepository;
use App\Web\UA;
use Intervention\Image\Constraint;
use Intervention\Image\ImageManagerStatic as Image;
use League\Flysystem\FileNotFoundException;
@ -13,6 +13,7 @@ use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Exception\HttpBadRequestException;
use Slim\Exception\HttpNotFoundException;
use Slim\Exception\HttpUnauthorizedException;
use Slim\Psr7\Stream;
class MediaController extends Controller
{
@ -31,11 +32,19 @@ class MediaController extends Controller
* @throws FileNotFoundException
*
*/
public function show(Request $request, Response $response, string $userCode, string $mediaCode, string $token = null): Response
{
public function show(
Request $request,
Response $response,
string $userCode,
string $mediaCode,
string $token = null
): Response {
$media = $this->getMedia($userCode, $mediaCode, true);
if (!$media || (!$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false))) {
if (!$media || (!$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get(
'admin',
false
))) {
throw new HttpNotFoundException($request);
}
@ -44,12 +53,9 @@ class MediaController extends Controller
$userAgent = $request->getHeaderLine('User-Agent');
$mime = $filesystem->getMimetype($media->storage_path);
if (isBot($userAgent) && (!isDiscord($userAgent) || (isDiscord($userAgent) && !isDisplayableImage($mime)))) {
return $this->streamMedia($request, $response, $filesystem, $media);
}
try {
$media->mimetype = $mime;
$media->extension = pathinfo($media->filename, PATHINFO_EXTENSION);
$size = $filesystem->getSize($media->storage_path);
$type = explode('/', $media->mimetype)[0];
@ -58,7 +64,7 @@ class MediaController extends Controller
$media->mimetype = 'application/octet-stream';
}
if ($type === 'text') {
if ($size <= (200 * 1024)) { // less than 200 KB
if ($size <= (500 * 1024)) { // less than 500 KB
$media->text = $filesystem->read($media->storage_path);
} else {
$type = 'application';
@ -70,12 +76,28 @@ class MediaController extends Controller
throw new HttpNotFoundException($request);
}
if (
UA::isBot($userAgent) &&
!(
// embed if enabled
(UA::embedsLinks($userAgent) &&
isEmbeddable($mime) &&
$this->getSetting('image_embeds') === 'on') ||
// if the file is too large to be displayed as non embedded
(UA::embedsLinks($userAgent) &&
isEmbeddable($mime) &&
$size >= (8 * 1024 * 1024))
)
) {
return $this->streamMedia($request, $response, $filesystem, $media);
}
return view()->render($response, 'upload/public.twig', [
'delete_token' => $token,
'media' => $media,
'type' => $type,
'url' => urlFor("/{$userCode}/{$mediaCode}"),
'copy_url_behavior' => $this->getSetting('copy_url_behavior', 'off'),
'url' => urlFor(glue($userCode, $mediaCode)),
'copy_raw' => $this->session->get('copy_raw', false),
]);
}
@ -113,11 +135,19 @@ class MediaController extends Controller
*
* @throws FileNotFoundException
*/
public function getRaw(Request $request, Response $response, string $userCode, string $mediaCode, ?string $ext = null): Response
{
public function getRaw(
Request $request,
Response $response,
string $userCode,
string $mediaCode,
?string $ext = null
): Response {
$media = $this->getMedia($userCode, $mediaCode, false);
if (!$media || (!$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false))) {
if (!$media || (!$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get(
'admin',
false
))) {
throw new HttpNotFoundException($request);
}
@ -148,13 +178,53 @@ class MediaController extends Controller
{
$media = $this->getMedia($userCode, $mediaCode, false);
if (!$media || (!$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get('admin', false))) {
if (!$media || (!$media->published && $this->session->get('user_id') !== $media->user_id && !$this->session->get(
'admin',
false
))) {
throw new HttpNotFoundException($request);
}
return $this->streamMedia($request, $response, $this->storage, $media, 'attachment');
}
/**
* @param Request $request
* @param Response $response
* @param string $vanity
* @param string $id
*
* @return Response
* @throws HttpNotFoundException
* @throws HttpBadRequestException
*/
public function createVanity(Request $request, Response $response, int $id): Response
{
$media = $this->database->query('SELECT * FROM `uploads` WHERE `id` = ? LIMIT 1', $id)->fetch();
$vanity = param($request, 'vanity');
$vanity = preg_replace('/[^a-z0-9]+/', '-', strtolower($vanity));
//handle collisions
$collision = $this->database->query('SELECT * FROM `uploads` WHERE `code` = ? AND `id` != ? LIMIT 1', [$vanity, $id])->fetch();
if (!$media) {
throw new HttpNotFoundException($request);
}
if ($vanity === '' || $collision) {
throw new HttpBadRequestException($request);
}
$this->database->query('UPDATE `uploads` SET `code` = ? WHERE `id` = ?', [$vanity, $media->id]);
$media->code = $vanity;
$response->getBody()->write(json_encode($media));
$this->logger->info('User '.$this->session->get('username').' created a vanity link for media '.$media->id);
return $response;
}
/**
* @param Request $request
* @param Response $response
@ -169,14 +239,20 @@ class MediaController extends Controller
if ($this->session->get('admin')) {
$media = $this->database->query('SELECT * FROM `uploads` WHERE `id` = ? LIMIT 1', $id)->fetch();
} else {
$media = $this->database->query('SELECT * FROM `uploads` WHERE `id` = ? AND `user_id` = ? LIMIT 1', [$id, $this->session->get('user_id')])->fetch();
$media = $this->database->query(
'SELECT * FROM `uploads` WHERE `id` = ? AND `user_id` = ? LIMIT 1',
[$id, $this->session->get('user_id')]
)->fetch();
}
if (!$media) {
throw new HttpNotFoundException($request);
}
$this->database->query('UPDATE `uploads` SET `published`=? WHERE `id`=?', [$media->published ? 0 : 1, $media->id]);
$this->database->query(
'UPDATE `uploads` SET `published`=? WHERE `id`=?',
[$media->published ? 0 : 1, $media->id]
);
return $response;
}
@ -198,19 +274,18 @@ class MediaController extends Controller
throw new HttpNotFoundException($request);
}
if ($this->session->get('admin', false) || $media->user_id === $this->session->get('user_id')) {
$this->deleteMedia($request, $media->storage_path, $id, $media->user_id);
$this->logger->info('User '.$this->session->get('username').' deleted a media.', [$id]);
if ($media->user_id === $this->session->get('user_id')) {
$user = make(UserQuery::class)->get($request, $media->user_id, true);
$this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota);
}
} else {
if (!$this->session->get('admin', false) && $media->user_id !== $this->session->get('user_id')) {
throw new HttpUnauthorizedException($request);
}
$this->deleteMedia($request, $media->storage_path, $id, $media->user_id);
$this->logger->info('User '.$this->session->get('username').' deleted a media.', [$id]);
if ($media->user_id === $this->session->get('user_id')) {
$user = make(UserRepository::class)->get($request, $media->user_id, true);
$this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota);
}
if ($request->getMethod() === 'GET') {
return redirect($response, route('home'));
}
@ -230,8 +305,13 @@ class MediaController extends Controller
*
* @throws HttpNotFoundException
*/
public function deleteByToken(Request $request, Response $response, string $userCode, string $mediaCode, string $token): Response
{
public function deleteByToken(
Request $request,
Response $response,
string $userCode,
string $mediaCode,
string $token
): Response {
$media = $this->getMedia($userCode, $mediaCode, false);
if (!$media) {
@ -296,17 +376,23 @@ class MediaController extends Controller
{
$mediaCode = pathinfo($mediaCode)['filename'];
$media = $this->database->query('SELECT `uploads`.*, `users`.*, `users`.`id` AS `userId`, `uploads`.`id` AS `mediaId` FROM `uploads` INNER JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `user_code` = ? AND `uploads`.`code` = ? LIMIT 1', [
$userCode,
$mediaCode,
])->fetch();
$media = $this->database->query(
'SELECT `uploads`.*, `users`.*, `users`.`id` AS `userId`, `uploads`.`id` AS `mediaId` FROM `uploads` INNER JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `user_code` = ? AND `uploads`.`code` = ? LIMIT 1',
[
$userCode,
$mediaCode,
]
)->fetch();
if (!$withTags || !$media) {
return $media;
}
$media->tags = [];
foreach ($this->database->query('SELECT `tags`.`id`, `tags`.`name` FROM `uploads_tags` INNER JOIN `tags` ON `uploads_tags`.`tag_id` = `tags`.`id` WHERE `uploads_tags`.`upload_id` = ?', $media->mediaId) as $tag) {
foreach ($this->database->query(
'SELECT `tags`.`id`, `tags`.`name` FROM `uploads_tags` INNER JOIN `tags` ON `uploads_tags`.`tag_id` = `tags`.`id` WHERE `uploads_tags`.`upload_id` = ?',
$media->mediaId
) as $tag) {
$media->tags[$tag->id] = $tag->name;
}
@ -324,33 +410,54 @@ class MediaController extends Controller
* @throws FileNotFoundException
*
*/
protected function streamMedia(Request $request, Response $response, Filesystem $storage, $media, string $disposition = 'inline'): Response
{
protected function streamMedia(
Request $request,
Response $response,
Filesystem $storage,
$media,
string $disposition = 'inline'
): Response {
set_time_limit(0);
$this->session->close();
$mime = $storage->getMimetype($media->storage_path);
if ((param($request, 'width') !== null || param($request, 'height') !== null) && explode('/', $mime)[0] === 'image') {
return $this->makeThumbnail($storage, $media, param($request, 'width'), param($request, 'height'), $disposition);
} else {
$stream = new Stream($storage->readStream($media->storage_path));
if ((param($request, 'width') !== null || param($request, 'height') !== null) && explode(
'/',
$mime
)[0] === 'image') {
return $this->makeThumbnail(
$storage,
$media,
param($request, 'width'),
param($request, 'height'),
$disposition
);
}
if (!in_array(explode('/', $mime)[0], ['image', 'video', 'audio']) || $disposition === 'attachment') {
return $response->withHeader('Content-Type', $mime)
->withHeader('Content-Disposition', $disposition.'; filename="'.$media->filename.'"')
->withHeader('Content-Length', $stream->getSize())
->withBody($stream);
}
if (isset($request->getServerParams()['HTTP_RANGE'])) {
return $this->handlePartialRequest($response, $stream, $request->getServerParams()['HTTP_RANGE'], $disposition, $media, $mime);
}
$stream = new Stream($storage->readStream($media->storage_path));
if (!in_array(explode('/', $mime)[0], ['image', 'video', 'audio']) || $disposition === 'attachment') {
return $response->withHeader('Content-Type', $mime)
->withHeader('Content-Disposition', $disposition.'; filename="'.$media->filename.'"')
->withHeader('Content-Length', $stream->getSize())
->withHeader('Accept-Ranges', 'bytes')
->withBody($stream);
}
if (isset($request->getServerParams()['HTTP_RANGE'])) {
return $this->handlePartialRequest(
$response,
$stream,
$request->getServerParams()['HTTP_RANGE'],
$disposition,
$media,
$mime
);
}
return $response->withHeader('Content-Type', $mime)
->withHeader('Content-Length', $stream->getSize())
->withHeader('Accept-Ranges', 'bytes')
->withBody($stream);
}
/**
@ -364,15 +471,23 @@ class MediaController extends Controller
* @throws FileNotFoundException
*
*/
protected function makeThumbnail(Filesystem $storage, $media, $width = null, $height = null, string $disposition = 'inline')
{
protected function makeThumbnail(
Filesystem $storage,
$media,
$width = null,
$height = null,
string $disposition = 'inline'
) {
return Image::make($storage->readStream($media->storage_path))
->resize($width, $height, function (Constraint $constraint) {
$constraint->aspectRatio();
})
->resizeCanvas($width, $height, 'center')
->psrResponse('png')
->withHeader('Content-Disposition', $disposition.';filename="scaled-'.pathinfo($media->filename, PATHINFO_FILENAME).'.png"');
->withHeader(
'Content-Disposition',
$disposition.';filename="scaled-'.pathinfo($media->filename, PATHINFO_FILENAME).'.png"'
);
}
/**
@ -385,8 +500,14 @@ class MediaController extends Controller
*
* @return Response
*/
protected function handlePartialRequest(Response $response, Stream $stream, string $range, string $disposition, $media, $mime)
{
protected function handlePartialRequest(
Response $response,
Stream $stream,
string $range,
string $disposition,
$media,
$mime
) {
$end = $stream->getSize() - 1;
[, $range] = explode('=', $range, 2);
@ -408,7 +529,9 @@ class MediaController extends Controller
$end = (isset($range[1]) && is_numeric($range[1])) ? (int) $range[1] : $stream->getSize();
}
$end = ($end > $stream->getSize() - 1) ? $stream->getSize() - 1 : $end;
if ($end > $stream->getSize() - 1) {
$end = $stream->getSize() - 1;
}
$stream->seek($start);
header("Content-Type: $mime");
@ -419,15 +542,7 @@ class MediaController extends Controller
http_response_code(206);
ob_end_clean();
$buffer = 16348;
$readed = $start;
while ($readed < $end) {
if ($readed + $buffer > $end) {
$buffer = $end - $readed + 1;
}
echo $stream->read($buffer);
$readed += $buffer;
}
fpassthru($stream->detach());
exit(0);
}

View file

@ -3,7 +3,7 @@
namespace App\Controllers;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\UserRepository;
use App\Web\ValidationHelper;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
@ -21,7 +21,7 @@ class ProfileController extends Controller
*/
public function profile(Request $request, Response $response): Response
{
$user = make(UserQuery::class)->get($request, $this->session->get('user_id'), true);
$user = make(UserRepository::class)->get($request, $this->session->get('user_id'), true);
return view()->render($response, 'user/edit.twig', [
'profile' => true,
@ -38,7 +38,7 @@ class ProfileController extends Controller
*/
public function profileEdit(Request $request, Response $response, int $id): Response
{
$user = make(UserQuery::class)->get($request, $id, true);
$user = make(UserRepository::class)->get($request, $id, true);
/** @var ValidationHelper $validator */
$validator = make(ValidationHelper::class)

View file

@ -3,9 +3,12 @@
namespace App\Controllers;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\UserRepository;
use App\Web\Theme;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Exception\HttpBadRequestException;
use Slim\Exception\HttpInternalServerErrorException;
class SettingController extends Controller
{
@ -14,6 +17,7 @@ class SettingController extends Controller
* @param Response $response
*
* @return Response
* @throws HttpInternalServerErrorException
*/
public function saveSettings(Request $request, Response $response): Response
{
@ -34,13 +38,14 @@ class SettingController extends Controller
// quota
$this->updateSetting('quota_enabled', param($request, 'quota_enabled', 'off'));
$this->updateSetting('default_user_quota', stringToBytes(param($request, 'default_user_quota', '1G')));
$user = make(UserQuery::class)->get($request, $this->session->get('user_id'));
$user = make(UserRepository::class)->get($request, $this->session->get('user_id'));
$this->setSessionQuotaInfo($user->current_disk_quota, $user->max_disk_quota);
$this->updateSetting('custom_head', param($request, 'custom_head'));
$this->updateSetting('recaptcha_enabled', param($request, 'recaptcha_enabled', 'off'));
$this->updateSetting('recaptcha_site_key', param($request, 'recaptcha_site_key'));
$this->updateSetting('recaptcha_secret_key', param($request, 'recaptcha_secret_key'));
$this->updateSetting('image_embeds', param($request, 'image_embeds'));
$this->applyTheme($request);
$this->applyLang($request);
@ -63,25 +68,29 @@ class SettingController extends Controller
}
}
/**
* @param Request $request
* @throws HttpInternalServerErrorException
*/
public function applyTheme(Request $request)
{
if (param($request, 'css') !== null) {
if (!is_writable(BASE_DIR.'static/bootstrap/css/bootstrap.min.css')) {
$this->session->alert(lang('cannot_write_file'), 'danger');
} else {
file_put_contents(BASE_DIR.'static/bootstrap/css/bootstrap.min.css', file_get_contents(param($request, 'css')));
}
$css = param($request, 'css');
if ($css === null) {
return;
}
// if is default, remove setting
if (param($request, 'css') !== 'https://bootswatch.com/_vendor/bootstrap/dist/css/bootstrap.min.css') {
$this->updateSetting('css', param($request, 'css'));
} else {
$this->database->query('DELETE FROM `settings` WHERE `key` = \'css\'');
}
if (!is_writable(BASE_DIR.'static/bootstrap/css/bootstrap.min.css')) {
$this->session->alert(lang('cannot_write_file'), 'danger');
throw new HttpInternalServerErrorException($request);
}
make(Theme::class)->applyTheme($css);
// if is default, remove setting
if ($css !== Theme::default()) {
$this->updateSetting('css', $css);
} else {
$this->database->query('DELETE FROM `settings` WHERE `key` = \'css\'');
}
}
@ -92,9 +101,15 @@ class SettingController extends Controller
private function updateSetting($key, $value = null)
{
if (!$this->database->query('SELECT `value` FROM `settings` WHERE `key` = '.$this->database->getPdo()->quote($key))->fetch()) {
$this->database->query('INSERT INTO `settings`(`key`, `value`) VALUES ('.$this->database->getPdo()->quote($key).', ?)', $value);
$this->database->query(
'INSERT INTO `settings`(`key`, `value`) VALUES ('.$this->database->getPdo()->quote($key).', ?)',
$value
);
} else {
$this->database->query('UPDATE `settings` SET `value`=? WHERE `key` = '.$this->database->getPdo()->quote($key), $value);
$this->database->query(
'UPDATE `settings` SET `value`=? WHERE `key` = '.$this->database->getPdo()->quote($key),
$value
);
}
}
}

View file

@ -3,7 +3,7 @@
namespace App\Controllers;
use App\Database\Queries\TagQuery;
use App\Database\Repositories\TagRepository;
use App\Web\ValidationHelper;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
@ -12,7 +12,6 @@ use Slim\Exception\HttpNotFoundException;
class TagController extends Controller
{
/**
* @param Request $request
* @param Response $response
@ -27,7 +26,7 @@ class TagController extends Controller
throw new HttpBadRequestException($request);
}
[$id, $limit] = make(TagQuery::class)->addTag(param($request, 'tag'), param($request, 'mediaId'));
[$id, $limit] = make(TagRepository::class)->addTag(param($request, 'tag'), param($request, 'mediaId'));
$this->logger->info("Tag added $id.");
@ -53,7 +52,7 @@ class TagController extends Controller
throw new HttpBadRequestException($request);
}
$result = make(TagQuery::class)->removeTag(param($request, 'tagId'), param($request, 'mediaId'));
$result = make(TagRepository::class)->removeTag(param($request, 'tagId'), param($request, 'mediaId'));
if ($result === null) {
throw new HttpNotFoundException($request);

View file

@ -123,8 +123,8 @@ class UpgradeController extends Controller
public function checkForUpdates(Request $request, Response $response): Response
{
$jsonResponse = [
'status' => null,
'message' => null,
'status' => 'OK',
'message' => lang('already_latest_version'),
'upgrade' => false,
];
@ -133,17 +133,18 @@ class UpgradeController extends Controller
try {
$json = $this->getApiJson();
$jsonResponse['status'] = 'OK';
foreach ($json as $release) {
if (version_compare($release->tag_name, PLATFORM_VERSION, '>') && ($release->prerelease === $acceptPrerelease)) {
if (
$release->prerelease === $acceptPrerelease &&
version_compare($release->tag_name, PLATFORM_VERSION, '>') &&
version_compare($release->tag_name, '4.0.0', '<')
) {
$jsonResponse['message'] = lang('new_version_available', [$release->tag_name]);
$jsonResponse['upgrade'] = true;
break;
}
if (version_compare($release->tag_name, PLATFORM_VERSION, '<=')) {
$jsonResponse['message'] = lang('already_latest_version');
$jsonResponse['upgrade'] = false;
break;
}
}
@ -154,10 +155,10 @@ class UpgradeController extends Controller
return json($response, $jsonResponse);
}
/**
* @param Request $request
* @param Response $response
* @param Request $request
* @param Response $response
* @return Response
* @throws \Twig\Error\LoaderError
* @throws \Twig\Error\RuntimeError

View file

@ -2,8 +2,8 @@
namespace App\Controllers;
use App\Database\Queries\TagQuery;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\TagRepository;
use App\Database\Repositories\UserRepository;
use App\Exceptions\ValidationException;
use Exception;
use Psr\Http\Message\ResponseInterface as Response;
@ -45,7 +45,7 @@ class UploadController extends Controller
try {
$file = $this->validateFile($request, $response);
$user = make(UserQuery::class)->get($request, $this->session->get('user_id'));
$user = make(UserRepository::class)->get($request, $this->session->get('user_id'));
$this->validateUser($request, $response, $file, $user);
} catch (ValidationException $e) {
@ -123,7 +123,9 @@ class UploadController extends Controller
*/
protected function validateFile(Request $request, Response $response)
{
if ($request->getServerParams()['CONTENT_LENGTH'] > stringToBytes(ini_get('post_max_size'))) {
$iniValue = ini_get('post_max_size');
$maxPostSize = $iniValue === '0' ? INF : stringToBytes($iniValue);
if ($request->getServerParams()['CONTENT_LENGTH'] > $maxPostSize) {
$this->json['message'] = 'File too large (post_max_size too low?).';
throw new ValidationException(json($response, $this->json, 400));
@ -206,6 +208,7 @@ class UploadController extends Controller
$this->json['message'] = 'OK';
$this->json['url'] = urlFor("/{$user->user_code}/{$code}.{$fileInfo['extension']}");
$this->json['raw_url'] = urlFor("/{$user->user_code}/{$code}/raw.{$fileInfo['extension']}");
$this->logger->info("User $user->username uploaded new media.", [$mediaId]);
@ -223,8 +226,8 @@ class UploadController extends Controller
[$type, $subtype] = explode('/', $mime);
/** @var TagQuery $query */
$query = make(TagQuery::class);
/** @var TagRepository $query */
$query = make(TagRepository::class);
$query->addTag($type, $mediaId);
if ($type === 'application' || $subtype === 'gif') {

View file

@ -2,7 +2,7 @@
namespace App\Controllers;
use App\Database\Queries\UserQuery;
use App\Database\Repositories\UserRepository;
use App\Web\Mail;
use App\Web\ValidationHelper;
use League\Flysystem\FileNotFoundException;
@ -90,7 +90,7 @@ class UserController extends Controller
return redirect($response, route('user.create'));
}
make(UserQuery::class)->create(
make(UserRepository::class)->create(
param($request, 'email'),
param($request, 'username'),
param($request, 'password'),
@ -133,7 +133,7 @@ class UserController extends Controller
*/
public function edit(Request $request, Response $response, int $id): Response
{
$user = make(UserQuery::class)->get($request, $id);
$user = make(UserRepository::class)->get($request, $id);
return view()->render($response, 'user/edit.twig', [
'profile' => false,
@ -152,7 +152,7 @@ class UserController extends Controller
*/
public function update(Request $request, Response $response, int $id): Response
{
$user = make(UserQuery::class)->get($request, $id);
$user = make(UserRepository::class)->get($request, $id);
$user->max_disk_quota = -1;
/** @var ValidationHelper $validator */
@ -180,7 +180,7 @@ class UserController extends Controller
return redirect($response, route('user.edit', ['id' => $id]));
}
make(UserQuery::class)->update(
make(UserRepository::class)->update(
$user->id,
param($request, 'email'),
param($request, 'username'),
@ -215,7 +215,7 @@ class UserController extends Controller
*/
public function delete(Request $request, Response $response, int $id): Response
{
$user = make(UserQuery::class)->get($request, $id);
$user = make(UserRepository::class)->get($request, $id);
if ($user->id === $this->session->get('user_id')) {
$this->session->alert(lang('cannot_delete'), 'danger');
@ -239,7 +239,7 @@ class UserController extends Controller
*/
public function clearUserMedia(Request $request, Response $response, int $id): Response
{
$user = make(UserQuery::class)->get($request, $id, true);
$user = make(UserRepository::class)->get($request, $id, true);
$medias = $this->database->query('SELECT * FROM `uploads` WHERE `user_id` = ?', $user->id);
@ -269,7 +269,7 @@ class UserController extends Controller
*/
public function refreshToken(Request $request, Response $response, int $id): Response
{
$query = make(UserQuery::class);
$query = make(UserRepository::class);
$user = $query->get($request, $id, true);
$this->logger->info('User '.$this->session->get('username')." refreshed token of user $user->id.");

View file

@ -21,7 +21,7 @@ class Migrator
* Migrator constructor.
*
* @param DB $db
* @param string $schemaPath
* @param string|null $schemaPath
*/
public function __construct(DB $db, ?string $schemaPath)
{
@ -29,13 +29,13 @@ class Migrator
$this->schemaPath = $schemaPath;
}
public function migrate()
public function migrate(): void
{
$this->db->getPdo()->exec(file_get_contents($this->schemaPath.DIRECTORY_SEPARATOR.'migrations.sql'));
$files = glob($this->schemaPath.'/'.$this->db->getCurrentDriver().'/*.sql');
$names = array_map(function ($path) {
$names = array_map(static function ($path) {
return basename($path);
}, $files);
@ -51,11 +51,11 @@ class Migrator
if (basename($file) === $migration->name && $migration->migrated) {
$continue = true;
break;
} else {
if (basename($file) === $migration->name && !$migration->migrated) {
$exists = true;
break;
}
}
if (basename($file) === $migration->name && !$migration->migrated) {
$exists = true;
break;
}
}
if ($continue) {

View file

@ -1,20 +1,20 @@
<?php
namespace App\Database\Queries;
namespace App\Database\Repositories;
use App\Database\DB;
use League\Flysystem\FileNotFoundException;
use League\Flysystem\Filesystem;
use League\Flysystem\Plugin\ListWith;
class MediaQuery
class MediaRepository
{
const PER_PAGE = 21;
const PER_PAGE_ADMIN = 27;
public const PER_PAGE = 21;
public const PER_PAGE_ADMIN = 27;
const ORDER_TIME = 0;
const ORDER_NAME = 1;
const ORDER_SIZE = 2;
public const ORDER_TIME = 0;
public const ORDER_NAME = 1;
public const ORDER_SIZE = 2;
/** @var DB */
protected $db;
@ -62,7 +62,7 @@ class MediaQuery
* @param DB $db
* @param bool $isAdmin
* @param Filesystem $storage
* @return MediaQuery
* @return MediaRepository
*/
public static function make(DB $db, Filesystem $storage, bool $isAdmin)
{
@ -74,7 +74,7 @@ class MediaQuery
*
* @return $this
*/
public function withUserId($id)
public function withUserId($id): MediaRepository
{
$this->userId = $id;
@ -87,27 +87,31 @@ class MediaQuery
*
* @return $this
*/
public function orderBy(string $type = null, $mode = 'ASC')
public function orderBy(string $type = null, $mode = 'ASC'): MediaRepository
{
$this->orderBy = ($type === null) ? self::ORDER_TIME : $type;
$this->orderBy = $type ?? self::ORDER_TIME;
$this->orderMode = (strtoupper($mode) === 'ASC') ? 'ASC' : 'DESC';
return $this;
}
/**
* @param string $text
* @param string|null $text
*
* @return $this
*/
public function search(?string $text)
public function search(?string $text): MediaRepository
{
$this->text = $text;
return $this;
}
public function filterByTag($tagId)
/**
* @param $tagId
* @return $this
*/
public function filterByTag($tagId): MediaRepository
{
if ($tagId !== null) {
$this->tagId = (int) $tagId;
@ -117,7 +121,11 @@ class MediaQuery
}
public function run(int $page)
/**
* @param int $page
* @return $this
*/
public function run(int $page): MediaRepository
{
if ($this->orderBy == self::ORDER_SIZE) {
$this->runWithFileSort($page);
@ -128,7 +136,11 @@ class MediaQuery
return $this;
}
public function runWithDbSort(int $page)
/**
* @param int $page
* @return $this
*/
public function runWithDbSort(int $page): MediaRepository
{
$params = [];
if ($this->isAdmin) {
@ -170,7 +182,11 @@ class MediaQuery
return $this;
}
public function runWithFileSort(int $page)
/**
* @param int $page
* @return $this
*/
public function runWithFileSort(int $page): MediaRepository
{
$this->storage->addPlugin(new ListWith());
@ -192,26 +208,41 @@ class MediaQuery
array_multisort(array_column($files, 'size'), $this->buildOrderBy(), SORT_NUMERIC, $files);
$params = [];
$queryPagesParams = [];
if ($this->text !== null) {
if ($this->isAdmin) {
[$queryMedia,] = $this->buildAdminQueries();
[$queryMedia, $queryPages] = $this->buildAdminQueries();
} else {
[$queryMedia,] = $this->buildUserQueries();
[$queryMedia, $queryPages] = $this->buildUserQueries();
$params[] = $this->userId;
}
$params[] = '%'.htmlentities($this->text).'%';
$queryPagesParams = $params;
$paths = array_column($files, 'path');
} else {
if ($this->tagId !== null) {
$paths = array_column($files, 'path');
$ids = $this->getMediaIdsByTagId($this->tagId);
$queryMedia = 'SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `uploads`.`storage_path` IN ("'.implode('","', $paths).'") AND `uploads`.`id` IN ('.implode(',', $ids).')';
} elseif ($this->tagId !== null) {
if ($this->isAdmin) {
[, $queryPages] = $this->buildAdminQueries();
} else {
$files = array_slice($files, $offset, $limit, true);
$paths = array_column($files, 'path');
$queryMedia = 'SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `uploads`.`storage_path` IN ("'.implode('","', $paths).'")';
[, $queryPages] = $this->buildUserQueries();
$queryPagesParams[] = $this->userId;
}
$paths = array_column($files, 'path');
$ids = $this->getMediaIdsByTagId($this->tagId);
$queryMedia = 'SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `uploads`.`storage_path` IN ("'.implode('","', $paths).'") AND `uploads`.`id` IN ('.implode(',', $ids).')';
} else {
if ($this->isAdmin) {
[, $queryPages] = $this->buildAdminQueries();
} else {
[, $queryPages] = $this->buildUserQueries();
$queryPagesParams[] = $this->userId;
}
$files = array_slice($files, $offset, $limit, true);
$paths = array_column($files, 'path');
$queryMedia = 'SELECT `uploads`.*, `users`.`user_code`, `users`.`username` FROM `uploads` LEFT JOIN `users` ON `uploads`.`user_id` = `users`.`id` WHERE `uploads`.`storage_path` IN ("'.implode('","', $paths).'")';
}
$medias = $this->db->query($queryMedia, $params)->fetchAll();
@ -239,7 +270,7 @@ class MediaQuery
}
}
$this->pages = count($this->media) / $limit;
$this->pages = $this->db->query($queryPages, $queryPagesParams)->fetch()->count / $limit;
if ($this->text !== null || $this->tagId !== null) {
$this->media = array_slice($this->media, $offset, $limit, true);
@ -331,7 +362,7 @@ class MediaQuery
protected function getMediaIdsByTagId($tagId)
{
$mediaIds = $this->db->query('SELECT `upload_id` FROM `uploads_tags` WHERE `tag_id` = ?', $tagId)->fetchAll();
$ids = [];
$ids = [-1];
foreach ($mediaIds as $pivot) {
$ids[] = $pivot->upload_id;
}

View file

@ -1,14 +1,14 @@
<?php
namespace App\Database\Queries;
namespace App\Database\Repositories;
use App\Database\DB;
use PDO;
class TagQuery
class TagRepository
{
const PER_MEDIA_LIMIT = 10;
public const PER_MEDIA_LIMIT = 10;
/**
* @var DB

View file

@ -1,15 +1,16 @@
<?php
namespace App\Database\Queries;
namespace App\Database\Repositories;
use App\Database\DB;
use App\Web\Session;
use InvalidArgumentException;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Exception\HttpNotFoundException;
use Slim\Exception\HttpUnauthorizedException;
class UserQuery
class UserRepository
{
/**
* @var DB
@ -34,7 +35,7 @@ class UserQuery
/**
* @param DB $db
* @param Session|null $session
* @return UserQuery
* @return UserRepository
*/
public static function make(DB $db, Session $session = null)
{
@ -59,7 +60,7 @@ class UserQuery
if ($authorize) {
if ($this->session === null) {
throw new \InvalidArgumentException('The session is null.');
throw new InvalidArgumentException('The session is null.');
}
if ($user->id !== $this->session->get('user_id') && !$this->session->get('admin', false)) {
@ -135,19 +136,19 @@ class UserQuery
$copyRaw,
$id,
]);
} else {
return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=?, `max_disk_quota`=?, `ldap`=?, `hide_uploads`=?, `copy_raw`=? WHERE `id` = ?', [
$email,
$username,
$isAdmin,
$isActive,
$maxUserQuota,
$ldap,
$hideUploads,
$copyRaw,
$id,
]);
}
return $this->database->query('UPDATE `users` SET `email`=?, `username`=?, `is_admin`=?, `active`=?, `max_disk_quota`=?, `ldap`=?, `hide_uploads`=?, `copy_raw`=? WHERE `id` = ?', [
$email,
$username,
$isAdmin,
$isActive,
$maxUserQuota,
$ldap,
$hideUploads,
$copyRaw,
$id,
]);
}
/**

View file

@ -42,6 +42,7 @@ class ViewFactory
$twig->addFunction(new TwigFunction('inPath', 'inPath'));
$twig->addFunction(new TwigFunction('humanFileSize', 'humanFileSize'));
$twig->addFunction(new TwigFunction('param', 'param'));
$twig->addFunction(new TwigFunction('glue', 'glue'));
return new View($twig);
}

View file

@ -2,7 +2,6 @@
namespace App\Middleware;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
@ -16,7 +15,7 @@ class AdminMiddleware extends Middleware
*
* @throws HttpUnauthorizedException
*
* @return Response
* @return ResponseInterface
*/
public function __invoke(Request $request, RequestHandler $handler): ResponseInterface
{

View file

@ -2,10 +2,10 @@
namespace App\Middleware;
use GuzzleHttp\Psr7\Response;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Server\RequestHandlerInterface as RequestHandler;
use Slim\Psr7\Factory\ResponseFactory;
class AuthMiddleware extends Middleware
{
@ -18,16 +18,16 @@ class AuthMiddleware extends Middleware
public function __invoke(Request $request, RequestHandler $handler): ResponseInterface
{
if (!$this->session->get('logged', false)) {
$this->session->set('redirectTo', (string) $request->getUri());
$this->session->set('redirectTo', (string) $request->getUri()->getPath());
return redirect(new Response(), route('login.show'));
return redirect((new ResponseFactory())->createResponse(), route('login.show'));
}
if (!$this->database->query('SELECT `id`, `active` FROM `users` WHERE `id` = ? LIMIT 1', [$this->session->get('user_id')])->fetch()->active) {
$this->session->alert(lang('account_disabled'), 'danger');
$this->session->set('logged', false);
return redirect(new Response(), route('login.show'));
return redirect((new ResponseFactory())->createResponse(), route('login.show'));
}
return $handler->handle($request);

67
app/Web/Theme.php Normal file
View file

@ -0,0 +1,67 @@
<?php
namespace App\Web;
class Theme
{
public const DEFAULT_THEME_URL = 'https://bootswatch.com/4/_vendor/bootstrap/dist/css/bootstrap.min.css';
/**
* @return array
*/
public function availableThemes(): array
{
$apiJson = json_decode(file_get_contents('https://bootswatch.com/api/4.json'));
$default = [];
$default['Default - Bootstrap 4 default theme'] = self::DEFAULT_THEME_URL;
$bootswatch = [];
foreach ($apiJson->themes as $theme) {
$bootswatch["{$theme->name} - {$theme->description}"] = $theme->cssMin;
}
$apiJson = json_decode(file_get_contents('https://theme-park.dev/themes.json'));
$base = $apiJson->applications->xbackbone->base_css;
$themepark = [];
foreach ($apiJson->themes as $name => $urls) {
$themepark[$name] = "{$base},{$urls->url}";
}
return [
'default' => $default,
'bootswatch.com' => $bootswatch,
'theme-park.dev' => $themepark
];
}
/**
* @param string $input
* @return bool
*/
public function applyTheme(string $input): bool
{
[$vendor, $css] = explode('|', $input, 2);
if ($vendor === 'theme-park.dev') {
[$base, $theme] = explode(',', $css);
$data = file_get_contents(self::DEFAULT_THEME_URL).file_get_contents($base).file_get_contents($theme);
} else {
$data = file_get_contents($css ?? self::DEFAULT_THEME_URL);
}
return (bool) file_put_contents(
BASE_DIR.'static/bootstrap/css/bootstrap.min.css',
$data
);
}
/**
* @return string
*/
public static function default(): string
{
return 'default|'.self::DEFAULT_THEME_URL;
}
}

55
app/Web/UA.php Normal file
View file

@ -0,0 +1,55 @@
<?php
namespace App\Web;
class UA
{
/**
* bot user agent => perform link embed
* @var string[]
*/
private static $bots = [
'TelegramBot' => false,
'facebookexternalhit/' => false,
'Facebot' => false,
'curl/' => false,
'wget/' => false,
'WhatsApp/' => false,
'Slack' => false,
'Twitterbot/' => false,
'discord' => true,
// discord image bot
'Mozilla/5.0 (Macintosh; Intel Mac OS X 11.6; rv:92.0) Gecko/20100101 Firefox/92.0' => true,
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0' => true,
];
/**
* @param string $userAgent
* @return bool
*/
public static function isBot(string $userAgent): bool
{
foreach (self::$bots as $bot => $embedsLink) {
if (stripos($userAgent, $bot) !== false) {
return true;
}
}
return false;
}
/**
* @param string $userAgent
* @return false|string
*/
public static function embedsLinks(string $userAgent)
{
foreach (self::$bots as $bot => $embedsLink) {
if (stripos($userAgent, $bot) !== false) {
return $embedsLink;
}
}
return false;
}
}

View file

@ -73,6 +73,30 @@ if (!function_exists('isDisplayableImage')) {
}
}
if (!function_exists('isEmbeddable')) {
/**
* @param ?string $mime
*
* @return bool
*/
function isEmbeddable(?string $mime): bool
{
return in_array($mime, [
'image/apng',
'image/bmp',
'image/gif',
'image/x-icon',
'image/jpeg',
'image/png',
'image/tiff',
'image/webp',
'video/mp4',
'video/ogg',
'video/webm',
]);
}
}
if (!function_exists('stringToBytes')) {
/**
* @param $str
@ -93,13 +117,13 @@ if (!function_exists('stringToBytes')) {
switch ($last) {
case 't':
$val *= 1024;
// no break
// no break
case 'g':
$val *= 1024;
// no break
// no break
case 'm':
$val *= 1024;
// no break
// no break
case 'k':
$val *= 1024;
}
@ -260,7 +284,7 @@ if (!function_exists('param')) {
* @param string $name
* @param null $default
*
* @return string
* @return mixed
*/
function param(Request $request, string $name, $default = null)
{
@ -270,11 +294,7 @@ if (!function_exists('param')) {
$params = $request->getParsedBody();
}
if (isset($params[$name])) {
return $params[$name];
}
return $default;
return $params[$name] ?? $default;
}
}
@ -312,60 +332,6 @@ if (!function_exists('lang')) {
}
}
if (!function_exists('isBot')) {
/**
* @param string $userAgent
*
* @return bool
*/
function isBot(string $userAgent)
{
$bots = [
'TelegramBot',
'facebookexternalhit/',
'Facebot',
'curl/',
'wget/',
'WhatsApp/',
'Slack',
'Twitterbot/',
'discord',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0' // discord image bot
];
foreach ($bots as $bot) {
if (stripos($userAgent, $bot) !== false) {
return true;
}
}
return false;
}
}
if (!function_exists('isDiscord')) {
/**
* @param string $userAgent
*
* @return bool
*/
function isDiscord(string $userAgent): bool
{
$bots = [
'discord',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:38.0) Gecko/20100101 Firefox/38.0' // discord image bot
];
foreach ($bots as $bot) {
if (stripos($userAgent, $bot) !== false) {
return true;
}
}
return false;
}
}
if (!function_exists('mime2font')) {
/**
* Convert get the icon from the file mimetype.
@ -551,3 +517,14 @@ if (!function_exists('isSecure')) {
|| (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] === 443);
}
}
if (!function_exists('glue')) {
/**
* @param mixed ...$pieces
* @return string
*/
function glue(...$pieces): string
{
return '/'.implode('/', $pieces);
}
}

9
app/routes.php Normal file → Executable file
View file

@ -19,12 +19,13 @@ use App\Middleware\AuthMiddleware;
use App\Middleware\CheckForMaintenanceMiddleware;
use Slim\Routing\RouteCollectorProxy;
global $app;
$app->group('', function (RouteCollectorProxy $group) {
$group->get('/home[/page/{page}]', [DashboardController::class, 'home'])->setName('home');
$group->get('/upload', [UploadController::class, 'uploadWebPage'])->setName('upload.web.show');
$group->post('/upload/web', [UploadController::class, 'uploadWeb'])->setName('upload.web');
$group->get('/home/switchView', [DashboardController::class, 'switchView'])->setName('switchView');
$group->group('', function (RouteCollectorProxy $group) {
$group->get('/system/deleteOrphanFiles', [AdminController::class, 'deleteOrphanFiles'])->setName('system.deleteOrphanFiles');
$group->get('/system/recalculateUserQuota', [AdminController::class, 'recalculateUserQuota'])->setName('system.recalculateUserQuota');
@ -32,11 +33,11 @@ $app->group('', function (RouteCollectorProxy $group) {
$group->get('/system/themes', [AdminController::class, 'getThemes'])->setName('theme');
$group->post('/system/settings/save', [SettingController::class, 'saveSettings'])->setName('settings.save');
$group->post('/system/upgrade', [UpgradeController::class, 'upgrade'])->setName('system.upgrade');
$group->get('/system/checkForUpdates', [UpgradeController::class, 'checkForUpdates'])->setName('system.checkForUpdates');
$group->get('/system/changelog', [UpgradeController::class, 'changelog'])->setName('system.changelog');
$group->get('/system', [AdminController::class, 'system'])->setName('system');
$group->get('/users[/page/{page}]', [UserController::class, 'index'])->setName('user.index');
@ -56,11 +57,13 @@ $app->group('', function (RouteCollectorProxy $group) {
$group->post('/user/{id}/refreshToken', [UserController::class, 'refreshToken'])->setName('refreshToken');
$group->get('/user/{id}/config/sharex', [ClientController::class, 'getShareXConfig'])->setName('config.sharex');
$group->get('/user/{id}/config/script', [ClientController::class, 'getBashScript'])->setName('config.script');
$group->get('/user/{id}/config/kde_script', [ClientController::class, 'getKDEScript'])->setName('kde_config.script');
$group->get('/user/{id}/export', [ExportController::class, 'downloadData'])->setName('export.data');
$group->post('/upload/{id}/publish', [MediaController::class, 'togglePublish'])->setName('upload.publish');
$group->post('/upload/{id}/unpublish', [MediaController::class, 'togglePublish'])->setName('upload.unpublish');
$group->post('/upload/{id}/vanity', [MediaController::class, 'createVanity'])->setName('upload.vanity');
$group->get('/upload/{id}/raw', [MediaController::class, 'getRawById'])->add(AdminMiddleware::class)->setName('upload.raw');
$group->map(['GET', 'POST'], '/upload/{id}/delete', [MediaController::class, 'delete'])->setName('upload.delete');

View file

@ -1,6 +1,6 @@
#!/usr/bin/env php
<?php
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.2 or above is required to run XBackBone.');
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 3) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.3 or above is required to run XBackBone.');
if (PHP_SAPI !== 'cli') {
die();
}

View file

@ -1,6 +1,6 @@
#!/usr/bin/env php
<?php
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.2 or above is required to run XBackBone.');
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 3) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.3 or above is required to run XBackBone.');
if (PHP_SAPI !== 'cli') {
die();
}

View file

@ -1,36 +0,0 @@
#!/usr/bin/env php
<?php
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.2 or above is required to run XBackBone.');
if (PHP_SAPI !== 'cli') {
die();
}
require __DIR__ . '/../vendor/autoload.php';
chdir(__DIR__ . '/../');
$json = json_decode(file_get_contents('https://bootswatch.com/api/4.json'));
if (!isset($argv[1])) {
echo 'Usage: php bin\\theme <theme-name|"default">' . PHP_EOL;
echo 'Here a list of available Bootswatch themes:' . PHP_EOL;
}
if (isset($argv[1]) && strtolower($argv[1]) === 'default') {
file_put_contents('static/bootstrap/css/bootstrap.min.css', file_get_contents('https://bootswatch.com/_vendor/bootstrap/dist/css/bootstrap.min.css'));
echo "Reverted to default theme." . PHP_EOL;
} else {
foreach ($json->themes as $theme) {
if (isset($argv[1]) && strtolower($argv[1]) === strtolower($theme->name)) {
file_put_contents('static/bootstrap/css/bootstrap.min.css', file_get_contents($theme->cssMin));
echo "Installed theme {$theme->name}." . PHP_EOL;
break;
}
if (!isset($argv[1])) {
echo " - {$theme->name} ({$theme->description})[Preview: {$theme->preview}]" . PHP_EOL;
}
}
}
exit(0);

View file

@ -3,6 +3,8 @@
use App\Database\DB;
use App\Web\Lang;
use Aws\S3\S3Client;
use League\Flysystem\Cached\CachedAdapter;
use League\Flysystem\Cached\Storage\Adapter;
use function DI\factory;
use function DI\get;
use Google\Cloud\Storage\StorageClient;
@ -46,57 +48,61 @@ return [
Filesystem::class => factory(function (Container $container) {
$config = $container->get('config');
switch ($config['storage']['driver']) {
case 'local':
return new Filesystem(new Local($config['storage']['path']));
case 's3':
$client = new S3Client([
'credentials' => [
'key' => $config['storage']['key'],
'secret' => $config['storage']['secret'],
],
'region' => $config['storage']['region'],
'endpoint' => $config['storage']['endpoint'],
'version' => 'latest',
'@http' => ['stream' => true],
]);
$driver = $config['storage']['driver'];
if ($driver === 'local') {
return new Filesystem(new Local($config['storage']['path']));
} elseif ($driver === 's3') {
$client = new S3Client([
'credentials' => [
'key' => $config['storage']['key'],
'secret' => $config['storage']['secret'],
],
'region' => $config['storage']['region'],
'endpoint' => $config['storage']['endpoint'],
'version' => 'latest',
'use_path_style_endpoint' => $config['storage']['use_path_style_endpoint'] ?? false,
'@http' => ['stream' => true],
]);
return new Filesystem(new AwsS3Adapter($client, $config['storage']['bucket'], $config['storage']['path']));
case 'dropbox':
$client = new DropboxClient($config['storage']['token']);
$adapter = new AwsS3Adapter($client, $config['storage']['bucket'], $config['storage']['path']);
} elseif ($driver === 'dropbox') {
$client = new DropboxClient($config['storage']['token']);
return new Filesystem(new DropboxAdapter($client), ['case_sensitive' => false]);
case 'ftp':
return new Filesystem(new FtpAdapter([
'host' => $config['storage']['host'],
'username' => $config['storage']['username'],
'password' => $config['storage']['password'],
'port' => $config['storage']['port'],
'root' => $config['storage']['path'],
'passive' => $config['storage']['passive'],
'ssl' => $config['storage']['ssl'],
'timeout' => 30,
]));
case 'google-cloud':
$client = new StorageClient([
'projectId' => $config['storage']['project_id'],
'keyFilePath' => $config['storage']['key_path'],
]);
$adapter = new DropboxAdapter($client);
} elseif ($driver === 'ftp') {
$adapter = new FtpAdapter([
'host' => $config['storage']['host'],
'username' => $config['storage']['username'],
'password' => $config['storage']['password'],
'port' => $config['storage']['port'],
'root' => $config['storage']['path'],
'passive' => $config['storage']['passive'],
'ssl' => $config['storage']['ssl'],
'timeout' => 30,
]);
} elseif ($driver === 'google-cloud') {
$client = new StorageClient([
'projectId' => $config['storage']['project_id'],
'keyFilePath' => $config['storage']['key_path'],
]);
return new Filesystem(new GoogleStorageAdapter($client, $client->bucket($config['storage']['bucket'])));
case 'azure':
$client = BlobRestProxy::createBlobService(
sprintf(
'DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;',
$config['storage']['account_name'],
$config['storage']['account_key']
)
);
$adapter = new GoogleStorageAdapter($client, $client->bucket($config['storage']['bucket']));
} elseif ($driver === 'azure') {
$client = BlobRestProxy::createBlobService(
sprintf(
'DefaultEndpointsProtocol=https;AccountName=%s;AccountKey=%s;',
$config['storage']['account_name'],
$config['storage']['account_key']
)
);
return new Filesystem(new AzureBlobStorageAdapter($client, $config['storage']['container_name']));
default:
throw new InvalidArgumentException('The driver specified is not supported.');
$adapter = new AzureBlobStorageAdapter($client, $config['storage']['container_name']);
} else {
throw new InvalidArgumentException('The driver specified is not supported.');
}
$cache = new Adapter(new Local(BASE_DIR.'resources/cache/fs'), 'file', 300); // 5min
return new Filesystem(new CachedAdapter($adapter, $cache));
}),
'storage' => get(Filesystem::class),

View file

@ -1,37 +1,38 @@
{
"name": "sergix44/xbackbone",
"license": "AGPL-3.0-only",
"version": "3.4.0",
"version": "3.7.0",
"description": "A lightweight ShareX PHP backend",
"type": "project",
"require": {
"php": ">=7.2",
"php": ">=7.3",
"ext-filter": "*",
"ext-gd": "*",
"ext-intl": "*",
"ext-json": "*",
"ext-pdo": "*",
"ext-zip": "*",
"erusev/parsedown": "^1.7",
"guzzlehttp/psr7": "^1.6",
"http-interop/http-factory-guzzle": "^1.0",
"intervention/image": "^2.4",
"intervention/image": "^2.6",
"league/flysystem": "^1.1.4",
"league/flysystem-aws-s3-v3": "^1.0",
"league/flysystem-azure-blob-storage": "^0.1.6",
"league/flysystem-cached-adapter": "^1.1",
"maennchen/zipstream-php": "^2.0",
"monolog/monolog": "^1.23",
"php-di/slim-bridge": "^3.0",
"sapphirecat/slim4-http-interop-adapter": "^1.0",
"slim/psr7": "^1.5",
"slim/slim": "^4.0",
"spatie/flysystem-dropbox": "^1.0",
"superbalist/flysystem-google-storage": "^7.2",
"twig/twig": "^2.12"
"twig/twig": "^2.14"
},
"config": {
"optimize-autoloader": true,
"preferred-install": "dist",
"sort-packages": true,
"platform": {
"php": "7.2.34"
"php": "7.3.33"
}
},
"autoload": {
@ -47,10 +48,12 @@
"Tests\\": "tests/"
}
},
"minimum-stability": "dev",
"prefer-stable": true,
"require-dev": {
"roave/security-advisories": "dev-latest",
"phpstan/phpstan": "^0.11.5",
"phpunit/phpunit": "7.5",
"phpunit/phpunit": "^9.0",
"symfony/dom-crawler": "^4.4"
}
}

3697
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1 @@
<script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-1835087833720665" crossorigin="anonymous"></script>

1
docs/ads.txt Normal file
View file

@ -0,0 +1 @@
google.com, pub-1835087833720665, DIRECT, f08c47fec0942fa0

View file

@ -5,6 +5,77 @@ nav_order: 9
---
# Changelog
## [3.7.0] - 2024-01-14
### Added
- Added support for vanity urls.
- Added KDE integration for linux script.
### Changed
- Updated translations.
- File preview is now clickable to open the file.
### Fixed
- Fixes for LDAP authentication.
## [3.6.3] - 2023-05-27
### Fixed
- Fix LDAP for php >= 8.1
## [3.6.2] - 2023-05-24
### Changed
- Support for PHP 8.2
### Removed
- Azure blob storage driver
## [3.6.1] - 2022-11-27
### Changed
- Upgraded dependencies
- Updated translations
### Fixed
- Fixed error in export data (#499)
- Fixed issues with reverse proxies (#495)
- Fixed duplicated twitter tags (#496)
## [3.6.0] - 2022-06-20
### Changed
- Improved embedding on discord of large videos.
- Releases are now compressed for faster downloads
- Updated translations
### Fixed
- Fixed deprecation notices on php >= 8
- Fixed embed UA for Discord.
- Fixed error with post_max_size = 0
### Removed
- Support for php 7.2
## [3.5.1] - 2021-10-22
### Changed
- Fixed embed UA for Discord.
- Updated translations.
## [3.5.0] - 2021-09-05
### Added
- Support for theme-park.dev themes.
- Updated translations.
### Fixed
- Wrong css when reapplying the default theme.
### Removed
- Dropped theme cli command.
## [3.4.1] - 2021-08-11
### Added
- Toggle to disable embeds.
### Changed
- Raw url copying now contains also the file extension.
## [3.4.0] - 2021-08-01
### Added
- Added image support for OG for Discord only.

View file

@ -16,6 +16,12 @@ and paste the URL copied from XBackBone, and all should work out-of-the-box.
If for whatever reason you need to change the instance url or the token, just edit the settings of the XBackBone plugin.
## MagicCap (Mac and Linux)
MagicCap supports the same file format used by ShareX.
Just download the ShareX config file from your profile, and then on MagicCap open the Preferences > Uploader settings and choose ShareX.
Set the path to the file you have downloaded, and you are good to go!
## uPic (Mac)
This tool does not support plugins or custom configuration, but you can configure it manually:
In preferences, you should add "Custom" host and configure it as follows:
@ -39,4 +45,4 @@ You can use this feature in combination with tools like [Flameshot](https://gith
The script requires `xclip`, `curl`, and `notify-send` on a desktop distribution.
*Note: XXX is the username of your XBackBone account.*
*Note: XXX is the username of your XBackBone account.*

View file

@ -38,7 +38,7 @@ return array(
'username' => 'xbackbone', // null, if sqlite
'password' => 's3cr3t', // null, if sqlite
),
)
);
```
## LDAP Authentication
@ -57,7 +57,7 @@ return array(
'base_domain' => 'dc=example,dc=com', // the base_dn string
'user_domain' => 'ou=Users', // the user dn string
'rdn_attribute' => 'uid=', // the attribute to identify the user
)
),
);
```
@ -67,15 +67,15 @@ return array(
...
'ldap' => array(
'enabled' => true, // enable it
'schema' => 'ldap' // use 'ldap' or 'ldaps' Default is 'ldap'
'schema' => 'ldap', // use 'ldap' or 'ldaps' Default is 'ldap'
'host' => 'ad.example.com', // set the ldap host
'port' => 389, // ldap port
'base_domain' => 'dc=example,dc=com', // the base_dn string
'search_filter' => '(&((objectClass=user)(sAMAccountName=????)))' // ???? is replaced with user provided username
'search_filter' => '(&(objectClass=user)(sAMAccountName=????))', // ???? is replaced with user provided username
'rdn_attribute' => 'sAMAccountName', // the attribute to use as username
'service_account_dn' => 'cn=xbackbone,cn=Users,dc=example,dc=com', // LDAP Service Account Full DN
'service_account_password' => 'examplepassword'
)
'service_account_password' => 'examplepassword',
),
);
```
@ -85,8 +85,8 @@ return array(
...
'ldap' => array(
'schema' => 'ldaps', //defaults to 'ldap'
'port' => 636
)
'port' => 636,
),
);
```
@ -96,8 +96,8 @@ return array(
...
'ldap' => array(
...
'useStartTLS' => true //defaults to false
)
'useStartTLS' => true, //defaults to false
),
);
```
The 'schema' => 'ldaps' and 'useStartTLS'=> true configuration directives are mutually exclusive. Do no use them together.
@ -116,7 +116,7 @@ return array(
'storage' => array (
'driver' => 'local',
'path' => '/path/to/storage/folder',
)
),
);
```
@ -131,7 +131,7 @@ return array(
'region' => 'the-region',
'bucket' => 'bucket-name',
'path' => 'optional/path/prefix',
)
),
);
```
For any filesystem S3-compatible, it's possible to specify an `endpoint` (for i.e. Minio)
@ -146,7 +146,7 @@ return array(
'region' => 'the-region',
'bucket' => 'bucket-name',
'path' => 'optional/path/prefix',
)
),
);
```
@ -157,7 +157,7 @@ return array(
'storage' => array (
'driver' => 'dropbox',
'token' => 'the-token',
)
),
);
```
@ -174,7 +174,7 @@ return array(
'path' => 'the/prefix/path/',
'passive' => true/false,
'ssl' => true/false,
)
),
);
```
@ -187,20 +187,7 @@ return array(
'project_id' => 'the-project-id',
'key_path' => 'the-key-path',
'bucket' => 'bucket-name',
)
);
```
+ Azure Blob Storage
```php
return array(
...
'storage' => array (
'driver' => 'azure',
'account_name' => 'the-storage-account-name',
'account_key' => 'the-account-key',
'container_name' => 'container-name',
)
),
);
```

View file

@ -7,7 +7,7 @@ nav_order: 2
# Installation
### Prerequisites
XBackBone require PHP >= `7.2`, with installed the required extensions:
XBackBone require PHP >= `7.3`, with installed the required extensions:
+ `php-sqlite3` for SQLite.
+ `php-mysql` for MariaDB/MySQL.
+ `php-gd` image manipualtion library.
@ -65,4 +65,4 @@ For futher and advanced configurations, see the [configuration page](configurati
## Docker deployment
Alternatively, a docker container is available.
[Docker container](https://hub.docker.com/r/pe46dro/xbackbone-docker){: .btn .btn-purple }
[Docker container](https://fleet.linuxserver.io/image?name=linuxserver/xbackbone){: .btn .btn-purple }

View file

@ -1,6 +1,6 @@
<?php
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 2) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.2 or above is required to run XBackBone.');
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 3) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.3 or above is required to run XBackBone.');
require __DIR__.'/vendor/autoload.php';
define('BASE_DIR', realpath(__DIR__).DIRECTORY_SEPARATOR);

View file

@ -1,6 +1,6 @@
<?php
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 1) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.1 or above is required to run XBackBone.');
((PHP_MAJOR_VERSION >= 7 && PHP_MINOR_VERSION >= 3) || PHP_MAJOR_VERSION > 7) ?: die('Sorry, PHP 7.3 or above is required to run XBackBone.');
require __DIR__.'/../vendor/autoload.php';
use App\Database\Migrator;
@ -9,13 +9,13 @@ use App\Web\Session;
use App\Web\View;
use DI\Bridge\Slim\Bridge;
use DI\ContainerBuilder;
use function DI\factory;
use function DI\get;
use function DI\value;
use League\Flysystem\FileExistsException;
use Psr\Container\ContainerInterface as Container;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use function DI\factory;
use function DI\get;
use function DI\value;
define('PLATFORM_VERSION', json_decode(file_get_contents(__DIR__.'/../composer.json'))->version);
define('BASE_DIR', realpath(__DIR__.'/../').DIRECTORY_SEPARATOR);
@ -175,12 +175,12 @@ $app->post('/', function (Request $request, Response $response, \DI\Container $c
$storage = $container->get('storage');
// check if the storage is valid
$storageTestFile = 'storage_test.xbackbone.txt';
$storageTestFile = 'storage_test.txt';
try {
try {
$success = $storage->write($storageTestFile, 'XBACKBONE_TEST_FILE');
$success = $storage->write($storageTestFile, 'TEST_FILE');
} catch (FileExistsException $fileExistsException) {
$success = $storage->update($storageTestFile, 'XBACKBONE_TEST_FILE');
$success = $storage->update($storageTestFile, 'TEST_FILE');
}
if (!$success) {
@ -212,11 +212,8 @@ $app->post('/', function (Request $request, Response $response, \DI\Container $c
// re-apply the previous theme if is present
$css = $db->query('SELECT `value` FROM `settings` WHERE `key` = \'css\'')->fetch()->value ?? null;
if ($css) {
$content = file_get_contents($css);
if ($content !== false) {
file_put_contents(BASE_DIR.'static/bootstrap/css/bootstrap.min.css', $content);
}
if ($css && strpos($css, '|') !== false) {
$container->make(\App\Web\Theme::class)->applyTheme($css);
}
// if is upgrading and existing installation, put it out maintenance

1949
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -1,26 +1,26 @@
{
"dependencies": {
"@fortawesome/fontawesome-free": "^5.15.2",
"bootstrap": "^4.6.0",
"bootstrap": "^4.6.1",
"bootstrap4-toggle": "^3.6.1",
"clipboard": "^2.0.7",
"dropzone": "^5.8.0",
"clipboard": "^2.0.10",
"dropzone": "^5.9.3",
"highlightjs": "^9.16.2",
"highlightjs-line-numbers.js": "^2.8.0",
"jquery": "^3.6.0",
"plyr": "^3.6.4",
"plyr": "^3.6.12",
"popper.js": "^1.16.1",
"tooltip.js": "^1.3.3"
},
"devDependencies": {
"grunt": "^1.3.0",
"grunt": "^1.5.3",
"grunt-contrib-compress": "^2.0.0",
"grunt-contrib-copy": "^1.0.0",
"grunt-contrib-cssmin": "^3.0.0",
"grunt-contrib-jshint": "^2.1.0",
"grunt-contrib-jshint": "^3.1.1",
"grunt-contrib-uglify": "^4.0.1",
"grunt-contrib-watch": "^1.1.0",
"grunt-shell": "^3.0.1",
"grunt-zip": "^0.18.2",
"load-grunt-tasks": "^4.0.0"
}
}

View file

@ -17,9 +17,9 @@ return [
'pager.next' => 'التالي',
'pager.previous' => 'السابق',
'copy_link' => 'نسخ الرابط',
'public.telegram' => 'مشاركة عبر تلغرام',
'public.delete_text' => 'هل تريد بالتأكيد حذف هذا العنصر؟ سيحذف نهائيا!',
'preview' => 'السابق',
'public.telegram' => 'شارك على تيليجرام',
'public.delete_text' => 'هل أنت متأكد من أنك تريد حذف هذا العنصر؟ لن تتمكن من استعادته',
'preview' => 'استعراض',
'filename' => 'اسم الملف',
'size' => 'حجم',
'public' => 'عام',
@ -33,7 +33,7 @@ return [
'hide' => 'إخفاء',
'files' => 'ملفات',
'theme' => 'سمة',
'click_to_load' => 'انقر للتحميل...',
'click_to_load' => 'انقر للتحميل',
'apply' => 'تطبيق',
'save' => 'حفظ',
'used' => 'مستخدَم',
@ -59,13 +59,13 @@ return [
'account_disabled' => 'حسابك معطل.',
'welcome' => 'مرحبا، %s!',
'goodbye' => 'وداعا!',
'email_required' => 'البريد الإلكتروني مطلوب.',
'email_taken' => 'البريد الإلكتروني قيد الاستخدام.',
'email_required' => 'عنوان البريد الإلكتروني مطلوب.',
'email_taken' => 'عنوان البريد الإلكتروني قيد الاستخدام بالفعل.',
'username_required' => 'اسم المستخدم مطلوب.',
'username_taken' => 'اسم المستخدم قيد الاستخدام.',
'password_required' => 'كلمة المرور مطلوبة.',
'user_created' => 'المستخدم "%s" أنشئ!',
'user_updated' => 'المستخدم "%s" تم تحديثه!',
'user_created' => 'تم إنشاء المستخدم "٪s"!',
'user_updated' => 'تم تحديث المستخدم "%s"!',
'profile_updated' => 'تم تحديث الملف الشخصي بنجاح!',
'user_deleted' => 'تم حذف المستخدم.',
'cannot_delete' => 'لا يمكنك حذف نفسك.',
@ -73,8 +73,8 @@ return [
'switch_to' => 'تبديل إلى',
'gallery' => 'معرض',
'table' => 'جدول',
'dotted_search' => 'بحث...',
'order_by' => 'ترتيب حسب...',
'dotted_search' => 'بحث',
'order_by' => 'ترتيب حسب',
'time' => 'وقت',
'name' => 'اسم',
'maintenance' => 'صيانة',
@ -88,7 +88,7 @@ return [
'updates' => 'تحديثات',
'cancel' => 'إلغاء',
'auto_set' => 'حدد تلقائيا',
'prerelease_channel' => 'قناة إصدار تجريبي',
'prerelease_channel' => 'قناة ما قبل الإصدار',
'drop_to_upload' => 'انقر أو اسحب ملفاتك هنا للرفع.',
'donation' => 'تبرع',
'remember_me' => 'تذكرني',
@ -101,7 +101,7 @@ return [
'password_recovery' => 'استعادة كلمة المرور',
'no_account' => 'لا تملك حسابا؟',
'register' => 'تسجيل',
'register_success' => 'تم إنشاء الحساب، تم إرسال رسالة تأكيد إلكترونية.',
'register_success' => 'تم إنشاء الحساب، تم إرسال رسالة تأكيد عبر البريد الإلكتروني.',
'mail.activate_account' => '%s - تفعيل الحساب',
'mail.recover_password' => '%s - استعادة كلمة المرور',
'recover_email_sent' => 'إن وجد، سيتم إرسال رسالة إلكترونية لاستعادة كلمة المرور إلى الحساب المحدد.',
@ -115,6 +115,51 @@ return [
'clear_account' => 'مسح الحساب',
'account_media_deleted' => 'كل الوسائط في الحساب تم حذفها.',
'danger_zone' => 'منطقة خطرة',
'send_notification' => 'إرسال رسالة إشعار إلكترونية',
'send_notification' => 'إرسال إشعار بالبريد الإلكتروني',
'mail.new_account' => '%s - إنشاء حساب جديد',
'php_info' => 'معلومات الPHP',
'enforce_language' => 'فرض اللغة',
'image_embeds' => 'تضمين الصور',
'token_not_found' => 'لم يتم العثور على الرمز المميز المحدد.',
'clean_orphaned_uploads' => 'تنظيف التحميلات المعزولة',
'show_all_tags' => 'إظهار جميع العلامات',
'cannot_demote' => 'لا يمكنك تخفيض رتبتك.',
'recaptcha_secret_key' => 'المفتاح السري reCAPTCHA',
'recaptcha_failed' => 'فشل reCAPTCHA',
'recaptcha_enabled' => 'تم تفعيل reCAPTCHA',
'default_user_quota' => 'الحصة الافتراضية للمستخدم',
'invalid_quota' => 'قيم غير صالحة كحصة مستخدم افتراضية.',
'copy_url_behavior' => 'نسخ وضع الرابط',
'token' => 'الرمز المميز',
'vanity_url' => 'رابط مخصص',
'orphaned_files' => 'الملفات المعزولة',
'copied' => 'تم النسخ إلى الحافظة!',
'client_config' => 'إعدادات العميل',
'deleted_orphans' => 'تم حذف %d من الملفات المعزولة بنجاح.',
'maintenance_in_progress' => 'المنصة تحت الصيانة، حاول مرة أخرى لاحقاً…',
'default_lang_behavior' => 'سيحاول XBackBone مطابقة لغة المتصفح افتراضيا (الاحتياطي هو الإنجليزية).',
'no_upload_token' => 'ليس لديك رمز مميز شخصي للتحميل. (قم بإنشاء واحد وحاول مرة أخرى.)',
'donate_text' => 'إذا كنت تحب XBackBone، ففكر في التبرع لدعم التطوير!',
'custom_head_html' => 'محتوى رأس HTML مخصص',
'custom_head_html_hint' => 'ستتم إضافة هذا المحتوى عند علامة <head> في كل صفحة.',
'custom_head_set' => 'تم تطبيق رأس HTML المخصص.',
'max_user_quota' => 'الحد الأقصى لحصة المستخدم',
'quota_enabled' => 'تفعيل حصة المستخدم',
'recalculate_user_quota' => 'إعادة حساب حصة المستخدم من القرص',
'mail.activate_text' => 'مرحبًا %s!<br>شكرًا لك على إنشاء حسابك على %s (<a href="%s">%s</a>)، انقر على الرابط التالي لتفعيله:<br><br><a href="%s">%s</a>',
'quota_recalculated' => 'تمت إعادة حساب حصة المستخدم من القرص بنجاح.',
'only_recaptcha_v3' => 'يتم دعم reCAPTCHA v3 فقط.',
'recaptcha_site_key' => 'مفتاح موقع reCAPTCHA',
'ldap_cant_connect' => 'لا يمكن الاتصال بخادم مصادقة LDAP.',
'upload_max_file_size' => 'الحد الأقصى لحجم الملف حاليًا هو %s.',
'zip_ext_not_loaded' => 'لم يتم تحميل الامتداد "zip" المطلوب',
'no_tags' => 'لم تتم إضافة أي علامات',
'changelog' => 'سجل التغيير',
'show_changelog' => 'عرض سجل التغيير',
'auto_tagging' => 'تحميل العلامات تلقائيًا',
'recaptcha_keys_required' => 'جميع مفاتيح reCAPTCHA مطلوبة.',
'user_create_password' => 'إذا تركت فارغة، فقد تحتاج إلى إرسال إعلام إلى عنوان البريد الإلكتروني للمستخدم.',
'mail.recover_text' => 'مرحبًا %s،<br>لقد تم طلب إعادة تعيين كلمة المرور لحسابك. لإكمال الإجراء انقر على الرابط التالي:<br><br><a href="%s">%s</a><br><br>إذا لم تكن أنت من طلب إعادة تعيين كلمة المرور، فما عليك سوى تجاهل هذا البريد الإلكتروني.',
'mail.new_account_text_with_reset' => 'مرحبًا %s!<br>تم إنشاء حساب جديد لك على %s (<a href="%s">%s</a>)، انقر على الرابط التالي لتعيين كلمة مرور وتنشيطها:<br ><br><a href="%s">%s</a>',
'mail.new_account_text_with_pw' => 'مرحبًا %s!<br>تم إنشاء حساب جديد لك على %s (<a href="%s">%s</a>)، باستخدام بيانات الاعتماد التالية:<br><br>اسم المستخدم: %s <br>كلمة المرور: %s<br><br>انقر على الرابط التالي للانتقال إلى صفحة تسجيل الدخول:<br><a href="%s">%s</a>',
];

View file

@ -19,7 +19,7 @@ return [
'pager.previous' => 'Предишно',
'copy_link' => 'Копирай линк',
'public.telegram' => 'Сподели по Telegram',
'public.delete_text' => 'Сигурни ли сте, че искате да изтриете това? Ще изчезне завинаги!',
'public.delete_text' => 'Наистина ли искате да изтриете този елемент? Няма да можете да го възстановите',
'preview' => 'Предварителен преглед',
'filename' => 'Файлово име',
'size' => 'Размер',
@ -34,7 +34,7 @@ return [
'files' => 'Файлове',
'orphaned_files' => 'Загубени файлове',
'theme' => 'Тема',
'click_to_load' => 'Натиснете за да заредите...',
'click_to_load' => 'Щракнете за зареждане…',
'apply' => 'Приложи',
'save' => 'Запомни',
'used' => 'Използвано',
@ -58,15 +58,107 @@ return [
'installed' => 'Инсталацията завърши успешно!',
'welcome' => 'Добре дошли, %s!',
'goodbye' => 'Довиждане!',
'email_required' => мейлът е необходим.',
'email_taken' => 'Имейлът вече се използва.',
'email_required' => зисква се имейл адрес.',
'email_taken' => 'Имейл адресът вече се използва.',
'username_required' => 'Потребителското име е необходимо.',
'username_taken' => 'Потребителското име вече е заето.',
'password_required' => 'Паролата е необходима.',
'password_required' => 'Паролата е задължителна.',
'user_created' => 'Потребител „%s“ бе създаден!',
'user_updated' => 'Потребител „%s“ бе обновен!',
'profile_updated' => 'Профилът бе обновен успешно!',
'user_deleted' => 'Потребителят бе изтрит.',
'cannot_delete' => 'Не можете да изтриете себе си.',
'gallery' => 'Галерия',
'image_embeds' => 'Вграждане на изображения',
'bad_login' => 'Грешни идентификационни данни.',
'account_disabled' => 'Вашият акаунт е деактивиран.',
'copied' => 'Копирано в клипборда!',
'none' => 'Нито един',
'open' => 'Отвори',
'token_not_found' => 'Посоченият токен не е намерен.',
'cannot_demote' => 'Не можете да се понижавате.',
'cannot_write_file' => 'Пътят на дестинацията не е за запис.',
'deleted_orphans' => 'Успешно изтрити %d осиротели файла.',
'switch_to' => 'Преминат към',
'table' => 'Таблица',
'time' => 'Време',
'name' => 'Име',
'maintenance' => 'Поддръжка',
'clean_orphaned_uploads' => 'Изчистване на остарели качвания',
'path_not_writable' => 'Изходният път не е за запис.',
'already_latest_version' => 'Вече имате най-новата версия.',
'new_version_available' => 'Налична е нова версия %s!',
'cannot_retrieve_file' => 'Файлът не може да бъде извлечен.',
'upgrade' => 'Подобряване',
'updates' => 'Надстройки',
'auto_set' => 'Задайте автоматично',
'default_lang_behavior' => 'XBackBone ще се опита да съвпадне с езика на браузъра по подразбиране (резервният вариант е английски).',
'donation' => 'Дарение',
'donate_text' => 'Ако харесвате XBackBone, помислете за дарение в подкрепа на развитието!',
'custom_head_html' => 'Персонализирано съдържание на HTML Head',
'custom_head_html_hint' => 'Това съдържание ще бъде добавено към маркера <head> на всяка страница.',
'custom_head_set' => 'Приложена е персонализирана HTML Head.',
'remember_me' => 'Помни ме',
'please_wait' => 'Моля изчакай…',
'dont_close' => 'Не затваряйте този раздел до приключване.',
'copy_url_behavior' => 'Режим на копиране на URL',
'dotted_search' => 'Търсене…',
'order_by' => 'Подредени по…',
'file_size_no_match' => 'Изтегленият файл не съответства на правилния размер на файла.',
'check_for_updates' => 'Провери за актуализации',
'no_account' => 'Нямате акаунт?',
'default_user_quota' => 'Потребителска квота по подразбиране',
'register' => 'Регистрация',
'max_user_quota' => 'Максимална потребителска квота',
'invalid_quota' => 'Невалидни стойности като потребителска квота по подразбиране.',
'account_activated' => 'Акаунтът е активиран, сега можете да влезете!',
'quota_enabled' => 'Активиране на потребителска квота',
'password_restored' => 'Нулиране на паролата.',
'quota_recalculated' => 'Потребителската квота е преизчислена от диска успешно.',
'delete_selected' => 'Изтрий избраното',
'delete_all' => 'Изтриване на всички',
'account_media_deleted' => 'Всички медии в акаунта са изтрити.',
'danger_zone' => 'Опасна зона',
'recaptcha_failed' => 'reCAPTCHA неуспешно',
'recaptcha_enabled' => 'reCAPTCHA е активирана',
'recaptcha_keys_required' => 'Всички ключове reCAPTCHA са задължителни.',
'recaptcha_site_key' => 'Ключ на сайта reCAPTCHA',
'send_notification' => 'Изпращане на известие по имейл',
'mail.new_account' => '%s - Създаване на нов акаунт',
'user_create_password' => 'Ако се остави празно, може да искате да изпратите известие до имейл адреса на потребителя.',
'ldap_cant_connect' => 'Не може да се свърже към LDAP сървъра за удостоверяване.',
'upload_max_file_size' => 'Максималният размер на файла в момента е %s.',
'no_tags' => 'Няма добавени тагове',
'auto_tagging' => 'Маркиране за автоматично качване',
'zip_ext_not_loaded' => 'Необходимото разширение "zip" не е заредено',
'changelog' => 'Регистър на промените',
'show_changelog' => 'Показване на регистъра на промените',
'register_success' => 'Акаунтът е създаден, изпратен е имейл за потвърждение.',
'recover_email_sent' => 'Ако е налице, имейл за възстановяване е изпратен до посочения акаунт.',
'mail.recover_password' => '%s - Възстановяване на парола',
'php_info' => 'PHP информация',
'system_settings' => 'Системни настройки',
'upload' => 'Качване',
'prerelease_channel' => 'Предварителен канал',
'settings_saved' => 'Системните настройки са запазени!',
'export_data' => 'Експортиране на данни',
'cancel' => 'Отмяна',
'no_upload_token' => 'Нямате личен токен за качване. (Генерирайте един и опитайте отново.)',
'maintenance_in_progress' => 'Платформата е в процес на поддръжка, опитайте отново по-късно…',
'drop_to_upload' => 'Щракнете или пуснете вашите файлове тук, за да ги качите.',
'register_enabled' => 'Регистрациите са активирани',
'hide_by_default' => 'Скриване на медиите по подразбиране',
'password_recovery' => 'Възстановяване на парола',
'mail.activate_text' => 'Здравейте %s!<br>благодаря ви, че създадохте своя акаунт в %s (<a href="%s">%s</a>), щракнете върху следната връзка, за да го активирате:<br><br>< a href="%s">%s</a>',
'mail.activate_account' => '%s - Активиране на акаунт',
'mail.recover_text' => 'Здравейте %s,<br>за вашия акаунт бе поискано нулиране на паролата. За да завършите процедурата, щракнете върху следната връзка:<br><br><a href="%s">%s</a><br><br>Ако не вие сте поискали нулирането на паролата, просто игнорирайте този имейл.',
'password_match' => 'Паролата и повторната парола трябва да са еднакви.',
'recalculate_user_quota' => 'Преизчисляване на потребителската квота от диска',
'password_repeat' => 'Повтори паролата',
'recaptcha_secret_key' => 'Секретен ключ на reCAPTCHA',
'mail.new_account_text_with_reset' => 'Здравейте %s!<br>за вас беше създаден нов акаунт на %s (<a href="%s">%s</a>), щракнете върху следната връзка, за да зададете парола и да я активирате:<br ><br><a href="%s">%s</a>',
'used_space' => 'Използвано пространство',
'clear_account' => 'Изчистване на акаунта',
'only_recaptcha_v3' => 'Поддържа се само reCAPTCHA v3.',
'mail.new_account_text_with_pw' => 'Здравейте %s!<br>за вас бе създаден нов акаунт на %s (<a href="%s">%s</a>) със следните идентификационни данни:<br><br>Потребителско име: %s <br>Парола: %s<br><br>Щракнете върху следната връзка, за да отидете на страницата за вход:<br><a href="%s">%s</a>',
];

163
resources/lang/ca.lang.php Normal file
View file

@ -0,0 +1,163 @@
<?php
return [
'no_media' => 'Sense medis.',
'raw' => 'Mostra raw',
'lang' => 'Anglès',
'enforce_language' => 'Aplicar idioma',
'no' => 'No',
'send' => 'Envia',
'login.username' => 'Nom d\'usuari o Email',
'password' => 'Contrasenya',
'login' => 'Registre',
'username' => 'Nom Usuari',
'home' => 'Casa',
'copy_link' => 'Copiar Link',
'public.telegram' => 'Compartir a Telegram',
'public.delete_text' => 'Segur que vols esborrar l\'element? No el podràs recuperar',
'preview' => 'Vista prèvia',
'filename' => 'Nom Arxiu',
'size' => 'Mida',
'public' => 'Public',
'owner' => 'Propietari',
'date' => 'Data',
'upload' => 'Puja',
'delete' => 'Esborra',
'hide' => 'Oculta',
'files' => 'Arxius',
'orphaned_files' => 'Arxius orfes',
'theme' => 'Tema',
'click_to_load' => 'Click per pujar…',
'apply' => 'Aplicar',
'save' => 'Guardar',
'used' => 'Usat',
'php_info' => 'Informació PHP',
'system_settings' => 'Opcions de Sistema',
'user.create' => 'Crear Usuari',
'user.edit' => 'Editar Usuari',
'is_active' => 'Està Actiu',
'is_admin' => 'és administrador',
'your_profile' => 'el teu perfil',
'token' => 'Token',
'copy' => 'Copiar',
'copied' => 'Copiat al portaretalls!',
'client_config' => 'Configuració Client',
'user_code' => 'Codi Usuari',
'active' => 'Actiu',
'reg_date' => 'Data Registre',
'none' => 'Cap',
'open' => 'Obert',
'confirm' => 'Confirmació',
'confirm_string' => 'Estàs segur?',
'installed' => 'Instal·lació satisfactòria!',
'bad_login' => 'Credencials Errònies.',
'account_disabled' => 'Compte Deshabilitat.',
'goodbye' => 'Adéu!',
'token_not_found' => 'Token no trobat.',
'email_taken' => 'Compte de correu en ús.',
'username_required' => 'Nom usuari Requerit.',
'username_taken' => 'Nom d\'usuari ja en ús.',
'password_required' => 'Contrasenya requerida.',
'user_created' => 'Usuari "%s" creat!',
'user_updated' => 'Usuari "%s" actualitzat!',
'profile_updated' => 'Perfil Actualitzat!',
'user_deleted' => 'Usuari esborrat.',
'cannot_delete' => 'No pots esborrar.-te.',
'cannot_demote' => 'No et pots degradar.',
'cannot_write_file' => 'No es pot escriure al path.',
'deleted_orphans' => '%d Fitxers orfes esborrats.',
'dotted_search' => 'Cerca…',
'order_by' => 'Endreça per.…',
'time' => 'Temps',
'name' => 'Nom',
'maintenance' => 'Manteniment',
'clean_orphaned_uploads' => 'Neteja càrregues orfes',
'path_not_writable' => 'No es pot escriure al path de sortida.',
'already_latest_version' => 'Ja estàs a la darrera versió.',
'new_version_available' => 'Nova versió %s disponible!',
'cannot_retrieve_file' => 'No es pot recuperar el fitxer.',
'file_size_no_match' => 'El fitxer baixat no coincideix amb la mida correcta del fitxer.',
'upgrade' => 'Actualitza',
'maintenance_in_progress' => 'En manteniment, torna-ho a provar més tard…',
'cancel' => 'Cancel·la',
'auto_set' => 'Estableix automàticament',
'default_lang_behavior' => 'XBackBone intentarà fer coincidir l\'idioma del navegador de manera predeterminada (la alternativa és l\'anglès).',
'prerelease_channel' => 'Canal de preestrena',
'drop_to_upload' => 'Feu clic o deixeu anar els vostres fitxers aquí per carregar-los.',
'donation' => 'Donatiu',
'custom_head_html' => 'Contingut de capçalera HTML personalitzat',
'custom_head_set' => 'Capçalera HTML personalitzada aplicada.',
'remember_me' => 'Recorda\'m',
'please_wait' => 'Esperi…',
'dont_close' => 'No tanquis la pestanya.',
'register_enabled' => 'Registres habilitats',
'hide_by_default' => 'Amaga medis per defecte',
'copy_url_behavior' => 'Mode copia URL',
'password_recovery' => 'Recupera password',
'no_account' => 'No tens compte?',
'register' => 'Registre',
'register_success' => 'S\'ha creat el compte, s\'ha enviat un correu electrònic de confirmació.',
'default_user_quota' => 'Quota d\'usuari per defecte',
'max_user_quota' => 'Quota màxima d\'usuari',
'invalid_quota' => 'Valors no vàlids com a quota d\'usuari predeterminada.',
'mail.activate_account' => '%s - Activació del compte',
'mail.recover_password' => '%s - Recuperació de la contrasenya',
'recover_email_sent' => 'Si existeix, s\'enviarà un correu electrònic de recuperació al compte especificat.',
'account_activated' => 'Compte activat, ara pots iniciar sessió!',
'quota_enabled' => 'Activa la quota d\'usuari',
'password_repeat' => 'Repeteix Contrasenya',
'password_match' => 'Les contrasenyes han de coincidir.',
'password_restored' => 'Contrasenya restablerta.',
'recalculate_user_quota' => 'Torneu a calcular la quota d\'usuari del disc',
'quota_recalculated' => 'La quota d\'usuari s\'ha recalculat des del disc correctament.',
'used_space' => 'Espai Utilitzat',
'delete_selected' => 'Esborra seleccionat',
'delete_all' => 'Esborra Tot',
'clear_account' => 'Esborra el compte',
'account_media_deleted' => 'S\'han suprimit tots els mitjans del compte.',
'danger_zone' => 'Zona Perillosa',
'recaptcha_failed' => 'reCAPTCHA Erroni',
'recaptcha_keys_required' => 'Calen totes les claus reCAPTCHA.',
'only_recaptcha_v3' => 'Només s\'admet reCAPTCHA v3.',
'recaptcha_site_key' => 'Clau del lloc reCAPTCHA',
'recaptcha_secret_key' => 'Clau secreta reCAPTCHA',
'send_notification' => 'Envia notificació per e-mail',
'mail.new_account' => '%s - Creació nou Compte',
'users' => 'Usuaris',
'system' => 'Sistema',
'mail.new_account_text_with_pw' => 'Hola, %s!<br>s\'ha creat un compte nou a %s (<a href="%s">%s</a>), amb les credencials següents:<br><br>Nom d\'usuari: %s <br>Contrasenya: %s<br><br>Feu clic a l\'enllaç següent per anar a la pàgina d\'inici de sessió:<br><a href="%s">%s</a>',
'user_create_password' => 'Si es deixa buit, és possible que vulgueu enviar una notificació a l\'adreça de correu electrònic de l\'usuari.',
'ldap_cant_connect' => 'No es pot connectar al servidor d\'autenticació LDAP.',
'upload_max_file_size' => 'La mida màxima del fitxer és actualment %s.',
'no_tags' => 'Sense Etiquetes',
'auto_tagging' => 'Etiquetatge de càrrega automàtica',
'zip_ext_not_loaded' => 'L\'extensió "zip" necessària no està carregada',
'changelog' => 'Codi de canvis',
'show_changelog' => 'Mostra canvis',
'image_embeds' => 'Insereix imatges',
'yes' => 'Sí',
'profile' => 'Perfil',
'pager.previous' => 'Anterior',
'logout' => 'Tancar Sessió',
'pager.next' => 'Següent',
'publish' => 'Publica',
'download' => 'Descarrega',
'update' => 'Actualitza',
'admin' => 'Admin',
'edit' => 'Edita',
'welcome' => 'Benvolgut, %s!',
'email_required' => 'Adreça email requerida.',
'gallery' => 'Galeria',
'switch_to' => 'Canvia a',
'no_upload_token' => 'No tens cap testimoni de càrrega personal. (Genereu-ne un i torneu-ho a provar.)',
'table' => 'Taula',
'check_for_updates' => 'Comprova actualitzacions',
'updates' => 'Actualitzacions',
'donate_text' => 'Si t\'agrada XBackBone, considera una donació per donar suport al desenvolupament!',
'settings_saved' => 'Opcions de sistema gravades!',
'export_data' => 'Exporta dades',
'custom_head_html_hint' => 'Aquest contingut s\'afegirà a l\'etiqueta <head> de cada pàgina.',
'mail.activate_text' => 'Hola, %s!<br>gràcies per crear el vostre compte a %s (<a href="%s">%s</a>), feu clic a l\'enllaç següent per activar-lo:<br><br>< a href="%s">%s</a>',
'mail.recover_text' => 'Hola %s,<br>s\'ha sol·licitat un restabliment de la contrasenya per al vostre compte. Per completar el procediment, feu clic a l\'enllaç següent:<br><br><a href="%s">%s</a><br><br>Si no heu estat vosaltres qui heu sol·licitat la restabliment de la contrasenya, simplement ignora aquest correu electrònic.',
'recaptcha_enabled' => 'reCAPTCHA Habilitat',
'mail.new_account_text_with_reset' => 'Hola, %s!<br>s\'ha creat un compte nou a %s (<a href="%s">%s</a>), feu clic a l\'enllaç següent per establir una contrasenya i activar-la:<br ><br><a href="%s">%s</a>',
];

View file

@ -113,8 +113,8 @@ return [
'mail.new_account_text_with_reset' => 'Zdravíme, %s!<br>Byl pro vás vytvořen nový účet na %s (<a href="%s">%s</a>). Klikněte na následující odkaz pro nastavení hesla a aktivaci účtu:<br><br><a href="%s">%s</a>',
'mail.new_account' => '%s - tvorba nového účtu',
'send_notification' => 'Poslat e-mailové oznámení',
'recaptcha_secret_key' => 'reCAPTCHA Secret Key',
'recaptcha_site_key' => 'reCAPTCHA Site Key',
'recaptcha_secret_key' => 'reCAPTCHA Tajný klíč',
'recaptcha_site_key' => 'reCAPTCHA Webový Klíč',
'only_recaptcha_v3' => 'Je podporována pouze reCAPTCHA v3.',
'recaptcha_keys_required' => 'Jsou vyžadovány všechny klíče reCAPTCHA.',
'recaptcha_enabled' => 'reCAPTCHA povolena',
@ -159,4 +159,5 @@ return [
'donation' => 'Přispět',
'drop_to_upload' => 'Klikněte nebo sem přetáhněte soubory pro nahrání.',
'no_upload_token' => 'Nemáte osobní nahrávací token. (Vygenerujte si jej a zkuste to znovu.)',
'image_embeds' => 'Vložené obrázky',
];

View file

@ -18,7 +18,7 @@ return [
'pager.previous' => 'Forrige',
'copy_link' => 'Kopier link',
'public.telegram' => 'Del på Telegram',
'public.delete_text' => 'Er du sikker på du vil slette dette element? Du vil ikke kunne gendanne det',
'public.delete_text' => 'Er du sikker på, at du vil slette dette element? Du vil ikke være i stand til at gendanne den',
'preview' => 'Forhåndsvisning',
'filename' => 'Filnavn',
'size' => 'Størrelse',
@ -68,19 +68,19 @@ return [
'remember_me' => 'Husk mig',
'custom_head_html' => 'Tilpasset HTML Head indhold',
'donate_text' => 'Hvis du kan lide XBackBone, kan du overveje en donation for at støtte udviklingen!',
'donation' => 'Donation',
'donation' => 'Donering',
'drop_to_upload' => 'Klik eller slip dine filer her for at uploade.',
'auto_set' => 'Indstil automatisk',
'auto_set' => 'Sæt automatisk',
'cancel' => 'Annuller',
'maintenance_in_progress' => 'Platformen er under vedligeholdelse, prøv igen senere…',
'updates' => 'Opdateringer',
'upgrade' => 'Opgrader',
'check_for_updates' => 'Søg efter opdateringer',
'file_size_no_match' => 'Den downloadede fil matcher ikke den korrekte filstørrelse.',
'cannot_retrieve_file' => 'Kan ikke hente filen.',
'cannot_retrieve_file' => 'Filen kan ikke hentes.',
'new_version_available' => 'Ny version %s tilgængelig!',
'already_latest_version' => 'Du har allerede den seneste version.',
'maintenance' => 'Vedligehold',
'maintenance' => 'Vedligeholdelse',
'name' => 'Navn',
'time' => 'Tid',
'order_by' => 'Sorter efter…',
@ -92,14 +92,14 @@ return [
'cannot_demote' => 'Du kan ikke degradere dig selv.',
'cannot_delete' => 'Du kan ikke slette dig selv.',
'user_deleted' => 'Bruger slettet.',
'profile_updated' => 'Profil opdateret!',
'password_required' => 'Adgangskoden er krævet.',
'profile_updated' => 'Profilen blev opdateret!',
'password_required' => 'Adgangskoden er krævet.',
'username_taken' => 'Brugernavnet er allerede i brug.',
'username_required' => 'Brugernavnet er krævet.',
'username_required' => 'Brugernavnet er krævet.',
'goodbye' => 'Farvel!',
'welcome' => 'Velkommen, %s!',
'account_disabled' => 'Din konto er slået fra.',
'bad_login' => 'Forkerte legitimationsoplysninger.',
'account_disabled' => 'Din konto er deaktiveret.',
'bad_login' => 'Forkerte loginoplysninger.',
'installed' => 'Installationen blev gennemført!',
'confirm_string' => 'Er du sikker?',
'confirm' => 'Bekræftelse',
@ -117,6 +117,48 @@ return [
'token' => 'Nøgle',
'system_settings' => 'Systemindstillinger',
'php_info' => 'PHP Informationer',
'upload' => 'Upload',
'enforce_language' => 'Håndhæv sprog',
'upload' => 'Overfør',
'enforce_language' => 'Håndhæve sproget',
'deleted_orphans' => 'Slettet %d forældreløse filer.',
'default_lang_behavior' => 'XBackBone vil prøve at matche browsersproget som standard (tilbagefaldet er Engelsk).',
'prerelease_channel' => 'Forhåndsudgivelse Kanal',
'token_not_found' => 'Den angivne token blev ikke fundet.',
'clean_orphaned_uploads' => 'Fjern forældreløse overførsler',
'custom_head_set' => 'Brugerdefineret HTML-hoved anvendt.',
'dont_close' => 'Luk ikke denne fane, før den er færdig.',
'default_user_quota' => 'Standard bruger plads',
'max_user_quota' => 'Max bruger plads',
'invalid_quota' => 'Ugyldige værdier som standard bruger plads.',
'mail.activate_account' => '%s - Aktivering af konto',
'mail.recover_password' => '%s - Gendan adgangskode',
'password_restored' => 'Nulstil kodeord.',
'recalculate_user_quota' => 'Genberegn bruger plads fra disk',
'quota_recalculated' => 'Bruger pladsen genberegnet fra disken med succes.',
'account_media_deleted' => 'Alle medier på kontoen er blevet slettet.',
'danger_zone' => 'Farligt område',
'recaptcha_keys_required' => 'Alle reCAPTCHA nøgler er påkrævet.',
'recaptcha_site_key' => 'reCAPTCHA webstedsnøgle',
'recaptcha_secret_key' => 'reCAPTCHA hemmelig nøgle',
'mail.new_account_text_with_reset' => 'Hej %s!<br>en ny konto blev oprettet til dig den %s (<a href="%s">%s</a>), klik på følgende link for at indstille en adgangskode og aktivere den:<br><br><a href="%s">%s</a>',
'user_create_password' => 'Hvis den efterlades tom, vil det være en god idé selv at sende en meddelelse til brugerens e-mailadresse.',
'ldap_cant_connect' => 'Kan ikke oprette forbindelse til LDAP-godkendelsesserveren.',
'upload_max_file_size' => 'Den maksimale filstørrelse er i øjeblikket %s.',
'no_tags' => 'Ingen tags tilføjet',
'auto_tagging' => 'Automatisk upload tagging',
'zip_ext_not_loaded' => 'Den nødvendige "zip"-udvidelse er ikke indlæst',
'changelog' => 'Ændringslog',
'show_changelog' => 'Vis ændringslog',
'no_upload_token' => 'Du har ikke et personligt upload token. (Generer en og prøv igen.)',
'custom_head_html_hint' => 'Dette indhold vil blive tilføjet ved <head> tagget på hver side.',
'register_success' => 'Kontoen er oprettet, en bekræftelses-e-mail er blevet sendt.',
'quota_enabled' => 'Aktiver brugerkvote',
'mail.activate_text' => 'Hej %s!<br>tak fordi du oprettede din konto på %s (<a href="%s">%s</a>), klik på følgende link for at aktivere den:<br><br><a href="%s">%s</a>',
'mail.recover_text' => 'Hej %s,<br>der er blevet anmodet om en nulstilling af adgangskoden til din konto. For at fuldføre proceduren, klik på følgende link:<br><br><a href="%s">%s</a><br><br>Hvis det ikke var dig, der anmodede om nulstilling af adgangskoden, skal du blot ignorere denne e-mail.',
'recover_email_sent' => 'Hvis tilstede, blev der sendt en gendannelses-e-mail til den angivne konto.',
'password_match' => 'Adgangskode og den gentaget adgangskode skal være ens.',
'clear_account' => 'Ryd Konto',
'only_recaptcha_v3' => 'Kun reCAPTCHA v3 understøttes.',
'image_embeds' => 'Integrer billeder',
'mail.new_account_text_with_pw' => 'Hej %s!<br>en ny konto blev oprettet til dig den %s (<a href="%s">%s</a>), med følgende oplysninger:<br><br>Brugernavn: %s<br>Adgangskode: %s<br><br>Klik på følgende link for at gå til login-siden:<br><a href="%s">%s</a>',
'path_not_writable' => 'Outputstien er ikke skrivbar.',
];

View file

@ -54,7 +54,7 @@ return [
'reg_date' => 'Registrierungsdatum',
'none' => 'keine',
'open' => 'Öffnen',
'confirm' => 'Bestätigung',
'confirm' => 'Bestätigen',
'confirm_string' => 'Bist du sicher?',
'installed' => 'Installation erfolgreich abgeschlossen!',
'bad_login' => 'Falsche Anmeldeinformationen.',
@ -153,6 +153,7 @@ return [
'mail.new_account' => '%s Erstellung von Konto',
'user_create_password' => 'Wenn das leer bleibt, wollen Sie vielleicht eine Benachrichtigung an die Benutzer per E-Mail senden.',
'no_tags' => 'Keine Tags hinzugefügt',
'show_all_tags' => 'Alle Tags anzeigen',
'upload_max_file_size' => 'Die maximale Dateigröße beträgt derzeit %s.',
'ldap_cant_connect' => 'Es kann keine Verbindung zum LDAP-Auth-Server hergestellt werden.',
'zip_ext_not_loaded' => 'Die zip-Erweiterung ist erforderlich',
@ -164,4 +165,6 @@ return [
'show_changelog' => 'Änderungsprotokoll ansehen',
'changelog' => 'Änderungsprotokoll',
'copied' => 'In Zwischenablage kopiert!',
'image_embeds' => 'Bilder einbetten',
'vanity_url' => 'Benutzerdefinierte URL',
];

5
resources/lang/en.lang.php Normal file → Executable file
View file

@ -30,6 +30,8 @@ return [
'download' => 'Download',
'upload' => 'Upload',
'delete' => 'Delete',
'confirm' => 'Confirm',
'vanity_url' => 'Custom URL',
'publish' => 'Publish',
'hide' => 'Hide',
'files' => 'Files',
@ -58,7 +60,6 @@ return [
'reg_date' => 'Registration Date',
'none' => 'None',
'open' => 'Open',
'confirm' => 'Confirmation',
'confirm_string' => 'Are you sure?',
'installed' => 'Installation completed successfully!',
'bad_login' => 'Wrong credentials.',
@ -155,8 +156,10 @@ return [
'ldap_cant_connect' => 'Can\'t connect to the LDAP auth server.',
'upload_max_file_size' => 'The max file size is currently %s.',
'no_tags' => 'No tags added',
'show_all_tags' => 'Show all tags',
'auto_tagging' => 'Auto upload tagging',
'zip_ext_not_loaded' => 'The required "zip" extension is not loaded',
'changelog' => 'Changelog',
'show_changelog' => 'Show changelog',
'image_embeds' => 'Embed images'
];

View file

@ -18,7 +18,7 @@ return [
'pager.previous' => 'Previo',
'copy_link' => 'Copiar enlace',
'public.telegram' => 'Compartir en Telegram',
'public.delete_text' => '¿Está seguro que desea borrar este elemento? ¡Será borrado para siempre!',
'public.delete_text' => '¿Está seguro que desea borrar este elemento? No vas a poder recuperarlo',
'preview' => 'Vista previa',
'filename' => 'Nombre del archivo',
'size' => 'Tamaño',
@ -54,7 +54,7 @@ return [
'reg_date' => 'Fecha de Registración',
'none' => 'Ninguno',
'open' => 'Abrir',
'confirm' => 'Confirmación',
'confirm' => 'Confirmar',
'confirm_string' => '¿Está seguro?',
'installed' => '¡Instalación completa!',
'bad_login' => 'Credenciales incorrectas.',
@ -129,8 +129,8 @@ return [
'upload_max_file_size' => 'El tamaño máximo del archivo es actualmente %s.',
'ldap_cant_connect' => 'No se puede conectar con el servidor de autentificación LDAP.',
'user_create_password' => 'Si se deja vacío, es posible que desee enviar una notificación a la dirección de correo electrónico del usuario.',
'mail.new_account_text_with_pw' => 'Hola %s!<br>se ha creado una nueva cuenta para ti en %s (<a href="%s">%s</a>), haz clic en el siguiente enlace para establecer una contraseña y activarla:<br><br><a href="%s">%s</a>',
'mail.new_account_text_with_reset' => 'Hola %s!<br>se ha creado una nueva cuenta para ti en %s (<a href="%s">%s</a>), haz clic en el siguiente enlace para establecer una contraseña y activarla:<br><br><a href="%s">%s</a>',
'mail.new_account_text_with_pw' => '¡Hola %s!<br>se ha creado una nueva cuenta para ti en %s (<a href="%s">%s</a>), haz clic en el siguiente enlace para establecer una contraseña y activarla:<br><br><a href="%s">%s</a>',
'mail.new_account_text_with_reset' => '¡Hola, %s!<br>Se creó una nueva cuenta para ti en %s (<a href="%s">%s</a>), haz clic en el siguiente enlace para establecer una contraseña y activarla:<br ><br><a href="%s">%s</a>',
'recaptcha_enabled' => 'reCAPTCHA activado',
'account_media_deleted' => 'Se han eliminado todos los archivos de la cuenta.',
'clear_account' => 'Limpiar cuenta',
@ -144,7 +144,7 @@ return [
'mail.recover_text' => 'Hola %s,<br>se ha solicitado el restablecimiento de la contraseña de su cuenta. Para completar el procedimiento haga clic en el siguiente enlace:<br><br><a href="%s">%s</a><br>Si no fue usted quien solicitó el restablecimiento de la contraseña, simplemente ignore este correo electrónico.',
'mail.activate_text' => 'Hola %s!<br>gracias por crear tu cuenta en %s (<a href="%s">%s</a>), haz clic en el siguiente enlace para activarla:<br><br><a href="%s">%s</a>',
'invalid_quota' => 'Valores no válidos como cuota de usuario por defecto.',
'max_user_quota' => 'Cuota máxima del usuario',
'max_user_quota' => 'Cuota máxima del usuario',
'default_user_quota' => 'Cuota de usuarios por defecto',
'register' => 'Registrarse',
'no_account' => '¿No tienes cuenta?',
@ -159,4 +159,12 @@ return [
'remember_me' => 'Recuerdame',
'custom_head_html_hint' => 'Este contenido se añadirá en la etiqueta <head> de cada página.',
'custom_head_html' => 'Contenido personalizado del encabezado HTML',
'image_embeds' => 'Incrustar imágenes',
'recaptcha_keys_required' => 'Todas las claves reCAPTCHA son requeridas.',
'recaptcha_secret_key' => 'Clave secreta de reCAPTCHA',
'recaptcha_site_key' => 'Clave del sitio reCAPTCHA',
'only_recaptcha_v3' => 'Solo reCAPTCHA v3 está soportado.',
'custom_head_set' => 'Cabecera HTML personalizada aplicada.',
'vanity_url' => 'URL personalizada',
'show_all_tags' => 'Mostrar todas las etiquetas',
];

View file

@ -0,0 +1,29 @@
<?php
return [
'lang' => 'انگلیسی',
'login.username' => 'نام کاربری یا صندوق پستی الکترونیک',
'enforce_language' => 'اجرا کردن زبان',
'yes' => 'بله',
'send' => 'ارسال',
'no_media' => 'رسانه ای یافت نشد .',
'home' => 'خانه',
'users' => 'کاربران',
'system' => 'سیستم',
'profile' => 'حساب کاربری',
'logout' => 'خارج شدن',
'public.telegram' => 'اشتراک گذاری در تلگرام',
'public.delete_text' => 'آیا مطمعن به حذف این آیتم هستید ؟ غیرقابل بازیابی بعد از حذف',
'preview' => 'پیش نمایش',
'size' => 'سایز',
'public' => 'عمومی',
'owner' => 'مالک',
'date' => 'تاریخ',
'no' => 'خیر',
'password' => 'کلمه عبور',
'login' => 'وارد شدن',
'username' => 'نام کاربری',
'pager.next' => 'بعدی',
'pager.previous' => 'قبلی',
'copy_link' => 'رونوشت از پیوند',
'filename' => 'نام فایل',
];

View file

@ -17,7 +17,7 @@ return [
'token_not_found' => 'Määritettyä tunnusta ei löydy.',
'client_config' => 'Asiakasohjelman konfigurointi',
'home' => 'Koti',
'enforce_language' => 'Vahvista kieli',
'enforce_language' => 'Pakota kieli',
'cannot_demote' => 'Et voi alentaa itseäsi.',
'cannot_delete' => 'Et voi poistaa itseäsi.',
'user_deleted' => 'Käyttäjä poistettu.',
@ -35,7 +35,7 @@ return [
'bad_login' => 'Väärät kirjautumistiedot.',
'installed' => 'Asennus suoritettu loppuun onnistuneesti!',
'confirm_string' => 'Oletko varma?',
'confirm' => 'Vahvistus',
'confirm' => 'Vahvista',
'open' => 'Auki',
'none' => 'Ei mitään',
'reg_date' => 'Rekisteröitymis päivä',
@ -91,4 +91,74 @@ return [
'no' => 'Ei',
'yes' => 'Kyllä',
'lang' => 'Englanti',
'recaptcha_enabled' => 'reCAPTCHA Käytössä',
'cancel' => 'Peruuta',
'send_notification' => 'Lähetä sähköpostivahvistus',
'auto_set' => 'Määritä automaattisesti',
'drop_to_upload' => 'Lähetä tiedostosi painamalla tai tiputtamalla tähän.',
'account_activated' => 'Käyttäjä aktivoitu, voit nyt kirjautua sisään!',
'used_space' => 'Käytetty Tila',
'delete_selected' => 'Poista Valitut',
'delete_all' => 'Poista Kaikki',
'danger_zone' => 'Vaarallinen Alue',
'recaptcha_failed' => 'reCAPTCHA Epäonnistui',
'only_recaptcha_v3' => 'Vain reCAPTCHA v3 on tuettu.',
'upload_max_file_size' => 'Suurin tiedostokoko on tällä hetkellä %s.',
'changelog' => 'Muutosloki',
'show_changelog' => 'Näytä muutosloki',
'please_wait' => 'Odota…',
'hide_by_default' => 'Piilota media oletuksena',
'settings_saved' => 'Järjestelmäasetukset tallennettu!',
'export_data' => 'Vie dataa',
'dont_close' => 'Älä sulje tätä välilehteä ennen kuin on valmista.',
'donation' => 'Lahjoitus',
'donate_text' => 'Jos tykkäät XBackBone-sovelluksesta, harkitse lahjoittamista kannattaaksesi sovelluksen ohjelmointia/kehittämistä!',
'table' => 'Pöytä',
'check_for_updates' => 'Tarkista päivitykset',
'upgrade' => 'Päivitä',
'updates' => 'Päivitykset',
'maintenance_in_progress' => 'Alusta huollossa, yritä myöhemmin uudelleen…',
'password_recovery' => 'Palauta salasana',
'no_account' => 'Eikö sinulla ole käyttäjää?',
'register' => 'Rekisteröidy',
'register_success' => 'Käyttäjä on luotu, vahvistussähköposti on lähetetty.',
'mail.recover_password' => '%s - Salasanan Palautus',
'password_repeat' => 'Toista salasana',
'password_match' => 'Salasanan ja uudelleenkirjoitetun salasanan täytyy olla sama.',
'password_restored' => 'Salana nollattu.',
'image_embeds' => 'Kuvien upottaminen',
'recalculate_user_quota' => 'Käyttäjäkiintiön laskeminen uudelleen levyltä',
'quota_recalculated' => 'Käyttäjäkiintiö lasketaan uudelleen levyltä onnistuneesti.',
'recaptcha_secret_key' => 'reCAPTCHA:n salainen avain',
'recaptcha_keys_required' => 'Kaikki reCAPTCHA-näppäimet ovat pakollisia.',
'mail.new_account' => '%s - Uuden tilin luominen',
'no_tags' => 'Tunnisteita ei ole lisätty',
'auto_tagging' => 'Automaattisen latauksen taggaus',
'zip_ext_not_loaded' => 'Vaadittua "zip" -laajennusta ei ladata',
'remember_me' => 'Muista minut',
'copy_url_behavior' => 'Kopioi URL-osoite -tila',
'register_enabled' => 'Rekisteröinnit käytössä',
'no_upload_token' => 'Sinulla ei ole henkilökohtaista lataustunnusta. (Luo sellainen ja yritä uudelleen.)',
'custom_head_html_hint' => 'Tämä sisältö lisätään <head> jokaisen sivun tunnisteeseen.',
'custom_head_set' => 'Mukautettu HTML-pää käytössä.',
'file_size_no_match' => 'Ladattu tiedosto ei vastaa oikeaa tiedostokokoa.',
'prerelease_channel' => 'Ennakkojulkaisukanava',
'default_user_quota' => 'Käyttäjän oletuskiintiö',
'max_user_quota' => 'Käyttäjän enimmäiskiintiö',
'mail.activate_account' => '%s - Tilin aktivointi',
'recover_email_sent' => 'Jos sellainen on, tietylle tilille lähetettiin palautussähköpostiviesti.',
'clear_account' => 'Tyhjennä tili',
'user_create_password' => 'Jos sinut jätetään tyhjäksi, sinun kannattaa ehkä lähettää ilmoitus käyttäjän sähköpostiosoitteeseen.',
'default_lang_behavior' => 'XBackBone yrittää oletusarvoisesti vastata selaimen kieltä (vara on englanti).',
'mail.activate_text' => 'Hei %s! <br>kiitos, että loit tilisi %s(<a href="%s":lle">%s</a>), napsauta seuraavaa linkkiä aktivoidaksesi sen:<br><br><a href="%s">%s</a>',
'account_media_deleted' => 'Kaikki tilin mediat on poistettu.',
'mail.new_account_text_with_reset' => 'Hei %s! <br>sinulle luotiin uusi tili %s(<a href="%s">%s</a>), napsauta seuraavaa linkkiä asettaaksesi salasanan ja aktivoidaksesi sen:<br><br><a href="%s">%s</a>',
'mail.new_account_text_with_pw' => 'Hei %s! <br>sinulle luotiin uusi tili %s(<a href="%s">%s</a>), jolla on seuraavat tunnistetiedot:<br><br>Käyttäjänimi: %s<br>Salasana: %s<br><br>Napsauta seuraavaa linkkiä siirtyäksesi kirjautumissivulle:<br><a href="%s">%s</a>',
'ldap_cant_connect' => 'Yhteyden muodostaminen LDAP-todennuspalvelimeen ei onnistu.',
'recaptcha_site_key' => 'reCAPTCHA-sivuston avain',
'custom_head_html' => 'Mukautettu HTML Head -sisältö',
'invalid_quota' => 'Virheelliset arvot oletuskäyttäjäkiintiönä.',
'mail.recover_text' => 'Hei %s, <br>tilillesi on pyydetty salasanan palautusta. Suorita toimenpide napsauttamalla seuraavaa linkkiä:<br><br><a href="%s">%s</a><br><br>Jos et ollut sinä, joka pyysit salasanan vaihtamista, ohita tämä sähköposti.',
'quota_enabled' => 'Käyttäjäkiintiön ottaminen käyttöön',
'vanity_url' => 'Mukautettu URL',
];

View file

@ -54,7 +54,7 @@ return [
'reg_date' => 'Date d\'inscription',
'none' => 'Aucun',
'open' => 'Ouvrir',
'confirm' => 'Confirmation',
'confirm' => 'Confirmer',
'confirm_string' => 'Êtes-vous sûr·e ?',
'installed' => 'L\'installation s\'est déroulée avec succès!',
'bad_login' => 'Identifiant ou mot de passe incorrect.',
@ -161,4 +161,6 @@ return [
'changelog' => 'Journal des changements',
'zip_ext_not_loaded' => 'L\'extension zip requise n\'est pas chargée',
'copied' => 'Copié dans le presse-papier !',
'image_embeds' => 'Intégrer des images',
'vanity_url' => 'URL personnalisée',
];

View file

@ -64,7 +64,7 @@ return [
'cancel' => 'Annuler',
'maintenance_in_progress' => 'Plateforme en maintenance, réessayez plus tard…',
'updates' => 'Mises à jour',
'upgrade' => 'Mettre à jour',
'upgrade' => 'Mettre à niveau',
'check_for_updates' => 'Vérifier les mises à jour',
'file_size_no_match' => 'Le fichier téléchargé n\'a pas la taille correcte.',
'cannot_retrieve_file' => 'Impossible de retrouver le fichier.',
@ -107,7 +107,7 @@ return [
'lang' => 'Français (Canada)',
'mail.new_account_text_with_pw' => 'Bonjour %s! <br> un nouveau compte a été créé pour vous sur %s (<a href="%s">% s</a>), avec les informations d\'identification suivantes : <br> <br> Nom d\'utilisateur :%s <br> Mot de passe :%s <br> <br> Cliquez sur le lien suivant pour accéder à la page de connexion : <br> <a href="%s">%s </a>',
'maintenance' => 'Maintenance',
'confirm' => 'Confirmation',
'confirm' => 'Confirmer',
'user_create_password' => 'Si laissé vide, vous souhaiterez peut-être envoyer une notification à l\'utilisateur par courriel.',
'mail.new_account' => '%s Création d\'un nouveau compte',
'mail.recover_password' => '%s Récupération de mot de passe',
@ -159,4 +159,6 @@ return [
'yes' => 'Oui',
'enforce_language' => 'Forcer la langue',
'copied' => 'Copié dans le presse-papier!',
'image_embeds' => 'Intégrer des images',
'vanity_url' => 'URL personnalisée',
];

View file

@ -158,5 +158,7 @@ return [
'no' => 'Nem',
'yes' => 'Igen',
'enforce_language' => 'A nyelv érvényesítése',
'lang' => 'Angol',
'lang' => 'Magyar',
'image_embeds' => 'Képek beágyazása',
'vanity_url' => 'Egyedi URL',
];

View file

@ -159,4 +159,6 @@ return [
'password_match' => 'Kata sandi harus sama.',
'custom_head_set' => 'Head HTML khusus diterapkan.',
'path_not_writable' => 'Destinasi berkas tidak dapat ditulis.',
'image_embeds' => 'Sematkan gambar',
'vanity_url' => 'URL kostum',
];

View file

@ -39,10 +39,10 @@ return [
'save' => 'Salva',
'used' => 'Usato',
'system_info' => 'Informazioni di Sistema',
'user.create' => 'Crea Utente',
'user.edit' => 'Modifica Utente',
'is_active' => 'Attivo',
'is_admin' => 'Amministratore',
'user.create' => 'Crea utente',
'user.edit' => 'Modifica utente',
'is_active' => 'È attivo',
'is_admin' => 'È amministratore',
'your_profile' => 'Il tuo profilo',
'token' => 'Token',
'copy' => 'Copia',
@ -161,4 +161,6 @@ return [
'changelog' => 'Registro dei cambiamenti',
'show_changelog' => 'Mostra registro dei cambiamenti',
'copied' => 'Copiato negli appunti!',
'image_embeds' => 'Incorpora immagini',
'vanity_url' => 'URL personalizzato',
];

View file

@ -35,7 +35,7 @@ return [
'files' => 'ファイル',
'orphaned_files' => '所有者のいないファイル',
'theme' => 'テーマ',
'click_to_load' => 'クリックしてロード...',
'click_to_load' => 'クリックしてロード',
'apply' => '適用',
'save' => '保存',
'system_info' => 'システム情報',
@ -90,4 +90,25 @@ return [
'system_settings' => 'システム設定',
'php_info' => 'PHPの情報',
'used' => '使用済み',
'switch_to' => '転換する:',
'table' => 'テーブル形',
'name' => 'ファイル名順',
'clean_orphaned_uploads' => '所有者のないファイルを削除',
'already_latest_version' => 'もうすでに最新のXbackboneを使っています。',
'check_for_updates' => '更新を確認',
'updates' => '更新内容',
'cancel' => 'キャンセル',
'default_lang_behavior' => 'Xbackboneで使用者のブラウザの言語を自動的に検索Defaultは英語.',
'donation' => '支援',
'donate_text' => '支援も受け入れていますので、Xbackboneが気に入った場合、よろしくお願いいたします',
'custom_head_html' => 'HTML Headのコンテンツをカスタマイズ',
'register_enabled' => '登録を活性化',
'order_by' => '…順',
'custom_head_set' => 'HTML Headのカスタマイズが適用されました。',
'copied' => 'コピーしました!',
'custom_head_html_hint' => 'この部分に入力した内容は全てのページの<head></head>の中に入ります.',
'remember_me' => 'ログイン情報を保存',
'please_wait' => '少々お待ちください…',
'dont_close' => '作業を完了する前にはこのタブを閉じないでください。',
'no_upload_token' => 'アップロードのための個人トークンがありません。(まず新しく生成してもう一度試してください)',
];

164
resources/lang/ko.lang.php Normal file
View file

@ -0,0 +1,164 @@
<?php
return [
'zip_ext_not_loaded' => '필요한 "zip" 확장자가 불러와지지 않았어요',
'image_embeds' => '임베드 이미지',
'show_changelog' => '변경사항 보기',
'changelog' => '변경사항',
'auto_tagging' => '자동 업로드 태그 지정',
'no_tags' => '추가된 태그 없음',
'upload_max_file_size' => '최대 파일 크기는 %s 에요.',
'ldap_cant_connect' => 'LDAP 인증 서버에 연결할 수 없어요.',
'user_create_password' => '만약 비어 있다면, 사용자의 이메일로 알림을 보내는 게 좋을 거예요.',
'mail.new_account_text_with_reset' => '%s 님 안녕하세요!<br>%s(<a href="%s">%s</a>) 에 대한 새 계정이 생성되었어요, 다음 링크를 클릭하고 비밀번호를 설정하여 활성화 하세요:<br><br><a href="%s">%s</a>',
'mail.new_account_text_with_pw' => '%s 님 안녕하세요!<br>%s(<a href="%s">%s</a>) 에 대한 새 계정이 생성되었어요,<br><br>이름: %s<br>비밀번호: %s<br><br>다음 링크를 클릭하고 로그인하세요:<br><a href="%s">%s</a>',
'mail.new_account' => '%s - 새로운 계정 생성',
'send_notification' => '이메일 알림 보내기',
'recaptcha_secret_key' => '리캡챠 Secret Key',
'recaptcha_site_key' => '리캡챠 Site Key',
'only_recaptcha_v3' => '리캡챠 v3만 지원해요.',
'recaptcha_keys_required' => '모든 리캡챠 키가 필요해요.',
'recaptcha_enabled' => '리캡챠 켜기',
'recaptcha_failed' => '리캡챠 실패',
'danger_zone' => '위험 구역',
'account_media_deleted' => '계정의 모든 미디어가 삭제되었어요.',
'clear_account' => '계정 지우기',
'delete_all' => '모두 삭제하기',
'clean_orphaned_uploads' => '존재하지 않는 파일 삭제하기',
'delete_selected' => '선택한 항목 삭제',
'used_space' => '사용된 공간',
'quota_recalculated' => '사용자 할당량 계산이 완료되었어요.',
'recalculate_user_quota' => '디스크에서 사용자 할당량 다시 계산하기',
'password_match' => '비밀번호와 재입력 값은 같아야 해요.',
'password_restored' => '비밀번호 초기화.',
'password_repeat' => '비밀번호 재입력',
'quota_enabled' => '사용자 할당량 켜기',
'account_activated' => '계정이 활성화되었어요, 이제 로그인을 할 수 있을거에요!',
'recover_email_sent' => '존재하는 계정이라면, 복구용 이메일이 전송되었을 거예요.',
'mail.recover_password' => '%s - 암호 재설정',
'mail.recover_text' => '%s 님 안녕하세요,<br>암호 재설정이 요청되었어요. 완료하려면 다음 링크를 클릭해주세요:<br><br><a href="%s">%s</a><br><br>만약 재설정을 요청하지 않았다면, 그냥 이 이메일은 무시해도 괜찮아요.',
'mail.activate_account' => '%s - 계정 활성화',
'mail.activate_text' => '%s 님 안녕하세요!<br>%s에 계정을 만들어 주셔서 감사합니다(<a href="%s">%s</a>), 다음 링크를 클릭하여 활성화하세요:<br><br><a href="%s">%s</a>',
'invalid_quota' => '기본 사용자 할당량 값이 잘못됐어요.',
'max_user_quota' => '최대 사용자 할당량',
'default_user_quota' => '기본 사용자 할당량',
'register_success' => '계정이 생성되었으며, 확인 이메일이 전송되었어요.',
'register' => '가입하기',
'no_account' => '혹시 계정이 없으신가요?',
'password_recovery' => '비밀번호 찾기',
'export_data' => '파일 내보내기',
'settings_saved' => '시스템 설정을 저장했어요!',
'copy_url_behavior' => 'URL 복사 모드',
'hide_by_default' => '기본적으로 미디어 숨기기',
'register_enabled' => '회원가입 활성화',
'dont_close' => '완료될 때까지 창을 닫지 마세요...',
'please_wait' => '잠시만 기다려주세요…',
'remember_me' => '로그인 상태 유지',
'custom_head_set' => '커스텀 HTML Head를 적용했어요.',
'custom_head_html_hint' => '입력된 값은 모든 페이지의 <head> 태그에 적용될 거에요.',
'maintenance_in_progress' => '유지보수 중 이에요, 나중에 다시 시도해주세요…',
'custom_head_html' => '커스텀 HTML Head',
'donate_text' => 'XBackBone이 마음에 든다면, 개발 지원을 위한 후원을 고려해보세요!',
'donation' => '기부',
'drop_to_upload' => '파일을 업로드하려면 클릭하거나 여기에 놓아주세요.',
'no_upload_token' => '개인 업로드 토큰이 없어요. (생성하고 다시 시도해 주세요.)',
'prerelease_channel' => 'Prerelease 채널',
'default_lang_behavior' => '기본적으로 브라우저의 언어와 똑같이 설정할 거에요 (만약 없다면 영어로 선택될거에요).',
'auto_set' => '자동 설정',
'cancel' => '취소',
'updates' => '업데이트',
'upgrade' => '업그레이드',
'check_for_updates' => '업데이트 확인',
'file_size_no_match' => '다운로드한 파일의 크기가 올바르지 않아요.',
'cannot_retrieve_file' => '파일을 검색할 수 없어요.',
'new_version_available' => '새로운 버전 %s 이 존재해요!',
'already_latest_version' => '이미 최신버전을 사용하고 있어요.',
'path_not_writable' => '출력 경로에 쓸 수 없어요.',
'maintenance' => '관리',
'name' => '이름순',
'time' => '날짜순',
'order_by' => '정렬하기…',
'dotted_search' => '검색…',
'table' => '테이블뷰',
'gallery' => '갤러리뷰',
'switch_to' => '전환하기',
'deleted_orphans' => '%d 개의 존재하지 않는 파일을 삭제했어요.',
'orphaned_files' => '존재하지 않는 파일',
'cannot_write_file' => '대상 경로에는 쓸 수 없어요.',
'cannot_demote' => '나 자신을 강등시킬 순 없어요.',
'cannot_delete' => '나 자신을 삭제할 순 없죠.',
'user_deleted' => '사용자를 삭제했어요.',
'profile_updated' => '프로필이 정상적으로 업데이트 되었어요!',
'user_updated' => '사용자 "%s" 가 업데이트 되었어요!',
'user_created' => '사용자 "%s" 가 생성되었어요!',
'password_required' => '비밀번호가 필요해요.',
'username_taken' => '이 이름은 이미 사용 중이에요.',
'username_required' => '이름이 필요해요.',
'email_taken' => '이 이메일 주소는 이미 사용 중이에요.',
'email_required' => '이메일 주소가 필요해요.',
'token_not_found' => '토큰을 찾을 수 없어요.',
'goodbye' => '잘가요!',
'welcome' => '%s 님 어서오세요!',
'account_disabled' => '당신의 계정은 비활성 상태입니다.',
'bad_login' => '잘못된 자격증명입니다.',
'installed' => '설치가 완료되었어요!',
'confirm' => '확인',
'confirm_string' => '확실한가요?',
'open' => '열기',
'none' => '없음',
'reg_date' => '생성된 날짜',
'admin' => '관리자',
'active' => '활성화',
'user_code' => '사용자 코드',
'user.edit' => '사용자 수정',
'user.create' => '사용자 생성',
'users' => '사용자',
'client_config' => '클라이언트 설정 파일',
'edit' => '수정',
'update' => '재생성',
'copied' => '클립보드에 복사 완료!',
'copy' => '복사',
'token' => '토큰',
'your_profile' => '나의 프로필',
'is_admin' => '관리자',
'is_active' => '활성화',
'system_settings' => '시스템 설정',
'php_info' => 'PHP 정보',
'used' => '사용량',
'save' => '저장',
'apply' => '적용',
'click_to_load' => '눌러서 불러오기…',
'theme' => '테마',
'files' => '파일',
'hide' => '숨기기',
'publish' => '공개',
'delete' => '삭제',
'upload' => '업로드',
'download' => '다운로드',
'raw' => '원본 보기',
'owner' => '소유자',
'date' => '날짜',
'public' => '공개',
'size' => '용량',
'filename' => '파일이름',
'preview' => '미리보기',
'no_media' => '아무 것도 없어요.',
'login.username' => '이름 또는 이메일',
'password' => '비밀번호',
'public.delete_text' => '정말 이 항목을 삭제할까요? 이 선택은 되돌릴 수 없어요',
'public.telegram' => '텔레그램에 공유하기',
'copy_link' => '링크 복사',
'pager.previous' => '이전',
'pager.next' => '다음',
'logout' => '로그아웃',
'profile' => '프로필',
'system' => '시스템',
'home' => '홈',
'username' => '이름',
'login' => '로그인',
'send' => '보내기',
'no' => '취소',
'yes' => '확인',
'enforce_language' => '언어 설정',
'lang' => 'Korean',
'vanity_url' => '사용자 정의 URL',
];

163
resources/lang/lt.lang.php Normal file
View file

@ -0,0 +1,163 @@
<?php
return [
'dotted_search' => 'Ieškoti…',
'table' => 'Lentelė',
'gallery' => 'Galerija',
'cannot_demote' => 'Negalite pažeminti savo pareigų.',
'cannot_delete' => 'Negalite ištrinti savęs.',
'user_deleted' => 'Vartotojas panaikintas.',
'profile_updated' => 'Profilis sėkmingai atnaujintas!',
'user_updated' => 'Vartotojas „%s“ atnaujintas!',
'user_created' => 'Vartotojas „%s“ sukurtas!',
'password_required' => 'Būtinas slaptažodis.',
'username_taken' => 'Vartotojo vardas jau užimtas.',
'username_required' => 'Vartotojo vardas yra būtinas.',
'email_taken' => 'El. pašto adresas jau yra naudojamas.',
'email_required' => 'Būtinas el. pašto adresas.',
'goodbye' => 'Iki pasimatymo!',
'welcome' => 'Sveiki, %s!',
'bad_login' => 'Neteisingi įgaliojimai.',
'installed' => 'Diegimas sėkmingai baigtas!',
'confirm_string' => 'Ar tikrai?',
'confirm' => 'Patvirtinimas',
'none' => 'Nėra',
'reg_date' => 'Registracijos data',
'admin' => 'Administratorius',
'active' => 'Aktyvus',
'user_code' => 'Vartotojo kodas',
'client_config' => 'Kliento konfigūracija',
'edit' => 'Redaguoti',
'update' => 'Atnaujinti',
'copied' => 'Nukopijuota į iškarpinę!',
'copy' => 'Kopijuoti',
'token' => 'Žetonas',
'your_profile' => 'Jūsų profilis',
'is_admin' => 'Yra administratorius',
'is_active' => 'Yra aktyvus',
'user.edit' => 'Redaguoti vartotoją',
'user.create' => 'Sukurti vartotoją',
'system_settings' => 'Sistemos nustatymai',
'php_info' => 'PHP informacija',
'save' => 'Išsaugoti',
'apply' => 'Taikyti',
'click_to_load' => 'Spustelėkite norėdami įkelti…',
'theme' => 'Tema',
'files' => 'Failai',
'hide' => 'Slėpti',
'delete' => 'Ištrinti',
'upload' => 'Įkelti',
'download' => 'Atsisiųsti',
'raw' => 'Rodyti neapdorotą',
'date' => 'Data',
'owner' => 'Savininkas',
'public' => 'Viešas',
'size' => 'Dydis',
'filename' => 'Failo pavadinimas',
'preview' => 'Peržiūra',
'public.delete_text' => 'Ar tikrai norite ištrinti šį elementą? Jūs negalėsite jo susigrąžinti',
'public.telegram' => 'Bendrinti Telegram',
'copy_link' => 'Kopijuoti nuorodą',
'pager.previous' => 'Ankstesnis',
'pager.next' => 'Kitas',
'logout' => 'Atsijungti',
'profile' => 'Profilis',
'system' => 'Sistema',
'users' => 'Vartotojai',
'home' => 'Pagrindinis',
'username' => 'Vartotojo vardas',
'login' => 'Prisijungti',
'password' => 'Slaptažodis',
'login.username' => 'Vartotojo vardas arba el. paštas',
'send' => 'Siųsti',
'no' => 'Ne',
'yes' => 'Taip',
'lang' => 'Lietuvių',
'account_media_deleted' => 'Visa paskyros medija buvo ištrinta.',
'copy_url_behavior' => 'URL kopijavimo režimas',
'hide_by_default' => 'Slėpti mediją pagal numatytuosius nustatymus',
'custom_head_set' => 'Pritaikyta pasirinktinė HTML „head“.',
'custom_head_html_hint' => 'Šis turinys bus pridėtas prie kiekvieno puslapio žymos <head>.',
'custom_head_html' => 'Pasirinktinis HTML „Head“ turinys',
'no_upload_token' => 'Neturite asmeninio įkėlimo prieigos rakto. (Sukurkite vieną ir bandykite dar kartą.)',
'path_not_writable' => 'Išvesties kelyje nėra galimybės įrašyti.',
'clean_orphaned_uploads' => 'Valyti vienišus įkėlimus',
'order_by' => 'Rūšiuoti pagal…',
'switch_to' => 'Pereiti prie',
'deleted_orphans' => 'Sėkmingai ištrinta %d vienišų failų.',
'cannot_write_file' => 'Paskirties kelyje nėra galimybės įrašyti.',
'token_not_found' => 'Nurodytas prieigos raktas nerastas.',
'account_disabled' => 'Jūsų paskyra išjungta.',
'open' => 'Atidaryti',
'used' => 'Naudojama',
'orphaned_files' => 'Vieniši failai',
'publish' => 'Publikuoti',
'no_media' => 'Jokia medija nerasta.',
'enforce_language' => 'Priverstinis kalbos naudojimas',
'image_embeds' => 'Įterpti vaizdai',
'show_changelog' => 'Rodyti pakeitimų žurnalą',
'changelog' => 'Pakeitimų žurnalas',
'zip_ext_not_loaded' => 'Reikalingas „zip“ plėtinys neįkeltas',
'auto_tagging' => 'Automatinis įkėlimo žymėjimas',
'no_tags' => 'Nėra pridėtų žymų',
'upload_max_file_size' => 'Maksimalus failo dydis šiuo metu yra %s.',
'ldap_cant_connect' => 'Nepavyksta prisijungti prie LDAP autentifikavimo serverio.',
'user_create_password' => 'Jei paliksite tuščią, galbūt norėsite nusiųsti pranešimą vartotojo el. pašto adresu.',
'mail.new_account_text_with_pw' => 'Sveiki, %s!<br>jums buvo sukurta nauja paskyra %s (<a href="%s">%s</a>) naudojant šiuos kredencialus:<br><br>Vartotojo vardas: %s<br> Slaptažodis:%s <br><br>Spustelėkite šią nuorodą, kad patektumėte į prisijungimo puslapį:<br><a href="%s">%s</a>',
'mail.new_account_text_with_reset' => 'Sveiki, %s! <br>jums buvo sukurta nauja paskyra %s (<a href="%s">%s</a>), spustelėkite šią nuorodą, kad nustatytumėte slaptažodį ir jį suaktyvintumėte: <br><br><a href="%s">%s</a>',
'mail.new_account' => '%s - naujos paskyros kūrimas',
'send_notification' => 'Siųsti el. pašto pranešimą',
'recaptcha_secret_key' => 'reCAPTCHA slaptas raktas',
'recaptcha_site_key' => 'reCAPTCHA svetainės raktas',
'only_recaptcha_v3' => 'Palaikomas tik reCAPTCHA v3.',
'recaptcha_keys_required' => 'Reikalingi visi reCAPTCHA raktai.',
'recaptcha_enabled' => 'reCAPTCHA įjungta',
'recaptcha_failed' => 'reCAPTCHA nepavyko',
'danger_zone' => 'Pavojaus zona',
'clear_account' => 'Išvalyti paskyrą',
'delete_all' => 'Ištrinti viską',
'delete_selected' => 'Ištrinti pasirinktą',
'used_space' => 'Naudojama talpa',
'quota_recalculated' => 'Vartotojo kvota sėkmingai perskaičiuota iš disko.',
'recalculate_user_quota' => 'Perskaičiuoti vartotojo kvotą iš disko',
'password_restored' => 'Slaptažodis nustatytas iš naujo.',
'password_match' => 'Slaptažodis ir pakartotinis slaptažodis turi būti vienodi.',
'password_repeat' => 'Pakartokite slaptažodį',
'quota_enabled' => 'Įgalinti vartotojo kvotą',
'account_activated' => 'Paskyra suaktyvinta, dabar galite prisijungti!',
'recover_email_sent' => 'Jei yra, atkūrimo el. laiškas buvo išsiųstas į nurodytą abonementą.',
'mail.recover_password' => '%s slaptažodžio atkūrimas',
'mail.recover_text' => 'Sveiki, %s,<br>paprašyta iš naujo nustatyti jūsų paskyros slaptažodį. Norėdami užbaigti procedūrą, spustelėkite šią nuorodą:<br><br><a href="%s">%s</a><br><br> Jei ne jūs paprašėte iš naujo nustatyti slaptažodį, tiesiog ignoruoti šį laišką.',
'mail.activate_account' => '%s - paskyros aktyvinimas',
'mail.activate_text' => 'Sveiki, %s!<br>ačiū, kad sukūrėte paskyrą %s (<a href="%s">%s</a>), spustelėkite šią nuorodą, kad ją suaktyvintumėte: <br><br><a href="%s">%s</a>',
'invalid_quota' => 'Neleistinos reikšmės kaip numatytoji vartotojo kvota.',
'max_user_quota' => 'Maksimali vartotojo kvota',
'default_user_quota' => 'Numatytoji vartotojo kvota',
'register_success' => 'Paskyra sukurta, patvirtinimo el. laiškas išsiųstas.',
'register' => 'Registruotis',
'no_account' => 'Neturite paskyros?',
'password_recovery' => 'Atkurti slaptažodį',
'export_data' => 'Eksportuoti duomenis',
'settings_saved' => 'Sistemos nustatymai išsaugoti!',
'register_enabled' => 'Registracijos įgalintos',
'dont_close' => 'Neuždarykite šio skirtuko iki kol bus pabaigta.',
'please_wait' => 'Prašome palaukti…',
'remember_me' => 'Atsiminti mane',
'donate_text' => 'Jei jums patinka XBackBone, apsvarstykite paaukoti, kad paremtumėte kūrimą!',
'donation' => 'Parama',
'drop_to_upload' => 'Spustelėkite arba numeskite failus čia, kad įkeltumėte.',
'prerelease_channel' => 'Išankstinių versijų kanalas',
'default_lang_behavior' => 'XBackBone bandys suderinti naršyklės kalbą pagal nutylėjimą (atsarginė yra anglų kalba).',
'auto_set' => 'Nustatyti automatiškai',
'cancel' => 'Atšaukti',
'maintenance_in_progress' => 'Platforma tvarkoma, bandykite dar kartą vėliau …',
'updates' => 'Atnaujinimai',
'upgrade' => 'Atnaujinti',
'check_for_updates' => 'Tikrinti, ar yra naujinimų',
'file_size_no_match' => 'Atsisiųstas failas neatitinka tinkamo failo dydžio.',
'cannot_retrieve_file' => 'Neįmanoma nuskaityti failo.',
'new_version_available' => 'Nauja versija %s pasiekiama!',
'already_latest_version' => 'Jūs jau turite naujausią versiją.',
'maintenance' => 'Palaikymas',
'name' => 'Vardas',
'time' => 'Laikas',
];

View file

@ -162,4 +162,5 @@ return [
'mail.new_account' => '%s - Opprettelse av ny konto',
'send_notification' => 'Send e-postmerknad',
'copied' => 'Kopiert til utklippstavle.',
'image_embeds' => 'Integrer bilder',
];

View file

@ -54,7 +54,7 @@ return [
'reg_date' => 'Registratiedatum',
'none' => 'Geen',
'open' => 'Open',
'confirm' => 'Bevestiging',
'confirm' => 'Bevestig',
'confirm_string' => 'Weet je het zeker?',
'installed' => 'Installatie succesvol voltooid!',
'bad_login' => 'Verkeerde verificatiegegevens.',
@ -101,9 +101,9 @@ return [
'lang_name' => 'Taal',
'default_lang_behavior' => 'XBackBone probeert standaard de taal van de browser te matchen (fallback is Engels).',
'lang_set' => 'Systeemtaal "%s" afgedwongen',
'show_changelog' => 'Changelog weergeven',
'changelog' => 'Changelog',
'zip_ext_not_loaded' => 'De vereiste zip extensie is niet geladen',
'show_changelog' => 'Wijzigingslog weergeven',
'changelog' => 'Wijzigingslog',
'zip_ext_not_loaded' => 'De vereiste "zip" extensie is niet geladen',
'auto_tagging' => 'Automatisch tags aanmaken',
'no_tags' => 'Geen tags toegevoegd',
'upload_max_file_size' => 'De maximale bestandsgrootte is momenteel %s.',
@ -164,4 +164,7 @@ return [
'php_info' => 'PHP Informatie',
'upload' => 'Uploaden',
'copied' => 'Gekopieerd naar klembord!',
'vanity_url' => 'Eigen URL',
'image_embeds' => 'Afbeeldingen insluiten',
'show_all_tags' => 'Toon alle tags',
];

View file

@ -21,7 +21,7 @@ return [
'delete' => 'Usuń',
'hide' => 'Ukryj',
'files' => 'Pliki',
'click_to_load' => 'Kliknij, aby załadować...',
'click_to_load' => 'Kliknij, aby załadować',
'apply' => 'Zastosuj',
'save' => 'Zapisz',
'system_info' => 'Informacje o systemie',
@ -38,7 +38,7 @@ return [
'admin' => 'Admin',
'reg_date' => 'Data rejestracji',
'open' => 'Otwórz',
'confirm' => 'Potwierdzenie',
'confirm' => 'Potwierdź',
'confirm_string' => 'Jesteś pewien?',
'installed' => 'Instalacja zakończona pomyślnie!',
'welcome' => 'Witaj, %s!',
@ -80,8 +80,8 @@ return [
'switch_to' => 'Przełącz na',
'gallery' => 'Galeria',
'table' => 'Tabela',
'dotted_search' => 'Szukaj...',
'order_by' => 'Sortuj...',
'dotted_search' => 'Szukaj',
'order_by' => 'Sortuj',
'time' => 'Czas',
'name' => 'Nazwa',
'maintenance' => 'Konserwacja',
@ -94,7 +94,7 @@ return [
'check_for_updates' => 'Sprawdź aktualizacje',
'upgrade' => 'Aktualizuj',
'updates' => 'Aktualizacje',
'maintenance_in_progress' => 'Platforma w trakcie konserwacji, spróbuj ponownie później...',
'maintenance_in_progress' => 'Trwają prace techniczne, spróbuj ponownie później…',
'cancel' => 'Anuluj',
'auto_set' => 'Ustaw automatycznie',
'default_lang_behavior' => 'XBackBone domyślnie spróbuje dopasować język przeglądarki (zastępczym jest Angielski).',
@ -160,4 +160,7 @@ return [
'mail.new_account_text_with_reset' => 'Cześć %s!<br>zostało utworzone nowe konto dla Ciebie na %s (<a href="%s">%s</a>), kliknij w poniższy link aby ustawić hasło i aktywować je:<br><br><a href="%s">%s</a>',
'mail.recover_text' => 'Cześć %s,<br>została wysłana prośba o zresetowanie hasła do twojego konta. Aby zakończyć procedurę, kliknij w poniższy link:<br><br><a href="%s">%s</a><br><br>Jeśli to nie ty poprosiłeś o zresetowanie hasła, po prostu zignoruj ten e-mail.',
'mail.activate_text' => 'Cześć %s!<br>dziękuję za utworzenie konta na %s (<a href="%s">%s</a>), kliknij w poniższy link, aby je aktywować:<br><br><a href="%s">%s</a>',
'image_embeds' => 'Osadź obrazy',
'copied' => 'Skopiowano!',
'vanity_url' => 'Niestandardowy adres URL',
];

View file

@ -26,7 +26,7 @@ return [
'owner' => 'Dono',
'date' => 'Data',
'raw' => 'Mostrar raw',
'download' => 'Transferir',
'download' => 'Descarregar',
'delete' => 'Apagar',
'publish' => 'Publicar',
'hide' => 'Esconder',
@ -54,7 +54,7 @@ return [
'reg_date' => 'Data de registo',
'none' => 'Nenhum',
'open' => 'Abrir',
'confirm' => 'Confirmação',
'confirm' => 'Confirmar',
'confirm_string' => 'Tem a certeza?',
'installed' => 'Instalação completa com sucesso!',
'bad_login' => 'Login inválido.',
@ -160,4 +160,6 @@ return [
'max_user_quota' => 'Quota Máxima do Utilizador',
'register' => 'Registar',
'settings_saved' => 'Definições de sistema guardadas!',
'image_embeds' => 'Embutir imagens',
'vanity_url' => 'URL personalizado',
];

163
resources/lang/ro.lang.php Normal file
View file

@ -0,0 +1,163 @@
<?php
return [
'login' => 'Autentificare',
'password' => 'Parola',
'lang' => 'Română',
'enforce_language' => 'Aplică limba',
'yes' => 'Da',
'username' => 'Utilizator',
'send' => 'Trimite',
'no_media' => 'Nu s-a gasit media.',
'login.username' => 'Utilizator sau E-Mail',
'no' => 'Nu',
'users' => 'Utilizatori',
'system' => 'Sistem',
'profile' => 'Profil',
'pager.previous' => 'Anterior',
'public.telegram' => 'Distribuie pe Telegram',
'home' => 'Acasa',
'logout' => 'Iesire',
'pager.next' => 'Urmatorul',
'copy_link' => 'Copiaza link-ul',
'public.delete_text' => 'Esti sigur ca doresti sa stergi acest element? Nu il vei putea recupera',
'preview' => 'Previzualizeaza',
'filename' => 'Numele fisierului',
'size' => 'Dimensiune',
'public' => 'Public',
'delete' => 'Elimina',
'publish' => 'Publica',
'hide' => 'Ascunde',
'files' => 'Fisiere',
'orphaned_files' => 'Fisiere Orfane',
'theme' => 'Tema',
'click_to_load' => 'Apasa pentru a incarca…',
'apply' => 'Aplica',
'save' => 'Salveaza',
'used' => 'Folosit',
'php_info' => 'Informatii PHP',
'system_settings' => 'Setari de Sistem',
'user.create' => 'Creaza Utilizator',
'is_active' => 'Este activ',
'is_admin' => 'Este administrator',
'your_profile' => 'Profilul Tau',
'token' => 'Token',
'copy' => 'Copiaza',
'copied' => 'Copiat in clipboard!',
'update' => 'Actualizare',
'edit' => 'Editare',
'client_config' => 'Configuratie Client',
'user_code' => 'Cod Utilizator',
'active' => 'Activ',
'admin' => 'Admin',
'reg_date' => 'Data de Inregistrare',
'none' => 'Nimic',
'open' => 'Deschis',
'confirm' => 'Confirmare',
'bad_login' => 'Date gresite.',
'account_disabled' => 'Contul tau este dezactivat.',
'welcome' => 'Bine ai venit, %s!',
'goodbye' => 'La revedere!',
'email_required' => 'Adresa de e-mail este necesara.',
'email_taken' => 'Adresa de e-mail este deja folosita.',
'username_required' => 'Numele de utilizator este necesar.',
'username_taken' => 'Numele de utilizator este deja folosit.',
'cannot_demote' => 'Nu te poti retrograda.',
'cannot_write_file' => 'Nu se poate scrie in calea de destinatie.',
'deleted_orphans' => 'S-au sters cu succes %d fisiere orfane.',
'switch_to' => 'Comuta la',
'gallery' => 'Galerie',
'order_by' => 'Comanda dupa…',
'time' => 'Timp',
'name' => 'Nume',
'maintenance' => 'Mentenanta',
'clean_orphaned_uploads' => 'Curata Incarcarile Orfane',
'path_not_writable' => 'Nu se poate scrie in calea de iesire.',
'already_latest_version' => 'Ai deja ultima versiune.',
'new_version_available' => 'Versiune noua %s valabila!',
'cannot_retrieve_file' => 'Nu se poate recupera fisierul.',
'file_size_no_match' => 'Fisierul descarcat nu se potriveste cu dimensiunea corecta a fisierului.',
'check_for_updates' => 'Verifica actualizari',
'upgrade' => 'Actualizare',
'updates' => 'Actualizari',
'cancel' => 'Anuleaza',
'auto_set' => 'Seteaza automat',
'default_lang_behavior' => 'XBackBone va incerca in mod implicit sa foloseasca limba browser-ului (limba de rezerva este Engleza).',
'prerelease_channel' => 'Canal Pre-Lansari',
'no_upload_token' => 'Nu ai un token personal de incarcare. (Genereaza unul si incearca din nou.)',
'drop_to_upload' => 'Apasa sau lasa fisierele aici pentru a le incarca.',
'donation' => 'Donatie',
'donate_text' => 'Daca-ti place XBackBone, ia in considerare o donatie pentru a sprijini dezvoltarea lui!',
'custom_head_html' => 'Continut personalizat HTML Head',
'custom_head_html_hint' => 'Acest continut va fi adaugat in tagul <head> pe fiecare pagina.',
'custom_head_set' => 'HTML head personalizat aplicat.',
'remember_me' => 'Nu ma uita',
'please_wait' => 'Te rog sa astepti…',
'dont_close' => 'Nu inchide acest tab inainte de finalizare.',
'register_enabled' => 'Inregistrari active',
'hide_by_default' => 'Ascunde media in mod implicit',
'copy_url_behavior' => 'Modul Copiere URL',
'settings_saved' => 'Setari de sistem salvate!',
'export_data' => 'Exporta data',
'password_recovery' => 'Recupereaza parola',
'no_account' => 'Nu ai un cont?',
'register' => 'Inregistrare',
'register_success' => 'Contul a fost creat, un e-mail de confirmare a fost trimis.',
'default_user_quota' => 'Quota User Implicit',
'max_user_quota' => 'Quota User Maxim',
'invalid_quota' => 'Valori invalide ca si user quota in mod implicit.',
'mail.recover_password' => '%s - Recuperare Parola',
'recover_email_sent' => 'Daca exista, un e-mail pentru recuperare a fost trimis catre contul specificat.',
'account_activated' => 'Cont activat, acum te poti autentifica!',
'quota_enabled' => 'Activeaza user quota',
'password_repeat' => 'Repeta Parola',
'password_match' => 'Parola si parola repetata trebuie sa fie identice.',
'password_restored' => 'Parola resetata.',
'recalculate_user_quota' => 'Recalculeaza user quota de pe disc',
'quota_recalculated' => 'User quota recalculata de pe disc cu succes.',
'used_space' => 'Spatiu Utilizat',
'delete_selected' => 'Sterge cele Selectate',
'delete_all' => 'Sterge Tot',
'clear_account' => 'Curata Contul',
'recaptcha_failed' => 'reCAPTCHA Esuat',
'recaptcha_enabled' => 'reCAPTCHA Activat',
'recaptcha_keys_required' => 'Toate cheile reCAPTCHA sunt necesare.',
'only_recaptcha_v3' => 'Doar reCAPTCHA v3 este suportat.',
'recaptcha_site_key' => 'reCAPTCHA Cheie Site',
'recaptcha_secret_key' => 'reCAPTCHA Cheie Secreta',
'send_notification' => 'Trimite Notificare prin E-mail',
'mail.new_account' => '%s - Crearea Unui Cont Nou',
'mail.new_account_text_with_reset' => 'Hey %s!<br>un nou cont a fost creat pentru tine pe %s (<a href="%s">%s</a>), apasa pe urmatorul link pentru a-ti seta o parola si a-ti activa contul:<br><br><a href="%s">%s</a>',
'user_create_password' => 'Daca este lasat gol, este posibil sa doresti sa trimiti o notificare la adresa de e-mail a utilizatorului.',
'ldap_cant_connect' => 'Nu se poate conecta la serverul de autentificare LDAP.',
'upload_max_file_size' => 'In acest moment dimensiunea maxima pentru un fisier este %s.',
'no_tags' => 'Nu s-au adaugat etichete',
'auto_tagging' => 'Incarcare automata a etichetarii',
'zip_ext_not_loaded' => 'Extensia "zip" necesara nu este incarcata',
'show_changelog' => 'Afiseaza jurnalul cu schimbari',
'image_embeds' => 'Incorporeaza imagini',
'user_updated' => 'Utilizator "%s" actualizat!',
'user_deleted' => 'Utilizator eliminat.',
'owner' => 'Proprietar',
'date' => 'Data',
'upload' => 'Incarca',
'user.edit' => 'Editeaza Utilizator',
'confirm_string' => 'Esti sigur?',
'raw' => 'Afiseaza brut',
'download' => 'Descarca',
'password_required' => 'Parola este necesara.',
'user_created' => 'Utilizator "%s" creat!',
'table' => 'Tabel',
'dotted_search' => 'Cauta…',
'installed' => 'Instalarea s-a completat cu succes!',
'profile_updated' => 'Profil actualizat cu succes!',
'mail.recover_text' => 'Hey %s,<br>o resetare de parola a fost ceruta pentru contul tau. Pentru a completa procedura, apasa pe urmatorul link:<br><br><a href="%s">%s</a><br><br>Daca nu ai fost tu cel care a cerut resetarea, te rog sa ignori acest e-mail.',
'token_not_found' => 'Token-ul specificat nu a fost gasit.',
'cannot_delete' => 'Nu te poti elimina pe tine.',
'maintenance_in_progress' => 'Platforma este in mentenanta, incearca mai tarziu…',
'mail.activate_text' => 'Hey %s!<br>iti multumesc ca ti-ai creat cont pe %s (<a href="%s">%s</a>), apasa pe urmatorul link pentru a-ti activa contul:<br><br><a href="%s">%s</a>',
'danger_zone' => 'Zona Periculoasa',
'mail.activate_account' => '%s - Activare Cont',
'account_media_deleted' => 'Toata media de pe cont a fost eliminata.',
'changelog' => 'Schimbari',
'mail.new_account_text_with_pw' => 'Hey %s!<br>un nou cont a fost creat pentru tine pe %s (<a href="%s">%s</a>), cu urmatoarele date:<br><br>Nume de utilizator: %s<br>Parola: %s<br><br>Apasa pe urmatorul link pentru a te autentifica:<br><a href="%s">%s</a>',
];

View file

@ -45,16 +45,16 @@ return [
'your_profile' => 'Ваш профиль',
'token' => 'Ключ',
'copy' => 'Копировать',
'update' => 'Обновить',
'update' => 'Обновление',
'edit' => 'Редактировать',
'client_config' => 'Конфигурация клиента',
'user_code' => 'Код пользователя',
'active' => 'Активен',
'active' => 'Активный',
'admin' => 'Админ',
'reg_date' => 'Дата регистрации',
'none' => 'Нет',
'none' => 'Никак',
'open' => 'Открыть',
'confirm' => 'Подтверждение',
'confirm' => 'Потвердить',
'confirm_string' => 'Вы уверены?',
'installed' => 'Установка успешно завершена!',
'bad_login' => 'Неверные учетные данные.',
@ -163,5 +163,7 @@ return [
'copied' => 'Скопировано!',
'system_settings' => 'Системные настройки',
'upload' => 'Выгрузить',
'php_info' => 'Инфо о PHP',
'php_info' => 'Информация о PHP',
'image_embeds' => 'Встроенные изображения',
'vanity_url' => 'Пользовательский URL',
];

163
resources/lang/sr.lang.php Normal file
View file

@ -0,0 +1,163 @@
<?php
return [
'no' => 'Ne',
'yes' => 'Da',
'send' => 'Pošalji',
'no_media' => 'Nije pronađen nijedan medija.',
'login.username' => 'Korisničko ime ili e-mail',
'password' => 'Lozinka',
'login' => 'Prijavite se',
'username' => 'Korisničko ime',
'home' => 'Kuća',
'users' => 'Korisnici',
'profile' => 'Profil',
'logout' => 'Odjavi se',
'pager.next' => 'Sledeće',
'pager.previous' => 'Prethodno',
'copy_link' => 'Kopiraj link',
'public.telegram' => 'Podeli na Telegramu',
'public.delete_text' => 'Da li ste sigurni da želite da izbrišete ovu stvar? Nećete moći da ga povratite',
'preview' => 'Pregled',
'size' => 'Veličina',
'public' => 'Javno',
'owner' => 'Vlasnik',
'date' => 'Datum',
'raw' => 'Prikaži raw',
'download' => 'Preuzimanje',
'delete' => 'Izbriši',
'publish' => 'Objavite',
'hide' => 'Sakri',
'files' => 'Fajlovi',
'theme' => 'Tema',
'click_to_load' => 'Kliknite za učitavanje…',
'apply' => 'Primeniti',
'save' => 'Sačuvaj',
'used' => 'Korišćeno',
'php_info' => 'PHP informacije',
'user.create' => 'Napravi korisnika',
'upload' => 'Upload',
'orphaned_files' => 'Orphaned Fajlovi',
'is_active' => 'Aktivan',
'is_admin' => 'Je administrator',
'token' => 'Token',
'copy' => 'Kopiraj',
'update' => 'Ažuriraj',
'edit' => 'Urediti',
'client_config' => 'Konfiguracija klijenta',
'user_code' => 'Korisnički kod',
'active' => 'Aktivan',
'admin' => 'Admin',
'reg_date' => 'Datum registracije',
'none' => 'Nijedan',
'open' => 'Otvori',
'confirm' => 'Potvrda',
'installed' => 'Instalacija je uspešno završena!',
'bad_login' => 'Pogrešne akreditive.',
'account_disabled' => 'Vaš nalog je onemogućen.',
'welcome' => 'Dobrodošli, %s!',
'goodbye' => 'Doviđenja!',
'token_not_found' => 'Navedeni token nije pronađen.',
'email_required' => 'E-mail adresa je obavezna.',
'email_taken' => 'E-mail adresa je već u upotrebi.',
'username_required' => 'Korisničko ime je obavezno.',
'user_created' => 'Korisnik "%s“ je kreiran!',
'user_updated' => 'Korisnik "%s“ je ažuriran!',
'profile_updated' => 'Profil je uspešno ažuriran!',
'user_deleted' => 'Korisnik je obrisan.',
'cannot_delete' => 'Ne možete da sami sebe izbrisati.',
'deleted_orphans' => 'Uspešno izbrisano %d orphaned files.',
'switch_to' => 'Prebacite na',
'gallery' => 'Galerija',
'table' => 'Sto',
'dotted_search' => 'Pretraga…',
'order_by' => 'Pretraga po…',
'time' => 'Vreme',
'name' => 'Ime',
'maintenance' => 'Održavanje',
'clean_orphaned_uploads' => 'Očistite neispunjene otpremanja',
'path_not_writable' => 'Na izlaznu putanju nije moguće pisati.',
'already_latest_version' => 'Već imate najnoviju verziju.',
'new_version_available' => 'Dostupna je nova verzija %s!',
'file_size_no_match' => 'Preuzet fajl ne odgovara ispravnoj veličini fajla.',
'check_for_updates' => 'Proveri ažuriranja',
'upgrade' => 'Nadogradi',
'updates' => 'Ažuriranja',
'cancel' => 'Otkaži',
'auto_set' => 'Podesite automatski',
'default_lang_behavior' => 'KSBackBone će pokušati da podrazumeva jezik pretraživača (zamena je engleski).',
'prerelease_channel' => 'Prerelease kanal',
'no_upload_token' => 'Nemate lični token za otpremanje. (Generišite jedan i pokušajte ponovo.)',
'donation' => 'Donacija',
'donate_text' => 'Ako vam se sviđa KSBackBone, razmislite o donaciji za podršku razvoju!',
'custom_head_html' => 'Prilagođeni sadržaj HTML glave',
'custom_head_html_hint' => 'Ovaj sadržaj će biti dodat u oznaku <head> na svakoj stranici.',
'custom_head_set' => 'Primenjena prilagođena HTML glava.',
'remember_me' => 'Zapamti me',
'dont_close' => 'Ne zatvarajte ovu karticu dok se ne završi.',
'hide_by_default' => 'Podrazumevano sakrijte medije',
'copy_url_behavior' => 'Režim kopiranja URL-a',
'settings_saved' => 'Podešavanja sistema su sačuvana!',
'export_data' => 'Izvadi podatke',
'password_recovery' => 'Oporavi lozinku',
'no_account' => 'Nemate nalog?',
'register' => 'Registrujte se',
'default_user_quota' => 'Podrazumevana korisnička kvota',
'max_user_quota' => 'Maksimalna kvota korisnika',
'invalid_quota' => 'Nevažeće vrednosti kao podrazumevana korisnička kvota.',
'mail.activate_account' => '%s - Aktivacija naloga',
'mail.recover_password' => '%s - Oporavak lozinke',
'recover_email_sent' => 'Ako postoji, na navedeni nalog je poslata e-pošta za oporavak.',
'account_activated' => 'Nalog je aktiviran, sada možete da se prijavite!',
'quota_enabled' => 'Omogući korisničku kvotu',
'password_repeat' => 'Ponovite lozinku',
'password_match' => 'Lozinka i lozinka za ponavljanje moraju biti iste.',
'password_restored' => 'Resetovanje lozinke.',
'recalculate_user_quota' => 'Ponovo izračunajte korisničku kvotu sa diska',
'lang' => 'Engleski',
'quota_recalculated' => 'Korisnička kvota je ponovo izračunata sa diska.',
'used_space' => 'Iskorišćeni prostor',
'delete_selected' => 'Izbriši izabrano',
'delete_all' => 'Izbriši sve',
'clear_account' => 'Obriši nalog',
'account_media_deleted' => 'Svi mediji na nalogu su izbrisani.',
'danger_zone' => 'Opasna zona',
'recaptcha_failed' => 'reCAPTCHA nije uspela',
'recaptcha_enabled' => 'reCAPTCHA je omogućena',
'recaptcha_keys_required' => 'Svi reCAPTCHA ključevi su obavezni.',
'only_recaptcha_v3' => 'Samo je reCAPTCHA v3 podržan.',
'recaptcha_site_key' => 'reCAPTCHA ključ sajta',
'recaptcha_secret_key' => 'reCAPTCHA tajni ključ',
'send_notification' => 'Pošaljite obaveštenje e-poštom',
'mail.new_account' => '%s - Kreiranje novog naloga',
'mail.new_account_text_with_reset' => 'Zdravo %s!<br>novi nalog je napravljen za vas na %s (<a href="%s">%s</a>), kliknite na sledeću vezu da postavite lozinku i aktivirate je:<br ><br><a href="%s">%s</a>',
'mail.new_account_text_with_pw' => 'Zdravo %s!<br>novi nalog je napravljen za vas na %s (<a href="%s">%s</a>), sa sledećim akreditivima:<br><br>Korisničko ime: %s <br>Lozinka: %s<br><br>Kliknite na sledeću vezu da biste otišli na stranicu za prijavu:<br><a href="%s">%s</a>',
'user_create_password' => 'Ako ostavite prazno, možda ćete želeti da pošaljete obaveštenje na adresu e-pošte korisnika.',
'ldap_cant_connect' => 'Ne mogu da se povežem sa LDAP serverom za potvrdu identiteta.',
'upload_max_file_size' => 'Maksimalna veličina fajla je trenutno %s.',
'no_tags' => 'Nema dodatih oznaka',
'auto_tagging' => 'Automatsko otpremanje oznaka',
'zip_ext_not_loaded' => 'Potrebna ekstenzija "zip" nije učitana',
'changelog' => 'Dnevnik pronena',
'show_changelog' => 'Prikaži dnevnik promena',
'image_embeds' => 'Ugradi slike',
'enforce_language' => 'Sprovedite jezik',
'user.edit' => 'Uredi korisnika',
'system' => 'Sistem',
'filename' => 'Naziv dokumenta',
'system_settings' => 'Podešavanja sistema',
'your_profile' => 'Tvoj profil',
'copied' => 'Kopirano u međuspremnik!',
'confirm_string' => 'Da li ste sigurni?',
'username_taken' => 'Korisničko ime je već zauzeto.',
'cannot_retrieve_file' => 'Nije moguće preuzeti fajl.',
'cannot_write_file' => 'Putanja odredišta nije upisiva.',
'maintenance_in_progress' => 'Platforma se održava, pokušajte ponovo kasnije…',
'password_required' => 'Lozinka je obavezna.',
'cannot_demote' => 'Ne možete sami sebe degradirati.',
'drop_to_upload' => 'Kliknite ili otpustite svoje fajlove ovde da biste ih otpremili.',
'register_enabled' => 'Registracije su omogućene',
'please_wait' => 'Sačekajte…',
'register_success' => 'Nalog je kreiran, e-mail za potvrdu je poslat.',
'mail.activate_text' => 'Zdravo %s!<br>hvala što ste otvorili svoj nalog na %s (<a href="%s">%s</a>), kliknite na sledeću vezu da biste ga aktivirali:<br><br>< a href="%s">%s</a>',
'mail.recover_text' => 'Zdravo %s,<br>zatraženo je resetovanje lozinke za vaš nalog. Da biste završili proceduru kliknite na sledeću vezu:<br><br><a href="%s">%s</a><br><br>Ako niste vi tražili resetovanje lozinke, jednostavno ignorišite ovu e-poštu.',
];

View file

@ -155,8 +155,11 @@ return [
'cannot_write_file' => 'Destinationens sökväg är ej skrivbar.',
'cannot_demote' => 'Du kan inte degradera dig själv.',
'token_not_found' => 'Den token som angavs hittades inte.',
'confirm' => 'Bekräftelse',
'confirm' => 'Bekräfta',
'copied' => 'Kopierat till urklipp!',
'token' => 'Token',
'orphaned_files' => 'Föräldralösa Filer',
'image_embeds' => 'Inbäddade bilder',
'vanity_url' => 'Anpassad URL',
'show_all_tags' => 'Visa alla taggar',
];

View file

@ -1,51 +1,165 @@
<?php
return [
'orphaned_files' => 'Çöp dosyalar',
'orphaned_files' => 'Sahipsiz Dosyalar',
'files' => 'Dosyalar',
'hide' => 'Gizle',
'publish' => 'yayınla',
'publish' => 'Yayınla',
'delete' => 'Sil',
'upload' => 'yükle',
'download' => 'indir',
'raw' => 'kaynak göster',
'upload' => 'Yükle',
'download' => 'İndir',
'raw' => 'Kaynak göster',
'date' => 'Tarih',
'owner' => 'Sahip',
'public' => 'Herkese açık',
'size' => 'boyut',
'size' => 'Boyut',
'filename' => 'Dosya adı',
'preview' => 'Önizle',
'public.delete_text' => 'Bu öğeyi silmek istediğinizden emin misiniz? geri dönüşü olmayacaktır',
'public.telegram' => 'Telegram\'da paylaş !',
'preview' => 'Ön izleme',
'public.delete_text' => 'Bu ögeyi silmek istediğinizden emin misiniz? Geri dönüşü olmayacaktır',
'public.telegram' => 'Telegram\'da paylaş',
'copy_link' => 'Bağlantıyı kopyala',
'pager.previous' => 'Önceki',
'pager.next' => 'Sonraki',
'logout' => 'Çıkış yap',
'logout' => 'Oturumu kapat',
'profile' => 'Profil',
'system' => 'Sistem',
'users' => 'Kullanıcılar',
'home' => 'Anasayfa',
'home' => 'Ana sayfa',
'username' => 'Kullanıcı adı',
'login' => 'Giriş',
'password' => 'Şifre',
'login' => 'Oturum aç',
'password' => 'Parola',
'login.username' => 'Kullanıcı adı veya e-posta',
'no_media' => 'Medya ortamı bulunamadı.',
'send' => 'Gönder',
'no' => 'Hayır',
'yes' => 'Evet',
'enforce_language' => 'Mevcut dile zorla',
'lang' => 'ingilizce',
'enforce_language' => 'Dili uygula',
'lang' => 'Türkçe',
'copy' => 'Kopyala',
'token' => 'Token',
'token' => 'Belirteç',
'your_profile' => 'Profiliniz',
'is_admin' => 'Yönetici mi',
'is_active' => 'Aktif mi',
'user.edit' => 'Kullanıcı bilgilerini değiştir',
'is_active' => 'Etkin mi',
'user.edit' => 'Kullanıcıyı düzenle',
'user.create' => 'Kullanıcı oluştur',
'system_settings' => 'Sistem Ayarları',
'php_info' => 'PHP Bilgileri',
'used' => 'Kullanılan',
'save' => 'Kaydet',
'apply' => 'Uygula',
'click_to_load' => 'Yüklemek için tıklayınız…',
'click_to_load' => 'Yüklemek için tıklayın…',
'theme' => 'Tema',
'username_taken' => 'Kullanıcı adı zaten alınmış.',
'password_required' => 'Parola gerekli.',
'reg_date' => 'Kayıt Tarihi',
'active' => 'Etkin',
'none' => 'Yok',
'open' => 'Açık',
'admin' => 'Yönetici',
'copied' => 'Panoya kopyalandı!',
'update' => 'Güncelle',
'edit' => 'Düzenle',
'client_config' => 'İstemci Yapılandırması',
'user_code' => 'Kullanıcı kodu',
'confirm_string' => 'Emin misiniz?',
'installed' => 'Kurulum başarıyla tamamlandı!',
'bad_login' => 'Yanlış kimlik bilgileri.',
'account_disabled' => 'Hesabınız devre dışı bırakıldı.',
'welcome' => 'Hoş geldiniz, %s!',
'goodbye' => 'Hoşça kal!',
'token_not_found' => 'Belirtilen belirteç bulunamadı.',
'email_required' => 'E-posta adresi gerekli.',
'email_taken' => 'Bu e-posta adresi zaten kullanılıyor.',
'username_required' => 'Kullanıcı adı gerekli.',
'image_embeds' => 'Gömülü görüntü',
'default_lang_behavior' => 'XBackBone varsayılan olarak tarayıcı diliyle eşleşmeye çalışacaktır (yedek dil İngilizce\'dir).',
'no_upload_token' => 'Kişisel bir yükleme belirteciniz yok. (Bir tane oluşturun ve tekrar deneyin.)',
'copy_url_behavior' => 'URL\'i kopyalama modu',
'delete_all' => 'Hepsini Sil',
'max_user_quota' => 'Azami Kullanıcı Kotası',
'mail.recover_text' => 'Merhaba %s,<br>hesabınız için bir parola sıfırlama istendi. İşlemleri tamamlamak için aşağıdaki bağlantıya tıklayın:<br><br><a href="%s">%s</a><br><br>Parola sıfırlamayı isteyen siz değilseniz bu e-postayı dikkate almayın.',
'clear_account' => 'Hesabı Temizle',
'mail.new_account_text_with_pw' => 'Merhaba %s!<br>, %s (<a href="%s">%s</a>) tarihinde sizin için aşağıdaki kimlik bilgileriyle yeni bir hesap oluşturuldu:<br><br>Kullanıcı adı: %s<br>Parola: %s<br><br>Oturum açma sayfasına gitmek için aşağıdaki bağlantıya tıklayın:<br><a href="%s">%s</a>',
'upload_max_file_size' => 'Azami dosya boyutu şu anda %s.',
'recover_email_sent' => 'Varsa, belirtilen hesaba bir kurtarma e-postası gönderildi.',
'cannot_demote' => 'Kendinizi rütbenizi indiremezsiniz.',
'cannot_write_file' => 'Hedef yol yazılabilir değil.',
'deleted_orphans' => '%d sahipsiz dosya başarıyla silindi.',
'gallery' => 'Galeri',
'table' => 'Tablo',
'dotted_search' => 'Ara…',
'time' => 'Zaman',
'name' => 'Ad',
'maintenance' => 'Bakım',
'path_not_writable' => ıkış yolu yazılabilir değil.',
'already_latest_version' => 'Zaten son sürüme sahipsiniz.',
'new_version_available' => 'Yeni %s sürümü var!',
'cannot_retrieve_file' => 'Dosya alınamıyor.',
'file_size_no_match' => 'İndirilen dosya doğru dosya boyutu ile eşleşmiyor.',
'check_for_updates' => 'Güncellemeleri denetle',
'upgrade' => 'Güncelle',
'updates' => 'Güncellemeler',
'maintenance_in_progress' => 'Platform bakımda, daha sonra tekrar deneyin…',
'cancel' => 'İptal',
'auto_set' => 'Otomatik olarak ayarla',
'prerelease_channel' => 'Ön Yayın Kanalı',
'drop_to_upload' => 'Yüklemek için dosyalarınızı buraya bırakın veya tıklayın.',
'donation' => 'Bağış',
'donate_text' => 'XBackBone\'u beğendiyseniz, geliştirmeyi desteklemek için bir bağış yapmayı düşünün!',
'custom_head_html_hint' => 'Bu içerik her sayfanın <head> etiketine eklenecek.',
'remember_me' => 'Beni hatırla',
'please_wait' => 'Lütfen bekleyin…',
'dont_close' => 'Tamamlanana kadar bu sekmeyi kapatmayın.',
'register_enabled' => 'Kayıtlar etkinleştirildi',
'hide_by_default' => 'Varsayılan olarak medyayı gizle',
'settings_saved' => 'Sistem ayarları kaydedildi!',
'export_data' => 'Veriyi dışarı çıkar',
'password_recovery' => 'Parolayı kurtar',
'no_account' => 'Hesabınız yok mu?',
'register' => 'Kaydol',
'register_success' => 'Hesap oluşturuldu, bir onay e-postası gönderildi.',
'default_user_quota' => 'Varsayılan Kullanıcı Kotası',
'invalid_quota' => 'Varsayılan kullanıcı kotası geçersiz değer.',
'mail.activate_account' => '%s - Hesap Etkinleştirme',
'mail.recover_password' => '%s - Parola Kurtarma',
'account_activated' => 'Hesap etkinleştirildi, artık oturum açabilirsiniz!',
'quota_enabled' => 'Kullanıcı kotasını etkinleştir',
'password_repeat' => 'Parolayı Tekrarla',
'password_match' => 'Parola ve tekrarlanan parola aynı olmalıdır.',
'password_restored' => 'Parola sıfırlandı.',
'recalculate_user_quota' => 'Diskten kullanıcı kotasını yeniden hesapla',
'quota_recalculated' => 'Diskten kullanıcı kotası başarıyla yeniden hesaplandı.',
'used_space' => 'Kullanılan Alan',
'delete_selected' => 'Seçilenleri Sil',
'account_media_deleted' => 'Hesaptaki tüm medya silindi.',
'danger_zone' => 'Tehlike Bölgesi',
'recaptcha_failed' => 'reCAPTCHA Başarısız oldu',
'recaptcha_enabled' => 'reCAPTCHA etkinleştirildi',
'recaptcha_keys_required' => 'Bütün reCAPTCHA anahtarları gerekli.',
'only_recaptcha_v3' => 'Yalnızca reCAPTCHA v3 desteklenmektedir.',
'recaptcha_site_key' => 'reCAPTCHA Site Anahtarı',
'recaptcha_secret_key' => 'reCAPTCHA Gizli Anahtarı',
'send_notification' => 'E-posta Bildirimi Gönder',
'mail.new_account' => '%s - Yeni Hesap Oluşturma',
'mail.new_account_text_with_reset' => 'Merhaba %s!<br>, %s (<a href="%s">%s</a>) tarihinde sizin için yeni bir hesap oluşturuldu, bir parola belirlemek ve etkinleştirmek için aşağıdaki bağlantıya tıklayın:<br><br><a href="%s">%s</a>',
'user_create_password' => 'Boş bırakılırsa, kullanıcı e-posta adresine bir bildirim göndermek isteyebilirsiniz.',
'ldap_cant_connect' => 'LDAP kimlik doğrulama sunucusuna bağlanılamıyor.',
'no_tags' => 'Etiket eklenmedi',
'auto_tagging' => 'Otomatik yükleme etiketleme',
'zip_ext_not_loaded' => 'Gereken "zip" eklentisi yüklenmedi',
'changelog' => 'Değişiklik Günlüğü (Yama Notları)',
'show_changelog' => 'Değişiklik günlüğünü göster',
'confirm' => 'Onayla',
'user_created' => '"%s" kullanıcısı oluşturuldu!',
'user_updated' => '"%s" kullanıcısı güncellendi!',
'profile_updated' => 'Profil başarıyla güncellendi!',
'user_deleted' => 'Kullanıcı silindi.',
'cannot_delete' => 'Kendi kullanıcınızı silemezsiniz.',
'order_by' => 'Sıralama ölçütü…',
'clean_orphaned_uploads' => 'Sahipsiz Yüklemeleri Temizle',
'custom_head_html' => 'Özel HTML başlık içeriği',
'custom_head_set' => 'Özel HTML başlığı uygulandı.',
'mail.activate_text' => 'Merhaba %s!<br>%s (<a href="%s">%s</a>) hesabınızı oluşturduğunuz için teşekkür ederiz, etkinleştirmek için aşağıdaki bağlantıya tıklayın:<br><br><a href="%s">%s</a>',
'switch_to' => 'Şuna geç',
'vanity_url' => 'Özel URL',
'show_all_tags' => 'Tüm etiketleri göster',
];

163
resources/lang/vi.lang.php Normal file
View file

@ -0,0 +1,163 @@
<?php
return [
'yes' => 'Có',
'reg_date' => 'Ngày đăng ký',
'lang' => 'Tiếng Việt',
'enforce_language' => 'Cài đặt ngôn ngữ',
'send' => 'Gửi',
'login.username' => 'Tên đăng nhập hoặc Email',
'password' => 'Mật khẩu',
'users' => 'Người dùng',
'system' => 'Hệ thống',
'profile' => 'Hồ sơ',
'logout' => 'Thoát',
'pager.previous' => 'Trước',
'copy_link' => 'Copy đường link',
'pager.next' => 'Tiếp',
'public.telegram' => 'Chia sẻ lên Telegram',
'public.delete_text' => 'Bạn có chắc là muốn xoá mục này? Bạn sẽ không thể khôi phục lại nó sau khi xoá',
'preview' => 'Xem trước',
'filename' => 'Tên tập tin',
'size' => 'Kích cỡ',
'public' => 'Chia sẻ công cộng',
'owner' => 'Chủ sở hữu',
'date' => 'Ngày',
'raw' => 'Xem dạng thuần',
'download' => 'Tải xuống',
'delete' => 'Xoá',
'publish' => 'Đăng lên',
'hide' => 'Ẩn đi',
'files' => 'Tập tin',
'theme' => 'Phông nền',
'click_to_load' => 'Bấm vào để tải…',
'save' => 'Lưu',
'used' => 'Đã sử dụng',
'php_info' => 'Thông tin PHP',
'no_media' => 'Không tìm thấy dữ liệu.',
'orphaned_files' => 'Tập tin với thư mục chính đã bị xoá',
'user.edit' => 'Chỉnh sửa Người dùng',
'is_active' => 'Đang hoạt động',
'token' => 'Mã token',
'copied' => 'Đã sao chép!',
'update' => 'Cập nhật',
'edit' => 'Chỉnh sửa',
'user_code' => 'Mã Người dùng',
'none' => 'Không có',
'open' => 'Mở',
'confirm' => 'Xác nhận',
'confirm_string' => 'Bạn có chắc chứ?',
'installed' => 'Đã hoàn thành cài đặt thành công!',
'welcome' => 'Chào mừng vào XBackBone, %s!',
'goodbye' => 'Gặp lại lần sau nhé!',
'token_not_found' => 'Mã token nhập vào không được tìm thấy.',
'email_taken' => 'Địa chỉ email đã được sử dụng.',
'username_taken' => 'Tên đăng nhập này đã có người sử dụng rồi.',
'password_required' => 'Bạn cần nhập mật khẩu.',
'user_created' => 'Người dùng "%s" đã được tạo!',
'user_updated' => 'Người dùng "%s" đã được cập nhật!',
'user_deleted' => 'Đã xoá người dùng.',
'cannot_demote' => 'Bạn không thể tự giáng cấp tài khoản người dùng của mình.',
'cannot_write_file' => 'Đường dẫn đích không thể ghi dữ liệu vào được.',
'switch_to' => 'Chuyển về',
'gallery' => 'Xem theo ô',
'table' => 'Xem dạng bảng',
'path_not_writable' => 'Đường dẫn xuất ra không ghi dữ liệu vào được.',
'already_latest_version' => 'Bạn đang dùng phiên bản mới nhất.',
'cannot_retrieve_file' => 'Không thể trích xuất tập tin.',
'check_for_updates' => 'Kiểm tra phiên bản mới',
'upgrade' => 'Nâng cấp',
'updates' => 'Cập nhật',
'maintenance_in_progress' => 'Hệ thống đang bảo trì, vui lòng thử lại sau…',
'cancel' => 'Bỏ',
'auto_set' => 'Tự động cài đặt',
'no_upload_token' => 'Bạn chưa có một mã tải lên cá nhân. (Hãy tạo một mã và thử lại nhé.)',
'drop_to_upload' => 'Bấm vào hoặc bỏ tập tin của bạn vào đây để tải lên.',
'donate_text' => 'Nếu bạn thích XBackBone, xin hãy quyên góp để hỗ trợ việc phát triển phần mềm cho người dùng!',
'custom_head_html' => 'Nội dung phần đầu dạng HTML tuỳ chỉnh',
'remember_me' => 'Nhớ tên đăng nhập',
'please_wait' => 'Xin chờ một chút…',
'settings_saved' => 'Cài đặt hệ thống đã được lưu!',
'export_data' => 'Xuất dữ liệu',
'password_recovery' => 'Khôi phục mật khẩu',
'no_account' => 'Bạn chưa có tài khoản?',
'register' => 'Hãy đăng ký',
'register_success' => 'Tài khoản của bạn đã được tạo, email xác nhận đã được gửi cho bạn.',
'default_user_quota' => 'Dung lượng mặc định cho người dùng',
'invalid_quota' => 'Thông tin dung lượng người dùng mặc định nhập vào không hợp lệ.',
'mail.activate_account' => '%s - Kích hoạt tài khoản',
'mail.recover_text' => 'Chào bạn %s,<br>một lệnh khôi phục mật khẩu đã được yêu cầu cho tài khoản của bạn. Để hoàn thành khôi phục mật khẩu bạn hãy bấm vào đường link sau :<br><br><a href="%s">%s</a><br><br>Nếu bạn không gửi yêu cầu, hãy bỏ qua email này.',
'mail.recover_password' => '%s - Khôi phục mật khẩu',
'recover_email_sent' => 'Nếu tài khoản hiện hữu, hệ thống sẽ gửi một email khôi phục mật khẩu đến tài khoản bạn đã nhập vào.',
'password_match' => 'Mật khẩu nhập vào và nhập lại phải trùng khớp nhau.',
'password_restored' => 'Đặt lại mật khẩu.',
'recalculate_user_quota' => 'Chỉnh lại dung lượng cho người dùng dựa trên ổ đĩa',
'quota_recalculated' => 'Dung lượng cho người dùng đã được chỉnh lại thành công theo dung lượng ổ đĩa.',
'delete_selected' => 'Xoá phần được chọn',
'delete_all' => 'Xoá hết',
'clear_account' => 'Xoá dữ liệu trong tài khoản',
'recaptcha_failed' => 'Xác minh reCAPTCHA thất bại',
'recaptcha_enabled' => 'Xác minh reCAPTCHA đã được bật',
'mail.new_account' => '%s - Tạo tài khoản mới',
'recaptcha_site_key' => 'Mã reCAPTCHA chia sẻ công cộng',
'user_create_password' => 'Nếu mật khẩu để trống, bạn có thể sẽ muốn gửi một thông báo đến email người dùng.',
'upload_max_file_size' => 'Kích cỡ tập tin tối đa hiện giờ là %s.',
'no_tags' => 'Không có thẻ nào được thêm vào',
'auto_tagging' => 'Tự động gắn thẻ vào các tập tin tải lên',
'zip_ext_not_loaded' => 'Gói mở rộng zip được yêu cầu không được tải thành công',
'changelog' => 'Nhật ký những thay đổi',
'show_changelog' => 'Hiển thị nhật ký những thay đổi',
'image_embeds' => 'Chèn hình ảnh',
'no' => 'Không',
'login' => 'Đăng nhập',
'username' => 'Tên đăng nhập',
'home' => 'Trang chủ',
'is_admin' => 'Là quản trị viên',
'copy_url_behavior' => 'Chế độ sao chép URL',
'upload' => 'Tải lên',
'your_profile' => 'Hồ sơ của bạn',
'email_required' => 'Bạn cần nhập địa chỉ email.',
'maintenance' => 'Bảo trì',
'username_required' => 'Bạn cần nhập tên đăng nhập.',
'system_settings' => 'Cài đặt hệ thống',
'apply' => 'Áp dụng',
'client_config' => 'Cấu hình client',
'account_disabled' => 'Tài khoản của bạn đang bị vô hiệu hoá.',
'name' => 'Tên',
'user.create' => 'Tạo Người dùng',
'copy' => 'Sao chép',
'bad_login' => 'Sai tên hoặc mật khẩu.',
'active' => 'Đang hoạt động',
'admin' => 'Quản trị viên',
'profile_updated' => 'Hồ sơ được cập nhật thành công!',
'cannot_delete' => 'Bạn không thể tự xoá tài khoản người dùng của bạn.',
'deleted_orphans' => 'Đã xoá %d tập tin không còn thư mục chính thành công.',
'dotted_search' => 'Tìm kiếm…',
'time' => 'Thời gian',
'order_by' => 'Sắp xếp theo…',
'new_version_available' => 'Đã có phiên bản %s mới!',
'custom_head_html_hint' => 'Nội dung này sẽ được thêm vào phần thẻ <head> trên mỗi trang.',
'clean_orphaned_uploads' => 'Xoá những phần tải lên với thư mục chính đã bị xoá',
'file_size_no_match' => 'Tập tin tải xuống không cùng kích cỡ đúng.',
'default_lang_behavior' => 'XBackBone sẽ khớp ngôn ngữ bạn đang sử dụng mặc định trên trình duyệt (trường hợp ngôn ngữ bạn dùng chưa hỗ trợ, ngôn ngữ dự phòng là tiếng Anh).',
'donation' => 'Quyên góp',
'dont_close' => 'Xin đừng đóng tab này đến khi đã hoàn thành xử lý.',
'register_enabled' => 'Đã bật chế độ cho người dùng đăng ký',
'prerelease_channel' => 'Kênh phát hành phiên bản sớm',
'hide_by_default' => 'Mặc định ẩn đi hình ảnh video tải lên',
'custom_head_set' => 'Phần đầu HTML tuỳ chỉnh đã được áp dụng.',
'mail.activate_text' => 'Xin chào %s!<br>cảm ơn bạn đã tạp tài khảon trên %s (<a href="%s">%s</a>), hãy bấm vào đường link sau để kích hoạt tài khoản của bạn:<br><br><a href="%s">%s</a>',
'max_user_quota' => 'Dung lượng tối đa cho người dùng',
'only_recaptcha_v3' => 'Chỉ hỗ trợ reCAPTCHA v3.',
'account_activated' => 'Tài khoản đã được kích hoạt, bạn có thể đăng nhập vào rồi!',
'password_repeat' => 'Nhập lại mật khẩu',
'recaptcha_keys_required' => 'Tất cả những mã reCAPTCHA đều buộc phải có.',
'send_notification' => 'Gửi email thông báo',
'quota_enabled' => 'Bật dung lượng cho người dùng',
'used_space' => 'Dung lượng đã dùng',
'danger_zone' => 'Vùng nguy hiểm',
'account_media_deleted' => 'Tất cả những hình ảnh video có trong tài khoản đã được xoá.',
'recaptcha_secret_key' => 'Mã reCAPTCHA bí mật',
'mail.new_account_text_with_reset' => 'Xin chào %s!<br>một tài khoản mới đã được tạo cho bạn ở %s (<a href="%s">%s</a>), hãy bấm vào đường link sau để cài mật khẩu và kích hoạt tài khoản nhé:<br><br><a href="%s">%s</a>',
'mail.new_account_text_with_pw' => 'Xin chào %s!<br>một tài khoản mới đã được tạo cho bạn trên %s (<a href="%s">%s</a>), với thông tin đăng nhập như sau:<br><br>Tên đăng nhập: %s<br>Mật khẩu: %s<br><br>Hãy bấm vào đường link sau đây để truy cập trang đăng nhập tài khoản nhé:<br><a href="%s">%s</a>',
'ldap_cant_connect' => 'Không thể kết nối với máy chủ xác minh LDAP.',
];

View file

@ -0,0 +1,164 @@
<?php
return [
'send' => '发送',
'no_media' => '未找到媒体。',
'yes' => '是',
'enforce_language' => '默认语言',
'no' => '否',
'lang' => '中文(简体)',
'copy_link' => '复制链接',
'size' => '大小',
'download' => '下载',
'user.edit' => '编辑用户',
'deleted_orphans' => '已成功删除 %d 个孤立文件。',
'drop_to_upload' => '单击或将您的文件拖放到此处进行上传。',
'settings_saved' => '系统设置已保存!',
'file_size_no_match' => '下载的文件与正确的文件大小不匹配。',
'default_lang_behavior' => '默认情况下XBackBone 将尝试匹配浏览器语言(后备为英语)。',
'custom_head_html' => '自定义 HTML Head 内容',
'remember_me' => '记住我',
'recover_email_sent' => '如果存在,则恢复电子邮件已发送到指定帐户。',
'hide_by_default' => '默认隐藏媒体',
'password_recovery' => '恢复密码',
'password' => '密码',
'login' => '登录',
'home' => '家',
'users' => '用户',
'profile' => '用户资料',
'pager.next' => '下一页',
'public.telegram' => '在Telegram上分享',
'preview' => '预览',
'filename' => '文件名',
'upload' => '上传',
'delete' => '删除',
'publish' => '发布',
'hide' => '隐藏',
'files' => '文件',
'orphaned_files' => '孤立文件',
'theme' => '主题',
'click_to_load' => '点击加载…',
'apply' => '应用',
'save' => '保存',
'php_info' => 'PHP 信息',
'system_settings' => '系统设置',
'user.create' => '创建用户',
'update' => '更新',
'is_active' => '是普通用户',
'is_admin' => '是管理员',
'token' => '令牌',
'your_profile' => '你的个人资料',
'user_code' => '用户代码',
'reg_date' => '注册日期',
'open' => '打开',
'confirm_string' => '你确定吗?',
'installed' => '安装成功完成!',
'bad_login' => '错误的凭据。',
'welcome' => '欢迎, %s!',
'goodbye' => '再见!',
'token_not_found' => '未找到指定的令牌。',
'email_required' => '需要电子邮件地址。',
'email_taken' => '电子邮件地址已被使用。',
'username_taken' => '用户名已被占用。',
'password_required' => '密码是必需的。',
'user_created' => '用户 "%s" 创建成功!',
'none' => '空',
'confirm' => '确认',
'cannot_write_file' => '目标路径不可写。',
'switch_to' => '切换到',
'table' => '表格',
'dotted_search' => '搜索…',
'order_by' => '分组…',
'gallery' => '大图模式',
'time' => '时间',
'name' => '名称',
'maintenance' => '维护',
'new_version_available' => '新版本 %s 可用!',
'donation' => '捐款',
'register_success' => '帐户已创建,确认电子邮件已发送。',
'max_user_quota' => '最大用户配额',
'invalid_quota' => '作为默认用户配额的值无效。',
'mail.activate_text' => '你好 %s !<br>感谢您创建您的帐户 %s (<a href="%s">%s</a>), 点击以下链接激活它:<br><br><a href="%s">%s</a>',
'mail.activate_account' => '%s - 帐号激活',
'mail.recover_password' => '%s - 密码恢复',
'recalculate_user_quota' => '从磁盘重新计算用户配额',
'danger_zone' => '危险区',
'send_notification' => '发送电子邮件通知',
'mail.new_account_text_with_reset' => '你好 %s !<br>为您创建了一个新帐户 %s (<a href="%s">%s</a>), 点击以下链接设置密码并激活:<br><br><a href="%s">%s</a>',
'user_create_password' => '如果留空,您可能希望向用户电子邮件地址发送通知。',
'ldap_cant_connect' => '无法连接到 LDAP 身份验证服务器。',
'auto_tagging' => '自动上传标签',
'account_disabled' => '您的帐户已被禁用。',
'copy_url_behavior' => '复制网址方式',
'zip_ext_not_loaded' => '未加载所需的zip扩展名',
'changelog' => '变更日志',
'show_changelog' => '显示日志',
'image_embeds' => '嵌入图像',
'already_latest_version' => '您已经拥有最新版本。',
'edit' => '编辑',
'system' => '系统',
'owner' => '所有者',
'date' => '日期',
'client_config' => '客户端配置',
'active' => '普通用户',
'login.username' => '用户名或电子邮件',
'username' => '用户名',
'logout' => '注销',
'pager.previous' => '上一页',
'public' => '公共',
'public.delete_text' => '你确定要删除这个项目吗?你将无法恢复它',
'raw' => '显示原始',
'copy' => '复制',
'copied' => '已复制到剪贴板!',
'admin' => '管理员',
'username_required' => '用户名是必需的。',
'user_updated' => '用户"%s" 更新成功!',
'cannot_delete' => '您不能删除自己。',
'cannot_demote' => '你不能禁用自己。',
'clean_orphaned_uploads' => '清理孤立上传',
'path_not_writable' => '输出路径不可写。',
'cannot_retrieve_file' => '无法检索文件。',
'profile_updated' => '个人资料更新成功!',
'user_deleted' => '用户已删除。',
'check_for_updates' => '检查更新',
'updates' => '更新',
'maintenance_in_progress' => '平台维护中,稍后再试…',
'auto_set' => '自动设置',
'upgrade' => '升级',
'cancel' => '取消',
'please_wait' => '请稍等…',
'no_upload_token' => '您没有个人上传令牌。 (生成一个并重试。)',
'custom_head_html_hint' => '此内容将添加到每个页面的 <head> 标记处。',
'custom_head_set' => '应用了自定义 HTML 头。',
'dont_close' => '在完成之前不要关闭此选项卡。',
'donate_text' => '如果您喜欢 XBackBone请考虑捐赠以支持开发',
'register_enabled' => '已启用注册',
'no_account' => '没有帐户?',
'account_activated' => '帐号已激活,现在您可以登录了!',
'quota_enabled' => '启用用户配额',
'password_match' => '密码和重复密码必须相同。',
'password_restored' => '重设密码。',
'export_data' => '导出数据',
'default_user_quota' => '默认用户配额',
'register' => '注册',
'password_repeat' => '重复输入密码',
'quota_recalculated' => '成功从磁盘重新计算用户配额。',
'delete_all' => '删除全部',
'clear_account' => '清除帐户',
'account_media_deleted' => '帐户中的所有媒体均已删除。',
'mail.new_account_text_with_pw' => '你好 %s !<br>为您创建了一个新帐户 %s (<a href="%s">%s</a>), 一下是登录信息:<br><br>用户名: %s <br>密码: %s <br><br>点击以下链接进入登录页面:<br><a href="%s"> %s </a>',
'used_space' => '已用空间',
'delete_selected' => '删除所选',
'upload_max_file_size' => '当前最大文件大小为 %s.',
'no_tags' => '未添加标签',
'mail.recover_text' => 'Hi %s,<br>已为您的帐户请求重置密码。要完成该过程,请单击以下链接:<br><br><a href="%s">%s</a><br><br>如果不是您要求重置密码,请忽略此电子邮件。',
'used' => '使用中',
'recaptcha_site_key' => 'reCAPTCHA 站点密钥',
'only_recaptcha_v3' => '只支持reCAPTCHA v3.',
'vanity_url' => '自定义网址',
'mail.new_account' => '新帐户创建',
'recaptcha_failed' => '验证失败',
'recaptcha_enabled' => '验证码启用',
'recaptcha_secret_key' => 'reCAPTCHA 密钥',
'prerelease_channel' => '预发布渠道',
'recaptcha_keys_required' => '所有 reCAPTCHA 密钥都是必需的。',
];

View file

@ -0,0 +1,19 @@
<div class="modal fade" id="modalVanity" tabindex="-1" role="dialog" aria-hidden="true">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">{{ lang('vanity_url') }}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<input type="text" class="form-control" id="modalVanity-input" maxlength="64">
</div>
<div class="modal-footer">
<button class="btn btn-primary media-vanity" id="modalVanity-link"><i class="fas fa-check fa-fw"></i> {{ lang('confirm') }}</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{ lang('no') }}</button>
</div>
</div>
</div>
</div>

6
resources/templates/dashboard/grid.twig Normal file → Executable file
View file

@ -19,7 +19,7 @@
<div class="pl-3 pt-2d5"><span class="badge badge-dark shadow-lg">{{ media.size }}</span></div>
<div class="text-right pr-3 pt-2d5">
<div class="btn-group shadow-lg">
<button type="button" class="btn btn-sm btn-success btn-clipboard" data-toggle="tooltip" title="{{ lang('copy_link') }}" data-clipboard-text="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ media.extension) }}{{ copy_raw ? '/raw' }}">
<button type="button" class="btn btn-sm btn-success btn-clipboard" data-toggle="tooltip" title="{{ lang('copy_link') }}" data-clipboard-text="{{ urlFor(glue(media.user_code, media.code) ~ (copy_raw ? '/raw.' ~ media.extension : '.' ~ media.extension)) }}">
<i class="fas fa-link"></i>
</button>
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ media.extension ~ '/download') }}" class="btn btn-sm btn-secondary" data-toggle="tooltip" title="{{ lang('download') }}"><i class="fas fa-cloud-download-alt"></i></a>
@ -28,6 +28,7 @@
{% else %}
<a class="btn btn-sm btn-info publish-toggle" data-toggle="tooltip" title="{{ lang('publish') }}" data-id="{{ media.id }}" data-published="{{ media.published }}"><i class="fas fa-check-circle"></i></a>
{% endif %}
<button class="btn btn-info btn-sm public-vanity" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('vanity_url') }}"><i class="fas fa-star"></i></button>
<button type="button" class="btn btn-sm btn-danger media-delete" data-link="{{ route('upload.delete', {'id': media.id}) }}" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('delete') }}">
<i class="fas fa-trash"></i>
</button>
@ -68,4 +69,5 @@
<div class="text-center text-muted"><i>{{ lang('no_media') }}</i></div>
{% endif %}
</div>
{% endblock %}
{% include 'comp/modal_vanity.twig' %}
{% endblock %}

8
resources/templates/dashboard/list.twig Normal file → Executable file
View file

@ -6,6 +6,7 @@
{% include 'comp/navbar.twig' %}
<div class="container">
{% include 'comp/alert.twig' %}
{% include 'comp/modal_vanity.twig' %}
<div class="card shadow-sm">
<div class="card-body">
@ -32,6 +33,7 @@
{% for media in medias %}
<tr id="media_{{ media.id }}" class="bulk-selector" data-id="{{ media.id }}">
<td class="text-center">
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ media.extension) }}" target="_blank" class="text-dark">
{% if isDisplayableImage(media.mimetype) %}
{% if media.username is not null %}
<img src="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ media.extension ~ '/raw?width=84&height=42') }}" class="img-fluid rounded">
@ -41,6 +43,7 @@
{% else %}
<i class="far {{ mime2font(media.mimetype) }} fa-2x"></i>
{% endif %}
</a>
</td>
<td>
<span class="text-maxlen">{{ media.filename }}</span>
@ -68,7 +71,7 @@
{% if media.username is not null %}
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ media.extension) }}" class="btn btn-sm btn-outline-secondary" data-toggle="tooltip" title="{{ lang('open') }}" target="_blank"><i class="fas fa-external-link-alt"></i></a>
<a href="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ media.extension ~ '/download') }}" class="btn btn-sm btn-outline-primary" data-toggle="tooltip" title="{{ lang('download') }}"><i class="fas fa-cloud-download-alt"></i></a>
<a href="javascript:void(0)" class="btn btn-sm btn-outline-success btn-clipboard" data-toggle="tooltip" title="{{ lang('copy_link') }}" data-clipboard-text="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ media.extension) }}{{ copy_raw ? '/raw' }}"><i class="fas fa-link"></i></a>
<a href="javascript:void(0)" class="btn btn-sm btn-outline-success btn-clipboard" data-toggle="tooltip" title="{{ lang('copy_link') }}" data-clipboard-text="{{ urlFor(glue(media.user_code, media.code) ~ (copy_raw ? '/raw.' ~ media.extension : '.' ~ media.extension)) }}"><i class="fas fa-link"></i></a>
{% else %}
<a href="{{ route('upload.raw', {'id': media.id}) }}" class="btn btn-sm btn-outline-dark" data-toggle="tooltip" title="{{ lang('raw') }}" target="_blank"><i class="fas fa-external-link-alt"></i></a>
{% endif %}
@ -77,6 +80,7 @@
{% else %}
<a href="javascript:void(0)" class="btn btn-sm btn-outline-info publish-toggle" data-toggle="tooltip" title="{{ lang('publish') }}" data-id="{{ media.id }}" data-published="{{ media.published }}"><i class="fas fa-check-circle"></i></a>
{% endif %}
<a href="javascript:void(0)" class="btn btn-sm btn-outline-info public-vanity" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('vanity_url') }}"><i class="fas fa-star"></i></a>
<a href="javascript:void(0)" class="btn btn-sm btn-outline-danger media-delete" data-link="{{ route('upload.delete', {'id': media.id}) }}" data-id="{{ media.id }}" data-toggle="tooltip" title="{{ lang('delete') }}"><i class="fas fa-trash"></i></a>
</div>
</td>
@ -96,4 +100,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock %}

View file

@ -16,6 +16,7 @@
{% if tags is empty %}
<h6 class="dropdown-header">{{ lang('no_tags') }}</h6>
{% else %}
<a class="dropdown-item" href="{{ route('home') }}">{{ lang('show_all_tags') }}</a>
{% for tag in tags %}
<a class="dropdown-item {{ request.queryParams['tag'] == tag.id ? 'active' }}" href="{{ queryParams({'tag': tag.id}) }}" data-id="{{ tag.id }}">{{ tag.name }}</a>
{% endfor %}

View file

@ -71,6 +71,12 @@
<input type="checkbox" name="auto_tagging" data-toggle="toggle" {{ settings.auto_tagging == 'on' ? 'checked' }}>
</div>
</div>
<div class="form-group row">
<label for="image_embeds" class="col-sm-4 col-form-label">{{ lang('image_embeds') }}</label>
<div class="col-sm-8">
<input type="checkbox" name="image_embeds" data-toggle="toggle" {{ settings.image_embeds == 'on' ? 'checked' }}>
</div>
</div>
<div class="form-group row">
<label for="themes" class="col-sm-4 col-form-label">{{ lang('theme') }}</label>
<div class="col-sm-8">
@ -215,4 +221,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock %}

View file

@ -0,0 +1,52 @@
#!/bin/bash
create_desktop_entry() {
cat << "EOF" > "$HOME/.local/share/kio/servicemenus/xbackbone-uploader.desktop"
[Desktop Entry]
Type=Service
ServiceTypes=KonqPopupMenu/Plugin
Icon=imaga
X-KDE-StartupNotify=false
X-KDE-Priority=TopLevel
MimeType=image/*;
Actions=xbackbone_upload
[Desktop Action xbackbone_upload]
Name=Upload with XBackBone
Exec=sh -c 'RESPONSE="$(curl -s -F "token={{ token }}" -F "upload=@%u" {{ upload_url }})"; if [ "$(echo "${RESPONSE}" | jq -r ".message")" = "OK" ]; then URL="$(echo "${RESPONSE}" | jq -r ".url")"; if [ "${DESKTOP_SESSION}" != "" ]; then echo "${URL}" | xclip -selection c; notify-send "Upload completed!" "${URL}"; else echo "${URL}"; fi; exit 0; else MESSAGE="$(echo "${RESPONSE}" | jq -r ".message")"; if [ $? -ne 0 ]; then echo "Unexpected response:"; echo "${RESPONSE}"; exit 1; fi; if [ "${DESKTOP_SESSION}" != "" ]; then notify-send "Error!" "${MESSAGE}"; else echo "Error! ${MESSAGE}"; fi; exit 1; fi'
Icon=image
EOF
echo "Service menu created!";
}
check() {
ERRORS=0;
if [ ! -x "$(command -v jq)" ]; then
echo "jq command not found.";
ERRORS=1;
fi
if [ ! -x "$(command -v curl)" ]; then
echo "curl command not found.";
ERRORS=1;
fi
if [ ! -x "$(command -v xclip)" ] && [ "${DESKTOP_SESSION}" != "" ]; then
echo "xclip command not found.";
ERRORS=1;
fi
if [ ! -x "$(command -v notify-send)" ] && [ "${DESKTOP_SESSION}" != "" ]; then
echo "notify-send command not found.";
ERRORS=1;
fi
if [ "${ERRORS}" -eq 1 ]; then
exit 1;
fi
}
check
create_desktop_entry

24
resources/templates/upload/public.twig Normal file → Executable file
View file

@ -17,8 +17,22 @@
<meta id="embed-image" property="og:image" content="{{ url }}/raw">
<meta id="discord" name="twitter:image" content="{{ url }}/raw">
<meta id="image-src" name="twitter:image:src" content="{{ url }}/raw">
<meta id="discord" name="twitter:image" content="{{ url }}/raw">
<meta id="image-src" name="twitter:image:src" content="{{ url }}/raw">
{% elseif type == 'video' %}
<meta name="twitter:card" content="player" />
<meta name="twitter:title" content="{{ media.filename }} ({{ media.size }})" />
<meta name="twitter:image" content="0" />
<meta name="twitter:player:stream" content="{{ url }}/raw" />
<meta name="twitter:player:width" content="720" />
<meta name="twitter:player:height" content="480" />
<meta name="twitter:player:stream:content_type" content="{{ media.mimetype }}" />
<meta property="og:url" content="{{ url }}/raw" />
<meta property="og:video" content="{{ url }}/raw" />
<meta property="og:video:secure_url" content="{{ url }}/raw" />
<meta property="og:video:type" content="{{ media.mimetype }}" />
<meta property="og:video:width" content="720" />
<meta property="og:video:height" content="480" />
<meta property="og:image" content="0" />
{% endif %}
{% endblock %}
@ -31,10 +45,11 @@
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<div class="ml-auto">
<a href="javascript:void(0)" class="btn btn-success my-2 my-sm-0 btn-clipboard" data-toggle="tooltip" title="{{ lang('copy_link') }}" data-clipboard-text="{{ url }}{{ copy_url_behavior == 'raw' ? '/raw' }}"><i class="fas fa-link fa-lg fa-fw"></i></a>
<a href="javascript:void(0)" class="btn btn-success my-2 my-sm-0 btn-clipboard" data-toggle="tooltip" title="{{ lang('copy_link') }}" data-clipboard-text="{{ urlFor(glue(media.user_code, media.code) ~ (copy_raw ? '/raw.' ~ media.extension : '.' ~ media.extension)) }}"><i class="fas fa-link fa-lg fa-fw"></i></a>
<a href="{{ url }}/raw" class="btn btn-secondary my-2 my-sm-0" data-toggle="tooltip" title="{{ lang('raw') }}"><i class="fas fa-file-alt fa-lg fa-fw"></i></a>
<a href="{{ url }}/download" class="btn btn-warning my-2 my-sm-0" data-toggle="tooltip" title="{{ lang('download') }}"><i class="fas fa-cloud-download-alt fa-lg fa-fw"></i></a>
{% if session.get('logged') %}
<a href="javascript:void(0)" class="btn btn-info my-2 my-sm-0 public-vanity" data-link="{{ route('upload.vanity', {'id': media.mediaId}) }}" data-id="{{ media.mediaId }}" data-toggle="tooltip" title="{{ lang('vanity') }}"><i class="fas fa-star fa-lg fa-fw"></i></a>
<a href="javascript:void(0)" class="btn btn-danger my-2 my-sm-0 public-delete" data-link="{{ route('upload.delete', {'id': media.mediaId}) }}" data-toggle="tooltip" title="{{ lang('delete') }}"><i class="fas fa-trash fa-lg fa-fw"></i></a>
{% endif %}
</div>
@ -43,7 +58,7 @@
</nav>
<div class="container-fluid">
{% include 'comp/alert.twig' %}
<div class="row ml-auto mr-auto">
<div class="row">
<div class="col-md-12 justify-content-center">
{% if delete_token is not null %}
<form method="post" action="{{ url }}/delete/{{ delete_token }}">
@ -148,4 +163,5 @@
</div>
</div>
{% include 'comp/modal_delete.twig' %}
{% include 'comp/modal_vanity.twig' %}
{% endblock %}

View file

@ -40,7 +40,7 @@
<label for="token" class="col-sm-3 col-form-label">{{ lang('token') }}</label>
<div class="col-sm-9">
<div class="input-group">
<input type="text" id="token" class="form-control" value="{{ user.token }}" readonly>
<input type="text" id="token" class="form-control privacy-blur" value="{{ user.token }}" readonly>
<div class="input-group-append">
<button class="btn btn-outline-success btn-clipboard" type="button" data-clipboard-target="#token"><i class="fas fa-fw fa-copy"></i> {{ lang('copy') }}</button>
<button class="btn btn-outline-primary refresh-token" data-id="{{ user.id }}" type="button"><i class="fas fa-fw fa-sync"></i> {{ lang('update') }}</button>
@ -66,7 +66,11 @@
<div class="btn-group">
<a href="{{ route('config.sharex', {'id': user.id}) }}" class="btn btn-lg btn-outline-dark"><i class="fas fa-fw fa-download"></i> ShareX</a>
<a href="javascript:alert('{{ lang('copied') }}')" data-clipboard-text="{{ route('config.screencloud', {'token': user.token}) }}" class="btn btn-lg btn-outline-info btn-clipboard"><i class="fas fa-fw fa-download"></i> Screencloud</a>
<a href="{{ route('config.script', {'id': user.id}) }}" class="btn btn-lg btn-outline-danger"><i class="fas fa-fw fa-download"></i> Linux Script</a>
<a href="{{ route('config.script', {'id': user.id}) }}" type="button" class="btn btn-lg btn-outline-danger"><i class="fas fa-fw fa-download"></i> Linux Script</a>
<button type="button" class="btn btn-outline-danger dropdown-toggle dropdown-toggle-split" id="userDropdown" data-toggle="dropdown" aria-expanded="false"></button>
<ul class="dropdown-menu">
<li><a class="dropdown-item text-danger" href="{{ route('kde_config.script', {'id': user.id}) }}"><i class="fas fa-fw fa-download"></i> KDE Linux Script</a></li>
</ul>
</div>
</div>
</div>
@ -133,4 +137,4 @@
</div>
</div>
</div>
{% endblock %}
{% endblock %}

View file

@ -223,4 +223,9 @@ body {
.hljs-ln-code {
padding-left: 5px !important;
}
}
.privacy-blur:not(:focus) {
color: transparent;
text-shadow: 0 0 5px rgba(0,0,0,0.5);
}

48
src/js/app.js Normal file → Executable file
View file

@ -29,8 +29,10 @@ var app = {
$('.user-delete').click(app.modalDelete);
$('.public-delete').click(app.modalDelete);
$('.public-vanity').click(app.modalVanity);
$('.media-delete').click(app.mediaDelete);
$('.publish-toggle').click(app.publishToggle);
$('.refresh-token').click(app.refreshToken);
$('#themes').mousedown(app.loadThemes);
$('.checkForUpdatesButton').click(app.checkForUpdates);
@ -46,6 +48,10 @@ var app = {
$('.alert').slideUp(500);
});
if ($('.dropzone').length > 0) {
app.initClipboardPasteToUpload();
}
new ClipboardJS('.btn-clipboard');
new Plyr($('#player'), {ratio: '16:9'});
@ -57,6 +63,30 @@ var app = {
$('#modalDelete-link').attr('href', $(this).data('link'));
$('#modalDelete').modal('show');
},
modalVanity: function () {
var id = $(this).data('id');
$('#modalVanity').modal('show');
$('#modalVanity-link').click(function () {
var $callerButton = $(this);
$.post(window.AppConfig.base_url + '/upload/' + id + '/vanity', {vanity: $('#modalVanity-input').val()}, function (responseData, status) {
$callerButton.tooltip('dispose');
$('#modalVanity').modal('hide');
$('#modalVanity-input').val('');
var parsedData = JSON.parse(responseData);
if ($('#media_' + id).find('.btn-group').length > 0) {
$('#media_' + id).find('.btn-group').find('a').each(function (item) {
var oldUrl = $(this).attr('href');
var newUrl = oldUrl.replace(oldUrl.substr(oldUrl.lastIndexOf('/') + 1), parsedData.code.code);
$(this).attr('href', newUrl);
});
} else {
var oldUrl = window.location.href;
var newUrl = oldUrl.replace(oldUrl.substr(oldUrl.lastIndexOf('/') + 1), parsedData.code.code);
window.location.href = newUrl;
}
});
});
},
publishToggle: function () {
var id = $(this).data('id');
var $callerButton = $(this);
@ -114,6 +144,9 @@ var app = {
var opt = document.createElement('option');
opt.value = value;
opt.innerHTML = key;
if (value === null) {
opt.disabled = true;
}
$themes.append(opt);
});
});
@ -223,7 +256,20 @@ var app = {
$('#dropdown-tag-list > a[data-id="' + $tag.data('id') + '"]').remove();
}
});
}
},
initClipboardPasteToUpload: function() {
document.onpaste = function(event){
if (event.clipboardData || event.originalEvent.clipboardData) {
const items = (event.clipboardData || event.originalEvent.clipboardData).items;
items.forEach((item) => {
if (item.kind === 'file') {
// Add the file to the dropzone instance.
Dropzone.forElement('.dropzone').addFile(item.getAsFile());
}
});
}
}
},
};
app.init();

View file

@ -7,7 +7,6 @@ use Tests\TestCase;
class LoginControllerTest extends TestCase
{
/** @test */
public function it_loads_the_login_page()
{

View file

@ -8,7 +8,7 @@ use Tests\TestCase;
class PasswordRecoveryControllerTest extends TestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
Mail::fake();

View file

@ -8,7 +8,7 @@ use Tests\TestCase;
class RegisterControllerTest extends TestCase
{
protected function setUp()
protected function setUp(): void
{
parent::setUp();
$this->updateSetting('register_enabled', 'on');
@ -97,7 +97,7 @@ class RegisterControllerTest extends TestCase
$this->assertSame(route('login'), $response->getHeaderLine('Location'));
$result = $this->database()->query('SELECT * FROM users WHERE id = ?', $userId)->fetch();
$this->assertSame('1', $result->active);
$this->assertSame(1, (int) $result->active);
$this->assertNull($result->activate_token);
}

View file

@ -8,7 +8,7 @@ abstract class TestCase extends BaseTestCase
{
use WithApplication;
protected function setUp()
protected function setUp(): void
{
parent::setUp();
$_SESSION = []; // ugly workaround to the the session superglobal between tests