224 Commits
1.3 ... 1.3.4

Author SHA1 Message Date
El RIDO
9914c37683 incrementing version 2020-03-22 06:44:04 +01:00
El RIDO
1439bb291f allow pasting password on paste with attachment - big kudos @rugk for finding it! - fixes #565, fixes #595 2020-03-21 16:53:55 +01:00
El RIDO
0907ee90e3 documenting change 2020-03-21 16:07:11 +01:00
El RIDO
7abfe56910 Merge branch 'preview-encoding' 2020-03-21 15:59:25 +01:00
El RIDO
71c76adac4 addressing false positive jsverify rngState 077c06da821594b3fe 2020-03-06 23:00:48 +01:00
rugk
7cb830e22f It includes a change in the RegEx for URLs because that was broken when a
& character later followed at any time after a link (even after a newline).
(with a negative lookahead)

Test with https://regex101.com/r/i7bZ73/1

Now the RegEx does not check for _all_ chars after a link, but just for the
one following the link.
(So the lookahead is not * anymore. I guess thsi behaviour was
the expectation when it has been implemented.)
2020-03-06 22:37:12 +01:00
El RIDO
c334d2d00d Merge branch 'master' into preview-encoding 2020-03-06 22:23:40 +01:00
El RIDO
c11dc8e17e reverting Helper.urls2links() method to old style, applied to element instead of string, allows inserting plain text as text node 2020-03-06 22:18:38 +01:00
El RIDO
8a6dcf910a Revert "in Helper.urls2links(), encode HTML entities, find and insert links, partially decoding only the href property of it"
This reverts commit 5340f417e0.
2020-03-06 20:57:15 +01:00
El RIDO
33bb0c6bd6 trying to recreate former StyleCI behaviour in changed preset 2020-03-06 20:50:19 +01:00
El RIDO
0564c0e62e fixing 'The provided fixer 'method_argument_space' cannot be disabled unless it was already enabled by your preset.' 2020-03-06 20:46:51 +01:00
El RIDO
f05e5c2e29 documenting change 2020-03-01 16:14:19 +01:00
El RIDO
879a2a9255 tweaking German translation for email strings 2020-03-01 08:55:24 +01:00
El RIDO
f391773c65 generalize date string handling, replacing hardcoded lookups, fixes #586 2020-03-01 08:54:48 +01:00
El RIDO
5340f417e0 in Helper.urls2links(), encode HTML entities, find and insert links, partially decoding only the href property of it 2020-02-29 09:37:54 +01:00
El RIDO
d2e9e47b67 refactor switch into nested if/else, to improve readability - no functional change 2020-02-29 08:45:56 +01:00
El RIDO
b0800060c2 fix change log 2020-02-16 13:33:48 +01:00
El RIDO
15f66870d1 Merge branch 'php7.4-ci' 2020-02-16 13:27:16 +01:00
El RIDO
afd82ac34d Merge branch 'master' into php7.4-ci 2020-02-16 13:23:11 +01:00
El RIDO
adece1d784 incrementing version 2020-02-16 11:15:51 +01:00
El RIDO
e74d786a68 update change log 2020-02-16 07:23:20 +01:00
El RIDO
f190317d95 remove obsolete sudo key 2020-02-05 19:35:46 +01:00
El RIDO
5d54006c9e update minimum required PHP version to 5.6 and replace slowEquals() with native hash_equals() function 2020-02-05 19:30:14 +01:00
El RIDO
2870023e9c updating composer requirements und identicon library 2020-02-05 19:17:22 +01:00
El RIDO
df7a06315f drop php 5.5 tests, allowing us to use current ubuntu bionic based environment and adding php 7.4 incl. GD library 2020-02-05 19:15:43 +01:00
El RIDO
12c83a13c7 addressing false positive jsverify rngState 85f362db8950cea741 2020-02-05 19:06:45 +01:00
El RIDO
aa377038a0 fixing DOMpurify 2.0.8 SRI after removing map line in file (which causes unnecessary requests to missing files in the browser) 2020-02-05 19:05:37 +01:00
El RIDO
7038fd5712 Revert "add 7.4 to travis CI tests"
This reverts commit 81194f6bd6.

Found that the trusty based php 7.4 in TravisCI doesn't include the GD module, that we need, plus there is an issue with the Filter::slowEquals() function that only remains for php 5.5 support that doesn't yet contain hash_compare().
2020-02-05 18:52:53 +01:00
El RIDO
81194f6bd6 add 7.4 to travis CI tests 2020-02-05 16:50:08 +01:00
El RIDO
bab95cce1b addressing false positive jsverify rngState 8bf7605ea139db4c28 2020-02-04 18:58:24 +01:00
El RIDO
00438ec1ab upgrade DOMpurify to 2.0.8 2020-02-04 18:43:35 +01:00
El RIDO
87423abd7c Fix ARIA for Editor/preview tabs. 2020-02-04 18:29:14 +01:00
El RIDO
347e7e03e1 Merge pull request #582 from RoiArthurB/patch-1
Update fr.json
2020-02-04 11:24:59 +01:00
Arthur Brugiere
6e08d8a497 Update fr.json
Fix missing translate + invalid translations
2020-02-04 14:54:47 +07:00
El RIDO
3fdd42487a fix FAQ links, tweaking the subtext display, add link to modern browser FAQ, fixes #577 2020-02-02 07:35:33 +01:00
El RIDO
2cbb8bf3ca in translation, allow links to be inserted unencoded into href attribute, simplfy sanitation by allowing only <a> tags in DOMpurify for plain text and comments and avoid DOMpurify removing magnet links, fixes #579 2020-02-02 07:08:38 +01:00
El RIDO
3996f82404 relax encoding of slashes just for plaintext display, so links can be detected 2020-02-01 16:30:41 +01:00
El RIDO
d7fd6667fd Merge branch 'displayEncoding2' 2020-02-01 16:16:05 +01:00
El RIDO
21ca30af3c apply StyleCI recommendation 2020-02-01 09:39:14 +01:00
El RIDO
1b206e8495 ensuring consistent use of php side encoding, testing all encoding cases, correctly report the language in the <html> tag 2020-02-01 09:15:14 +01:00
El RIDO
cc0920fc09 add HTML entity encoding to PHP translation logic, remove exception to allow <br/> tags in DOMpurify by eliminating the single case that made use of it 2020-02-01 08:46:59 +01:00
El RIDO
428ea2f34e adding test that expects parameters of php translation to get HTML entities to get encoded 2020-02-01 08:09:30 +01:00
El RIDO
f940f17bba Merge branch 'displayEncoding' 2020-02-01 07:53:32 +01:00
El RIDO
91003d6597 Merge remote-tracking branch 'origin/master' into displayEncoding 2020-02-01 07:52:48 +01:00
El RIDO
9a4018bffe jsverify rngState 8270695ec83abf412d was a false positive, due to incorrect test logic 2020-02-01 07:40:14 +01:00
El RIDO
8a6415ef5f fixing jsverify rngStates 0220439df7ec68a15b, 015c81b7afd06e4293 & 041e3d57692b08fc4a 2020-01-31 22:42:42 +01:00
El RIDO
b674c187a0 Merge pull request #578 from imtms/master
Update Chinese translation.
2020-01-31 21:34:34 +01:00
R4SAS
665192e27e Merge pull request #580 from mkromar/footer-link-fix-sl
Fixed info link in page footer of sl translation.
2020-01-31 19:02:31 +00:00
mkromar
b4256a986a Fixed info link in page footer of sl translation. 2020-01-31 19:47:24 +00:00
TMs
13b30608cb Update Chinese translation. 2020-01-31 12:36:02 +08:00
El RIDO
a86dd35ac3 Merge pull request #574 from PrivateBin/rugk-php-runner
Test PHP Composer runner of GitHub
2020-01-29 13:06:40 +01:00
rugk
19d0cace13 Merge branch 'readmeupdate' 2020-01-27 21:13:47 +01:00
rugk
d0589e77d4 Feature FAQ link in Readme & remove legacy things
* remove old ZeroBin 0.19 guide, this is so old already, few people will benefit from a direct link in the Readme. It stays in the wiki for those, who need it.
* add direct link to the FAQ - it's one of our best documentation/sources, so it's a shame it is not featured more prominently 😉
2020-01-27 15:28:40 +01:00
rugk
271c954f9a Test PHP Composer runner of GitHub
GitHub has these new CI/CD features, so let's test whether this makes sense.

I guess this PHP thing just installs the project via composer… 🤔
2020-01-26 23:25:24 +01:00
Erion
3f8cf1792d Switch to single quotes. 2020-01-26 18:08:59 +01:00
Erion
f6899785a9 Fix ARIA for Editor/preview tabs. 2020-01-25 18:47:18 +01:00
El RIDO
2d11d7b29e re-applying sprintf simplification and rephrased jsdoc block 2020-01-25 09:16:14 +01:00
El RIDO
29efc14aa7 Revert "implement simplified translation logic, forcing the use of safe application via jQuery element"
This reverts commit 62365880b4. The unit tests showed that the text2string function completely undid the XSS fix, so it was always unsafe to use it. Also the logic simplifications were smaller then expected.
2020-01-25 09:07:29 +01:00
El RIDO
62365880b4 implement simplified translation logic, forcing the use of safe application via jQuery element 2020-01-25 09:07:06 +01:00
El RIDO
aa3f1206b2 rewriting translations to pass jQuery element where easily possible 2020-01-25 08:13:36 +01:00
El RIDO
b160e5d1f8 Merge branch 'tupaschoal-translate-pt' 2020-01-22 20:15:20 +01:00
Tulio Leao
56ad0273e4 Update pt translation 2020-01-21 22:47:17 -03:00
El RIDO
83c29165ad Merge branch 'ensag-dev-master' 2020-01-21 19:02:05 +01:00
ensag-dev
39ee46caee Update for e-mail function 2020-01-21 08:11:16 +00:00
ensag-dev
774fea9230 Small corrections 2020-01-21 08:05:17 +00:00
El RIDO
1d8b0d6189 Merge branch 'rylebrun-mail_fr_translation' 2020-01-20 19:39:13 +01:00
El RIDO
72e96c7147 german translation of send to mail messages 2020-01-20 19:38:52 +01:00
El RIDO
1ae4f4f0fc updating all languages with missing translation, addresses failing unit test in previous commit 2020-01-20 19:24:28 +01:00
rylebrun
28c387074f Add mail fr translation for buttons 2020-01-20 12:11:03 +01:00
rylebrun
3993b47e06 Add mail fr translation 2020-01-20 12:03:11 +01:00
El RIDO
42130e0468 prevent potentially non-encoded string from getting returned 2020-01-18 10:53:58 +01:00
El RIDO
685c354d0e several changes:
- added tests for all 4 cases: output to string or into element vs first param contains link or not
- cleaned up logic - skip HTML entity encoding only if we can ensure insertion to text node / when output to string, we always encode
- DOMpurify sanitizes gopher, ws & wss links, which we previosly had tested for
2020-01-18 10:44:35 +01:00
El RIDO
fa9d3037ba fixing logic & indentation 2020-01-18 07:44:32 +01:00
El RIDO
7b87dc3ca9 cleanup revert 2020-01-18 07:36:43 +01:00
El RIDO
0d08edbe55 Revert "getting rid of htmlEntities (except for tests)" a0740ff79f 2020-01-18 07:30:01 +01:00
El RIDO
cec5cb41d7 Partial revert "Do not double-encode HTML in i18n", only revert the removal of required encoding logic - still has to be moved
This reverts commit 01414e43ca.
2020-01-18 07:20:05 +01:00
El RIDO
76eff6a87a Revert "[TEST] Try to disallow vulnerable cases" to remove accidentally committed file and statement that breaks the tests
This reverts commit ebc2d649c4.
2020-01-18 07:12:03 +01:00
El RIDO
fd4492f229 ensuring that both critical branches get tested 2020-01-18 07:09:56 +01:00
El RIDO
5daba16333 Merge branch 'ensag-dev-master' 2020-01-16 05:28:17 +01:00
rugk
eb549d70d1 Invert conatainsLink logic 2020-01-15 17:52:51 +01:00
ensag-dev
9f6c02276a Update Occitan translation 2020-01-14 16:24:53 +01:00
rugk
ebc2d649c4 [TEST] Try to disallow vulnerable cases 2020-01-13 19:56:15 +01:00
rugk
01414e43ca Do not double-encode HTML in i18n
This issue got introduced in 4bf7f86 due to double

Fixes https://github.com/PrivateBin/PrivateBin/issues/557
Fixes https://github.com/PrivateBin/PrivateBin/issues/558

Also _inverted_ the logic/variable name for containsNoLinks to
the more logical one "containsLinks" to avoid too many negations.

Also verified that the attachment name is stil properly displayed
when you clone a paste.
2020-01-13 19:17:30 +01:00
El RIDO
9aac073a49 clarifying for #525 that none is a string, as PHP might evaluate it to NULL instead 2020-01-09 05:42:42 +01:00
El RIDO
599264e167 partially address #556 - now comments can only be added after successfull decryption 2020-01-08 19:48:42 +01:00
El RIDO
ed590ee557 incrementing version 2020-01-08 19:31:06 +01:00
El RIDO
d73f8468d8 documenting changes for 1.2.2 2020-01-08 19:23:33 +01:00
El RIDO
ef8943d838 upgrading base-x library to 3.0.7 2020-01-07 20:11:12 +01:00
El RIDO
2fd649db14 upgrading showdown to released 1.9.1 version 2020-01-07 19:58:05 +01:00
El RIDO
11a7ac4e2b address new fixer in StyleCI causing false positives in templates 2020-01-07 19:39:22 +01:00
El RIDO
a9bf667f8e address error, displayed when paste has attachment, but configuration has them disabled 2020-01-04 13:33:03 +01:00
El RIDO
4bf7f863dc more general solution addressing #554, kudos @rugk for the suggestions 2020-01-04 13:14:53 +01:00
El RIDO
8d0ac336d2 addressing jsverifyRngState 8b8f0d4ec2a67139b5, fixes HTML injection via filename, closes #554 2019-12-25 09:14:32 +01:00
El RIDO
ddaee6486d Merge branch 'm1cr0man-master' 2019-12-25 08:16:33 +01:00
El RIDO
3485922366 documenting change 2019-12-25 08:16:17 +01:00
El RIDO
0efe6f7a8e simplify logic, fullfills the unit test 2019-12-25 08:11:25 +01:00
El RIDO
07a6e3094d adding unit tests for the new confi file env variable 2019-12-25 07:58:14 +01:00
Lucas Savva
7d9ec9509b Handle previously renamed CONFIG_PATH gracefully 2019-12-24 19:12:08 +00:00
Lucas Savva
d5d13fa831 Add logic to rename insecure CONFIG_PATH 2019-12-24 18:51:47 +00:00
Lucas Savva
13fb849973 Add CONFIG_PATH notes to INSTALL.md 2019-12-20 14:28:43 +00:00
Lucas Savva
b5c86e290f squashme: fix code style issue 2019-12-20 10:42:59 +00:00
Lucas Savva
6b0468ebff Add support for a CONFIG_PATH variable 2019-12-19 23:06:32 +00:00
El RIDO
825f6884be updating German translations 2019-12-07 08:26:51 +01:00
El RIDO
ee9e340de0 Merge branch 'qianmengnet-master' 2019-12-07 08:22:44 +01:00
El RIDO
2cbb86cefc adding missing translation IDs, kudos @qianmengnet for finding these 2019-12-07 08:22:29 +01:00
El RIDO
3923817f2b formatting of JSON, unicode tilde 2019-12-07 08:18:13 +01:00
Alex Lee
b00d8e4ad8 Update zh.json 2019-12-05 08:34:42 +08:00
Alex Lee
aa75e596c8 Update zh.json 2019-12-04 12:20:23 +08:00
El RIDO
787daccb78 Merge branch 'Haocen-543' 2019-11-29 19:12:36 +01:00
Haocen Xu
87cf61c39b Update SRI 2019-11-21 17:49:21 -05:00
Haocen Xu
853fd906cb Fix unnecessary closure capture 2019-11-21 17:43:10 -05:00
El RIDO
af8d963fd2 updating DOMpurify library, fixes #523 2019-11-02 17:31:45 +01:00
El RIDO
0ed238a775 Merge branch 'AndriiZ-master' 2019-11-02 17:21:22 +01:00
El RIDO
8cf0c86ebb simplify case statement, update documentation 2019-11-02 17:18:22 +01:00
El RIDO
b23fd48d49 Merge branch 'master' of https://github.com/AndriiZ/PrivateBin into AndriiZ-master 2019-11-02 17:11:05 +01:00
El RIDO
ffe26a8841 Merge branch 'Haocen-398' 2019-11-02 17:04:19 +01:00
El RIDO
0b6139fb42 updating change log and optimizing png 2019-11-02 17:03:40 +01:00
Haocen Xu
7d7ff34d83 Update SRI 2019-10-31 15:07:24 -04:00
Haocen Xu
e079f6c830 Implement Email button 2019-10-31 15:07:13 -04:00
Haocen Xu
63fdd2eba3 Fix missing semi colon 2019-10-30 14:04:10 -04:00
El RIDO
759113f453 Merge branch 'Haocen-527' 2019-10-26 06:04:39 +02:00
El RIDO
7255cd29a7 documenting change 2019-10-26 06:04:21 +02:00
El RIDO
13afa7fe21 Merge branch '527' of https://github.com/Haocen/PrivateBin-Contribute into Haocen-527 2019-10-26 06:01:39 +02:00
El RIDO
00a9e36c59 incrementing version 2019-10-26 06:01:24 +02:00
Haocen Xu
6fc4303acc Update SRI 2019-10-25 13:09:07 -04:00
Haocen Xu
56222d6cfb Bugfix when password is disabled in config no new paste can be
created
2019-10-25 13:05:09 -04:00
Andriy Zhuk
65b7077756 Added plural rules for ukrainian 2019-10-18 12:31:40 +03:00
Andriy Zhuk
03138bcde5 Fixed ... with … 2019-10-18 12:27:40 +03:00
Andriy Zhuk
7e9e3155a8 Fixed few typos 2019-10-17 17:20:00 +03:00
Andriy Zhuk
2b3b47c59d Removed line 2019-10-17 16:03:37 +03:00
Andriy Zhuk
8fc85bc39c Added line 2019-10-17 15:33:12 +03:00
Andriy Zhuk
92571512bf Added ukrainian localization 2019-10-17 15:24:33 +03:00
El RIDO
d3153b5e38 trying to fix travis on PHP 5 by removing composer.lock that depends on imcompatible phpunit version 2019-09-22 22:04:17 +02:00
El RIDO
71797d1dd4 changes required for jsdoc, adding legacy.js to code coverage 2019-09-22 21:18:19 +02:00
El RIDO
476b9c90e2 updating PHP dependencies (they remain unchanged), committing lock for github dependency graph support 2019-09-22 19:52:25 +02:00
El RIDO
2d4edfe401 incrementing version number in preparation of release 2019-09-22 19:42:04 +02:00
El RIDO
ced5f30280 Merge branch 'cryptomilk-master-htaccess' 2019-09-20 07:06:38 +02:00
El RIDO
d5aeba60ca increase default size limit to 10 MiB, documenting change 2019-09-20 07:04:26 +02:00
El RIDO
5c0012cf51 adding database migration to increase data to MEDIUMBLOB on MySQL by default 2019-09-20 06:57:54 +02:00
El RIDO
091dc14074 Merge branch 'master-htaccess' of https://github.com/cryptomilk/PrivateBin into cryptomilk-master-htaccess 2019-09-20 06:28:07 +02:00
El RIDO
a3f793fec7 documenting changes 2019-09-20 06:27:07 +02:00
El RIDO
b496ae42fd Merge branch 'better-feature-detection' 2019-09-20 06:18:10 +02:00
El RIDO
e9eeeacdf0 addressing jsverifyRngState 0f5ea3f961827b0c4d 2019-09-19 20:48:05 +02:00
El RIDO
8da382f7c6 Merge branch 'master' into better-feature-detection 2019-09-19 20:19:35 +02:00
El RIDO
28d70a1b18 upgrading DOMpurify, fixes #520 2019-09-19 20:13:47 +02:00
El RIDO
c1f6e5663b Merge branch 'master' into better-feature-detection 2019-09-19 20:02:00 +02:00
El RIDO
bf0be09f09 removing old IE warning, as it is ignored by IE. The modern warning does get displayed, so let's use this more generic warning instead. 2019-09-19 20:01:10 +02:00
El RIDO
955317d924 make codacy a bit happier 2019-09-19 19:47:19 +02:00
El RIDO
8e27dbff15 clarify the use of 'unsafe-eval' and what the impact removing it has - Firefox users may not care and disable it to improve security 2019-09-19 19:24:28 +02:00
El RIDO
7c61f59dcd removing untranslated string for non-human entities, moving insecure notice to template, so it can remains translated 2019-09-19 19:14:48 +02:00
El RIDO
70c38db81d adding ES6 and async feature detection to correctly flag old chromes and operas with the modern browser error 2019-09-18 07:47:26 +02:00
El RIDO
4332d0edb0 making legacy.js work even on IE 6 by avoiding jQuery 2019-09-18 07:31:32 +02:00
El RIDO
5810f17c31 fixing HTTP only error detection in Chrome and Android by ensuring all logic is contained in legacy.js 2019-09-17 21:41:25 +02:00
El RIDO
15b3d67ba7 adding browserstack badge in order to be elegible for their OpenSource program (https://www.browserstack.com/open-source?ref=pricing) 2019-09-16 20:51:49 +02:00
El RIDO
1a42158dd1 address Codacy's concern about missing semicolons 2019-09-14 09:53:22 +02:00
El RIDO
713ce148a4 address Codacy's concern that i is already defined 2019-09-14 09:50:47 +02:00
El RIDO
63426d6f8b splitting out PrivateBin.InitialCheck class into Legacy.Check and working on making it compatible with IE 11 2019-09-14 09:41:52 +02:00
El RIDO
a363b2ff95 eslint env cleanup 2019-09-08 09:12:56 +02:00
El RIDO
c2962af4f8 trying different approach to convince codacy about false positive 2019-09-08 09:08:21 +02:00
El RIDO
ae11d168ce trying to convince codacy about the eslint changes 2019-09-08 09:02:15 +02:00
El RIDO
7b029d3657 trying to convince codacy about the eslint changes 2019-09-08 08:55:19 +02:00
El RIDO
b1c9ca65fa trying to address eslint false positives 2019-09-08 08:39:28 +02:00
El RIDO
5471757fa7 making webassembly optional, ensuring retry button works when wrong password is provided
Tested configurations:
- browser with WASM support (Firefox 68.0.2)
  - creates paste with zlib compression, no password
  - creates paste with zlib compression, with password
  - reads paste with zlib compression, no password
  - reads paste with zlib compression, with password + retry button works
  - reads paste without compression, no password
  - reads paste without compression, with password + retry button works
- browser without WASM support (Chromium 76.0.3809.100, started via `chromium-browser --js-flags=--noexpose_wasm`)
  - creates paste without compression, no password, but shows WASM warning
  - creates paste without compression, with password, but shows WASM warning
  - fails to read paste with zlib compression, no password + shows WASM error
  - fails to read paste with zlib compression, with password + shows WASM error
  - reads paste without compression, no password
  - reads paste without compression, with password + retry button works
2019-09-08 08:21:54 +02:00
El RIDO
7a85900b7c Merge branch 'master' into better-feature-detection 2019-09-07 11:25:50 +02:00
El RIDO
269def8300 Merge branch 'idarlund-patch-6' 2019-09-07 11:23:20 +02:00
Idar Lund
c992d10833 Update no.json
updated new lines to Norwegian
2019-09-04 12:21:04 +02:00
El RIDO
813e72d871 don't encode HTML entities in translations if they contain links 2019-08-28 20:37:14 +02:00
El RIDO
50881a75e6 ensure bots are prohibited completely from indexing 2019-08-28 20:36:26 +02:00
El RIDO
c56d777c11 fixing logic when there are no icons and warning icons, add more test cases 2019-08-28 20:29:23 +02:00
El RIDO
7f65fe9218 fixing conflicting icons when using error message div for warnings in bootstrap template 2019-08-28 19:25:11 +02:00
El RIDO
ad570c391a extend Alert class unit testing 2019-08-28 19:23:58 +02:00
El RIDO
a6aef109cc making feature detection work as intended in chrome 2019-08-27 23:16:06 +02:00
El RIDO
6fcd82fb85 making the feature detection more robust, let users with no WASM create uncompressed pastes, remove dead & duplicate code 2019-08-27 07:38:27 +02:00
El RIDO
ff68043c9f Merge branch 'Haocen-505-patch' 2019-08-25 18:16:17 +02:00
Haocen Xu
5877111ccb Update SRI 2019-08-25 12:03:37 -04:00
Haocen Xu
00b886c492 Refactor attachment editable logic to avoid undesired assumption 2019-08-25 12:00:59 -04:00
El RIDO
e242d87427 Merge branch 'Haocen-489,491,493,494' 2019-08-25 17:30:20 +02:00
El RIDO
271d4b680a updating changelog 2019-08-25 17:29:52 +02:00
El RIDO
ad096b80a1 refactoring logic, to make intention more clear and reduce complexity 2019-08-25 17:24:22 +02:00
Haocen Xu
b912c07cd1 Update SRI 2019-08-25 02:17:29 -04:00
Haocen Xu
ab75b183fb Fix click on new paste on clone paste editing view not removing custom
attachment

Fix cloning paste with attachment

Update CSP in sample and default configuration

Ensure clone paste also clone format

Fix clone button hiding logic when paste is burn after read

Remove attachment name when new paste clicked on

Enable file operation only when editing
2019-08-25 02:16:58 -04:00
El RIDO
121b1e75d2 remove debug statement, fixes #462 2019-08-24 08:42:33 +02:00
El RIDO
c77726b917 Merge branch 'Haocen-495', fixes #495 2019-08-23 07:02:54 +02:00
Haocen Xu
649c7aaa78 Fix bootstrap 3 support for modern high res monitors 2019-08-22 14:04:42 -04:00
Haocen Xu
6a79519641 Allow textarea to be resized vertically only 2019-08-22 13:55:52 -04:00
El RIDO
e4a0a8e82c Merge branch 'Haocen-317' 2019-08-21 19:04:16 +02:00
El RIDO
72565e48ff Merge branch '317' of https://github.com/Haocen/PrivateBin-Contribute into Haocen-317 2019-08-21 19:03:54 +02:00
Haocen Xu
ffac1adad6 Dropzone should be fixed to viewport, instead of fixed to sibling
element
2019-08-21 02:24:56 -04:00
El RIDO
d317cfbcc0 update SRI hashes 2019-08-21 07:17:24 +02:00
El RIDO
388655fdd1 Merge branch 'Haocen-317', fixes #317, fixes #487 2019-08-21 07:15:09 +02:00
El RIDO
b7b7aa3a47 credit were credit is due 2019-08-21 07:14:46 +02:00
Haocen Xu
2eed7a8a1c Update SRI
Remove dejavu
2019-08-17 15:39:13 -04:00
Haocen Xu
078b8d8fd6 Clear attachment if user cancel file select 2019-08-17 15:14:40 -04:00
Haocen Xu
3a9730f883 Improve file upload UX
Fix incorrect highlight logic

Fix transition on fileupload highlight

Handle drag leave

Fix draghover

Minor style improvements
2019-08-17 15:13:58 -04:00
El RIDO
30ddcacca6 fixing unit tests 2019-08-17 10:20:46 +02:00
El RIDO
1de315619b Merge branch 'macropin', fixes #485 2019-08-17 10:07:16 +02:00
El RIDO
e7fab8439d documenting showdown fix and incrementing library version to circumvent browser caching 2019-08-17 10:04:54 +02:00
El RIDO
f22449ffd1 Merge branch 'fix-showdown' of https://github.com/macropin/PrivateBin into macropin 2019-08-17 09:59:44 +02:00
El RIDO
962df90b24 Merge branch 'Haocen-479' 2019-08-17 09:40:43 +02:00
El RIDO
d351c7b734 documenting changes, fixes #354, fixes #479, fixes #484 2019-08-17 09:40:23 +02:00
El RIDO
84827e19c3 Merge branch '479' of https://github.com/Haocen/PrivateBin-Contribute into Haocen-479 2019-08-17 08:42:25 +02:00
El RIDO
b8196ee63c documented mobile UI change, fixes #477 2019-08-17 08:39:15 +02:00
El RIDO
e6e4facde0 Merge branch 'Haocen-477' 2019-08-17 08:31:07 +02:00
Haocen Xu
6ac425d468 Fix incorrect style on button 2019-08-15 14:58:27 -04:00
Andrew Cutler
49b358b1ee patch showdown.js to allow 100 nested spans. Ref https://github.com/PrivateBin/PrivateBin/issues/485 2019-08-15 13:41:41 +10:00
Haocen Xu
71931b0f18 Clear discussion if new/clone paste clicked 2019-08-14 20:40:50 -04:00
Haocen Xu
1af7b536a5 Fix an edge case where we cannot find any shortUrl 2019-08-14 00:06:51 -04:00
Haocen Xu
a5cd8696e6 Ensure shortener button re-enable after creating new paste 2019-08-13 21:55:35 -04:00
Haocen Xu
cd5ede5670 Enhance URL shortener integration, clear address bar when create new paste from existing paste 2019-08-13 21:44:53 -04:00
Haocen Xu
cb877e4494 447, Rework UX to address obscured send button and hard to click
shortener button
2019-08-13 19:21:26 -04:00
El RIDO
c66bff9d1b fixing travis CI builds for php 5.5, which require trusty 2019-07-27 08:19:01 +02:00
El RIDO
d63a0d10d3 fixing npm package version number 2019-07-27 08:11:29 +02:00
El RIDO
847c9e7355 better looking check mark 2019-07-27 07:47:03 +02:00
El RIDO
d33c89666d Merge branch 'security-md' 2019-07-27 07:43:41 +02:00
El RIDO
c8a9038f27 Merge branch 'master' into security-md 2019-07-27 07:43:16 +02:00
El RIDO
b65303dd71 update wording as suggested and version to latest release 2019-07-27 07:42:54 +02:00
El RIDO
8d323c1da4 document the applicability of RFC 1855 / Netiquette 2019-07-27 07:31:34 +02:00
Andreas Schneider
5c5de860e2 INSTALL: Creata a mediumblob for data in a paste
This allows to upload bigger pastes and pastes with attachments in the
v2 paste format.

Fixes #456
2019-07-12 10:07:22 +02:00
Andreas Schneider
da576baab9 Allow to upload bigger files
Signed-off-by: Andreas Schneider <asn@cryptomilk.org>
2019-07-12 09:03:14 +02:00
El RIDO
78225165ca Merge branch 'BigWax-patch-1' 2019-07-11 16:50:51 +02:00
El RIDO
b0d1a3949e add bulgarian to the supported languages 2019-07-11 16:50:32 +02:00
BigWax
1469d0c062 Create bg.json
Bulgarian translation
2019-07-10 16:06:55 +01:00
R4SAS
a1704b2dd9 [i18n] update russian translation 2019-07-10 02:43:00 +03:00
El RIDO
a270cd818a create security.md for new Github security feature 2019-05-23 17:06:33 +02:00
94 changed files with 5951 additions and 1083 deletions

View File

@@ -1,3 +1,4 @@
---
parserOptions:
ecmaVersion: 2017
@@ -11,17 +12,16 @@ env:
es6: true
jquery: true
node: true
mocha: true
globals:
DOMPurify: false
after: true
before: true
cleanup: true
describe: false
it: false
jsc: false
jsdom: true
kjua: true
DOMPurify: readonly
cleanup: writable
describe: readonly
jsc: readonly
jsdom: writable
kjua: writable
WebCrypto: writable
# http://eslint.org/docs/rules/
rules:

3
.gitattributes vendored
View File

@@ -1,5 +1,6 @@
doc/ export-ignore
tst/ export-ignore
img/browserstack.svg export-ignore
js/.istanbul.yml export-ignore
js/.nycrc.yml export-ignore
js/common.js export-ignore
@@ -18,4 +19,6 @@ js/test/ export-ignore
.styleci.yml export-ignore
.travis.yml export-ignore
composer.json export-ignore
composer.lock export-ignore
BADGES.md export-ignore
CODE_OF_CONDUCT.md export-ignore

23
.github/workflows/php.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: PHP Composer
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Validate composer.json and composer.lock
run: composer validate
- name: Install dependencies
run: composer install --prefer-dist --no-progress --no-suggest
# Add a test script to composer.json, for instance: "test": "vendor/bin/phpunit"
# Docs: https://getcomposer.org/doc/articles/scripts.md
# - name: Run test suite
# run: composer run-script test

4
.gitignore vendored
View File

@@ -12,10 +12,6 @@ data/
doc/*
!doc/*.md
# Ignore developers composer status so it isn't accidentally checked in,
# see https://github.com/PrivateBin/PrivateBin/issues/84
composer.lock
# Ignore vendor dir of Composer except PHP files
vendor/*.*
vendor/*/*.*

View File

@@ -2,3 +2,11 @@ RewriteEngine on
RewriteCond !%{HTTP_USER_AGENT} "Let's Encrypt validation server" [NC]
RewriteCond %{HTTP_USER_AGENT} ^.*(bot|spider|crawl|https?://|WhatsApp|SkypeUriPreview|facebookexternalhit) [NC]
RewriteRule .* - [R=403,L]
<IfModule mod_php7.c>
php_value max_execution_time 30
php_value post_max_size 10M
php_value upload_max_size 10M
php_value upload_max_filesize 10M
php_value max_file_uploads 100
</IfModule>

View File

@@ -17,8 +17,9 @@ disabled:
- concat_without_spaces
- declare_equal_normalize
- heredoc_to_nowdoc
- method_argument_space
- method_argument_space_strict
- new_with_braces
- no_alternative_syntax
- phpdoc_align
- phpdoc_no_access
- phpdoc_separation

View File

@@ -1,12 +1,11 @@
language: php
sudo: false
php:
- '5.5'
- '5.6'
- '7.0'
- '7.1'
- '7.2'
- '7.3'
- '7.4'
# as this is a php project, node.js (for JS unit testing) isn't installed
install:
@@ -14,6 +13,7 @@ install:
- source ~/.nvm/nvm.sh && nvm install --lts
before_script:
- rm composer.lock
- composer install -n
- npm install -g mocha
- cd js && npm install

View File

@@ -7,3 +7,5 @@
[![SensioLabsInsight](https://insight.sensiolabs.com/projects/57c9e74e-c6f9-4de6-a876-df66ec2ea1ff/mini.png)](https://insight.sensiolabs.com/projects/57c9e74e-c6f9-4de6-a876-df66ec2ea1ff)
[![Codacy Badge](https://api.codacy.com/project/badge/Coverage/094500f62abf4c9aa0c8a8a4520e4789)](https://www.codacy.com/app/PrivateBin/PrivateBin)
[![Test Coverage](https://codeclimate.com/github/PrivateBin/PrivateBin/badges/coverage.svg)](https://codeclimate.com/github/PrivateBin/PrivateBin/coverage) [![Code Coverage](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/badges/coverage.png?b=master)](https://scrutinizer-ci.com/g/PrivateBin/PrivateBin/?branch=master)
[![BrowserStack - cross browser testing](img/browserstack.svg)](https://www.browserstack.com/)

View File

@@ -1,6 +1,48 @@
# PrivateBin version history
* **1.3 (not yet released)**
* **1.4 (not yet released)**
* **1.3.4 (2020-03-22)**
* CHANGED: Minimum required PHP version is 5.6, due to a change in the identicon library and to use php's native hash_equals()
* CHANGED: Upgrading libraries to: identicon 2.0.0
* FIXED: Support custom expiration options in email function (#586)
* FIXED: Regression with encoding of HTML entities (#588)
* FIXED: Unable to paste password on paste with attachment (#565 & #595)
* **1.3.3 (2020-02-16)**
* CHANGED: Upgrading libraries to: DOMpurify 2.0.8
* CHANGED: Several translations got updated with missing messages
* CHANGED: Introduce HTML entity encoding on server side (#581)
* FIXED: HTML entity double encoding issues introduced in 1.3.2 (#560)
* **1.2.3 (2020-02-16)**
* CHANGED: Upgrading libraries to: DOMpurify 2.0.8
* CHANGED: Introduce HTML entity encoding on server side (#581)
* FIXED: HTML entity double encoding issues introduced in 1.3.2 (#560)
* **1.3.2 (2020-01-11)**
* ADDED: Translation for Ukrainian (#533)
* ADDED: Option to send a mail with the link, when creating a paste (#398)
* ADDED: Add support for CONFIG_PATH environment variable (#552)
* CHANGED: Upgrading libraries to: base-x 3.0.7, DOMpurify 2.0.7 & Showdown 1.9.1
* FIXED: HTML injection via unescaped attachment filename (#554)
* FIXED: Password disabling option (#527)
* **1.2.2 (2020-01-11)**
* CHANGED: Upgrading libraries to: bootstrap 3.4.1, DOMpurify 2.0.7, jQuery 3.4.1, kjua 0.6.0, Showdown 1.9.1 & SJCL 1.0.8
* FIXED: HTML injection via unescaped attachment filename (#554)
* **1.3.1 (2019-09-22)**
* ADDED: Translation for Bulgarian (#455)
* CHANGED: Improved mobile UI - obscured send button and hard to click shortener button (#477)
* CHANGED: Enhanced URL shortener integration (#479)
* CHANGED: Improved file upload drag & drop UI (#317)
* CHANGED: Increased default size limit from 2 to 10 MiB, switch data from BLOB to MEDIUMBLOB in MySQL (#458)
* CHANGED: Upgrading libraries to: DOMpurify 2.0.1
* FIXED: Enabling browsers without WASM to create pastes and read uncompressed ones (#454)
* FIXED: Cloning related issues (#489, #491, #493, #494)
* FIXED: Enable file operation only when editing (#497)
* FIXED: Clicking 'New' on a previously submitted paste does not blank address bar (#354)
* FIXED: Clear address bar when create new paste from existing paste (#479)
* FIXED: Discussion section not hiding when new/clone paste is clicked on (#484)
* FIXED: Showdown.js error when posting svg qrcode (#485)
* FIXED: Failed to handle the case where user cancelled attachment selection properly (#487)
* FIXED: Displaying the appropriate errors in older browsers (#508)
* **1.3 (2019-07-09)**
* ADDED: Translation for Czech (#424)
* ADDED: Threat modeled the application (#177)
* ADDED: Made compression configurable (#38)

9
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,9 @@
# Netiquette
As suggested by the current project hoster, we are hereby referring to
[RFC 1855](https://tools.ietf.org/html/rfc1855) as a minimum set of guidelines
of Network Etiquette for individuals interacting on this project.
The maintainers of this project reserve the right to remove unlawful or
disrupting content and block users that repeatedly disturb the project at their
discretion.

View File

@@ -25,6 +25,8 @@ Sébastien Sauvage - original idea and main developer
* PunKeel - first docker container
* thororm - Display of video, audio & PDF, drag & drop, preview of attachments
* Harald Leithner - base58 encoding of key
* Haocen - lots of bugfixes and UI improvements
* Lucas Savva - configurable config file location, NixOS packaging
## Translations
* Hexalyse - French
@@ -42,3 +44,5 @@ Sébastien Sauvage - original idea and main developer
* Michael van Schaik - Dutch
* Péter Tabajdi - Hungarian
* info-path - Czech
* BigWax - Bulgarian
* AndriiZ - Ukrainian

View File

@@ -50,6 +50,27 @@ process (see also
> PrivateBin will look for your includes / data here:
> /home/example.com/secret/privatebin
### Changing the config path only
In situations where you want to keep the PrivateBin static files separate from the
rest of your data, or you want to reuse the installation files on multiple vhosts,
you may only want to change the `conf.php`. In this instance, you can set the
`CONFIG_PATH` environment variable to the absolute path to the `conf.php` file.
This can be done in your web server's virtual host config, the PHP config, or in
the index.php if you choose to customize it.
Note that your PHP process will need read access to the config wherever it may be.
> #### CONFIG_PATH example
> Setting the value in an Apache Vhost:
> SetEnv CONFIG_PATH /var/lib/privatebin/conf.php
>
> In a php-fpm pool config:
> env[CONFIG_PATH] = /var/lib/privatebin/conf.php
>
> In the index.php, near the top:
> putenv('CONFIG_PATH=/var/lib/privatebin/conf.php');
### Transport security
When setting up PrivateBin, also set up HTTPS, if you haven't already. Without HTTPS
@@ -66,8 +87,9 @@ See [this FAQ item](https://github.com/PrivateBin/PrivateBin/wiki/FAQ#what-are-t
In the file `cfg/conf.php` you can configure PrivateBin. A `cfg/conf.sample.php`
is provided containing all options and default values. You can copy it to
`cfg/conf.php` and adapt it as needed. The config file is divided into multiple
sections, which are enclosed in square brackets.
`cfg/conf.php` and adapt it as needed. Alternatively you can copy it anywhere and
set the `CONFIG_PATH` environment variable (see above notes). The config file is
divided into multiple sections, which are enclosed in square brackets.
In the `[main]` section you can enable or disable the discussion feature, set
the limit of stored pastes and comments in bytes. The `[traffic]` section lets
@@ -139,7 +161,7 @@ For reference or if you want to create the table schema for yourself to avoid ha
```sql
CREATE TABLE prefix_paste (
dataid CHAR(16) NOT NULL,
data BLOB,
data MEDIUMBLOB,
postdate INT,
expiredate INT,
opendiscussion INT,
@@ -165,7 +187,7 @@ CREATE INDEX parent ON prefix_comment(pasteid);
CREATE TABLE prefix_config (
id CHAR(16) NOT NULL, value TEXT, PRIMARY KEY (id)
);
INSERT INTO prefix_config VALUES('VERSION', '1.3');
INSERT INTO prefix_config VALUES('VERSION', '1.3.4');
```
In **PostgreSQL**, the data, attachment, nickname and vizhash columns needs to be TEXT and not BLOB or MEDIUMBLOB.

View File

@@ -1,6 +1,6 @@
# [![PrivateBin](https://cdn.rawgit.com/PrivateBin/assets/master/images/preview/logoSmall.png)](https://privatebin.info/)
*Current version: 1.3*
*Current version: 1.3.4*
**PrivateBin** is a minimalist, open source online [pastebin](https://en.wikipedia.org/wiki/Pastebin)
where the server has zero knowledge of pasted data.
@@ -95,9 +95,9 @@ file](https://github.com/PrivateBin/PrivateBin/wiki/Configuration):
## Further resources
* [Installation guide](https://github.com/PrivateBin/PrivateBin/blob/master/INSTALL.md#installation)
* [FAQ](https://github.com/PrivateBin/PrivateBin/wiki/FAQ)
* [Upgrading from ZeroBin 0.19 Alpha](https://github.com/PrivateBin/PrivateBin/wiki/Upgrading-from-ZeroBin-0.19-Alpha)
* [Installation guide](https://github.com/PrivateBin/PrivateBin/blob/master/INSTALL.md#installation)
* [Configuration guide](https://github.com/PrivateBin/PrivateBin/wiki/Configuration)

18
SECURITY.md Normal file
View File

@@ -0,0 +1,18 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 1.3.4 | :heavy_check_mark: |
| < 1.3.4 | :x: |
## Reporting a Vulnerability
You can send us email at security@privatebin.org. You should be able to get
a response within a week (usually during the next weekend). The respondee will
reply from their personal address and can offer you their GPG public key to
support end-to-end encrypted communication on sensitive topics or attachments.
You can also contact us via the regular issue tracker if the risk of early
publication is low or you would request input from other PrivateBin users.

View File

@@ -29,8 +29,8 @@ defaultformatter = "plaintext"
; (optional) set a syntax highlighting theme, as found in css/prettify/
; syntaxhighlightingtheme = "sons-of-obsidian"
; size limit per paste or comment in bytes, defaults to 2 Mebibytes
sizelimit = 2097152
; size limit per paste or comment in bytes, defaults to 10 Mebibytes
sizelimit = 10485760
; template to include, default is "bootstrap" (tpl/bootstrap.php)
template = "bootstrap"
@@ -60,17 +60,26 @@ languageselection = false
; a different user when the same username was used in a comment. It might be
; used to get the IP of a non anonymous comment poster if the server salt is
; leaked and a SHA256 HMAC rainbow table is generated for all (relevant) IPs.
; Can be set to one these values: none / vizhash / identicon (default).
; icon = none
; Can be set to one these values: "none" / "vizhash" / "identicon" (default).
; icon = "none"
; Content Security Policy headers allow a website to restrict what sources are
; allowed to be accessed in its context. You need to change this if you added
; custom scripts from third-party domains to your templates, e.g. tracking
; scripts or run your site behind certain DDoS-protection services.
; Check the documentation at https://content-security-policy.com/
; Note: If you use a bootstrap theme, you can remove the allow-popups from the sandbox restrictions.
; By default this disallows to load images from third-party servers, e.g. when they are embedded in pastes. If you wish to allow that, you can adjust the policy here. See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-it-load-embedded-images for details.
; cspheader = "default-src 'none'; manifest-src 'self'; connect-src *; script-src 'self' 'unsafe-eval'; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals"
; Notes:
; - If you use a bootstrap theme, you can remove the allow-popups from the
; sandbox restrictions.
; - By default this disallows to load images from third-party servers, e.g. when
; they are embedded in pastes. If you wish to allow that, you can adjust the
; policy here. See https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-it-load-embedded-images
; for details.
; - The 'unsafe-eval' is used in two cases; to check if the browser supports
; async functions and display an error if not and for Chrome to enable
; webassembly support (used for zlib compression). You can remove it if Chrome
; doesn't need to be supported and old browsers don't need to be warned.
; cspheader = "default-src 'none'; manifest-src 'self'; connect-src * blob:; script-src 'self' 'unsafe-eval'; style-src 'self'; font-src 'self'; img-src 'self' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals"
; stay compatible with PrivateBin Alpha 0.19, less secure
; if enabled will use base64.js version 1.7 instead of 2.1.9 and sha1 instead of
@@ -86,8 +95,8 @@ languageselection = false
; Pick compression algorithm or disable it. Only applies to pastes/comments
; created after changing the setting.
; Can be set to one these values: none / zlib (default).
; compression = zlib
; Can be set to one these values: "none" / "zlib" (default).
; compression = "zlib"
[expire]
; expire value that is selected per default

View File

@@ -24,9 +24,9 @@
"docs" : "https://privatebin.info/codedoc/"
},
"require" : {
"php" : "^5.5.0 || ^7.0",
"php" : "^5.6.0 || ^7.0",
"paragonie/random_compat" : "2.0.18",
"yzalis/identicon" : "1.2.0"
"yzalis/identicon" : "2.0.0"
},
"require-dev" : {
"codacy/coverage" : "dev-master",

2699
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
body {
@@ -80,10 +80,29 @@ body.loading {
margin-bottom: 20px;
}
#dropzone {
text-align: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
opacity: 0.6;
background-color: #99ccff;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center;
background-size: 25vh;
outline: 2px dashed #228bff;
outline-offset: -50px;
}
.dragAndDropFile{
color:#777;
font-size:1em;
display:inline;
color: #777;
font-size: 1em;
display: inline;
white-space: normal;
}
#deletelink {
@@ -112,8 +131,9 @@ body.loading {
margin-bottom: 10px;
}
#message {
#message, .replymessage {
font-family: monospace;
resize: vertical;
}
#nickname {
@@ -124,6 +144,10 @@ body.loading {
margin-bottom: 10px;
}
#filewrap {
transition: background-color 0.75s ease-out;
}
.comment {
border-left: 1px solid #ccc;
padding: 5px 0 5px 10px;
@@ -131,7 +155,7 @@ body.loading {
transition: background-color 0.75s ease-out;
}
.comment.highlight {
.highlight {
background-color: #ffdd86;
transition: background-color 0.2s ease-in;
}
@@ -147,3 +171,37 @@ li.L0, li.L1, li.L2, li.L3, li.L5, li.L6, li.L7, li.L8 {
.dark-theme .alert-info .alert-link {
color: #fff;
}
/* address 2K or 4K monitors when using bootstrap 3 */
@media (min-width: 1280px) {
.container {
width: 100%;
padding-left: 4ch;
padding-right: 4ch;
}
}
.modal-dialog {
margin: auto !important;
}
/* makeup for the original margin on modal-dialog */
@media (min-width: 768px) {
.modal-content {
margin: 30px 0;
}
}
.modal-content {
margin: 10px;
}
.modal-body {
display: flex;
justify-content: center;
align-items: center;
}
.modal .modal-content button {
margin: 0.5em 0;
}

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
/* When there is no script at all other */

View File

@@ -6,7 +6,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
/* CSS Reset from YUI 3.4.1 (build 4118) - Copyright 2011 Yahoo! Inc. All rights reserved.
@@ -102,6 +102,7 @@ h3.title {
padding: 5px;
white-space: pre-wrap;
font-family: Consolas, "Lucida Console", "DejaVu Sans Mono", Monaco, monospace;
resize: vertical;
}
#attachmentPreview img {
@@ -115,10 +116,29 @@ h3.title {
margin-bottom: 20px;
}
#dropzone {
text-align: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
opacity: 0.6;
background-color: #99ccff;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24'%3E%3Cpath d='M0 0h24v24H0z' fill='none'/%3E%3Cpath d='M19.35 10.04C18.67 6.59 15.64 4 12 4 9.11 4 6.6 5.64 5.35 8.04 2.34 8.36 0 10.91 0 14c0 3.31 2.69 6 6 6h13c2.76 0 5-2.24 5-5 0-2.64-2.05-4.78-4.65-4.96zM14 13v4h-4v-4H7l5-5 5 5h-3z'/%3E%3C/svg%3E");
background-repeat: no-repeat;
background-position: center;
background-size: 25vh;
outline: 2px dashed #228bff;
outline-offset: -50px;
}
.dragAndDropFile{
color:#777;
font-size:1em;
display:inline;
color: #777;
font-size: 1em;
display: inline;
white-space: normal;
}
#status {
@@ -405,6 +425,15 @@ h4.title {
.commentdate { color: #bfcede; }
#filewrap {
transition: background-color 0.75s ease-out;
}
.highlight {
background-color: #ffdd86;
transition: background-color 0.2s ease-in;
}
img.vizhash {
width: 16px;
height: 16px;

View File

@@ -55,6 +55,6 @@ $ ln -s /usr/bin/nodejs /usr/local/bin/node
To generate the documentation, change into the main directory and run phpdoc:
```console
$ cd PrivateBin
$ jsdoc -p -d doc/jsdoc js/privatebin.js
$ jsdoc -p -d doc/jsdoc js/privatebin.js js/legacy.js
```

188
i18n/bg.json Normal file
View File

@@ -0,0 +1,188 @@
{
"PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
"%s е изчистен и изцяло достъпен като отворен код, онлайн \"paste\" услуга, където сървъра не знае подадената информация. Тя се шифрова/дешифрова <i>във браузъра</i> използвайки 256 битов AES алгоритъм. Повече информация може да намерите на <a href=\"https://privatebin.info/\">страницата на проекта (Английски)</a>",
"Because ignorance is bliss":
"Невежеството е блаженство",
"en": "bg",
"Paste does not exist, has expired or has been deleted.":
"Информацията не съществува, срокът и е изтекъл или е била изтрита.",
"%s requires php %s or above to work. Sorry.":
"%s има нужда от PHP %s или по-нова, за да работи. Съжалявам.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s задължава отдела от настройките [%s] да съществува във файла със настройките.",
"Please wait %d seconds between each post.":
"Моля изчакайте %d секунди между всяка публикация.",
"Paste is limited to %s of encrypted data.":
"Съдържанието е ограничено до %s криптирана информация.",
"Invalid data.":
"Невалидна информация.",
"You are unlucky. Try again.":
"Нямаш късмет. Пробвай отново.",
"Error saving comment. Sorry.":
"Грешка в запазването на коментара. Съжалявам.",
"Error saving paste. Sorry.":
"Грешка в записването на информацията. Съжалявам.",
"Invalid paste ID.":
"Невалиден идентификационен код.",
"Paste is not of burn-after-reading type.":
"Информацията не е от тип \"унищожаване след преглед\".",
"Wrong deletion token. Paste was not deleted.":
"Невалиден код за изтриване. Информацията Ви не беше изтрита.",
"Paste was properly deleted.":
"Информацията Ви е изтрита.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"Услугата %s се нуждае от JavaScript, за да работи. Съжаляваме за неудобството.",
"%s requires a modern browser to work.":
"%s се нуждае от съвременен браузър за да работи.",
"New":
"Създаване",
"Send":
"Изпрати",
"Clone":
"Дублирай",
"Raw text":
"Чист текст",
"Expires":
"Изтича",
"Burn after reading":
"Унищожи след преглед",
"Open discussion":
"Отворена дискусия",
"Password (recommended)":
"Парола (препоръчва се)",
"Discussion":
"Коментари",
"Toggle navigation":
"Включи или Изключи навигацията",
"%d seconds": ["%d секунди", "%d секунда"],
"%d minutes": ["%d минути", "%d минута"],
"%d hours": ["%d часа", "%d час"],
"%d days": ["%d дни", "%d ден"],
"%d weeks": ["%d седмици", "%d седмица"],
"%d months": ["%d месеци", "%d месец"],
"%d years": ["%d години", "%d година"],
"Never":
"Никога",
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
"Забележка: Това е пробна услуга: Информацията може да бъде изтрита по всяко време. Котета ще измрат ако злоупотребиш с услугата.",
"This document will expire in %d seconds.":
["Този документ изтича след една секунда.", "Този документ изтича след %d секунди."],
"This document will expire in %d minutes.":
["Този документ изтича след една минута.", "Този документ изтича след %d минути."],
"This document will expire in %d hours.":
["Този документ изтича след един час.", "Този документ изтича след %d часа."],
"This document will expire in %d days.":
["Този документ изтича след един ден.", "Този документ изтича след %d дни."],
"This document will expire in %d months.":
["Този документ изтича след една година.", "Този документ изтича след %d години."],
"Please enter the password for this paste:":
"Моля въведете паролата за това съдържание:",
"Could not decrypt data (Wrong key?)":
"Информацията не можеше да се дешифрова (Грешен ключ?)",
"Could not delete the paste, it was not stored in burn after reading mode.":
"Изтриването на информацията беше неуспешно. Тя не е от тип \"унищожаване след преглед\".",
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
"САМО ЗА ВАШИТЕ ОЧИ. Не затваряйте прозореца, понеже тази информация няма да може да бъде показана отново.",
"Could not decrypt comment; Wrong key?":
"Дешифроването на коментара беше неуспешно. Грешен ключ?",
"Reply":
"Отговор",
"Anonymous":
"Безименен",
"Avatar generated from IP address":
"Аватар (на базата на IP адреса Ви)",
"Add comment":
"Добави коментар",
"Optional nickname…":
"Избирателен псевдоним",
"Post comment":
"Публикувай коментара",
"Sending comment…":
"Изпращане на коментара Ви…",
"Comment posted.":
"Коментара Ви е публикуван.",
"Could not refresh display: %s":
"Презареждането на екрана беше неуспешно: %s",
"unknown status":
"Неизвестно състояние",
"server error or not responding":
"Грешка в сървъра или не отговаря",
"Could not post comment: %s":
"Публикуването на коментара Ви беше неуспешно: %s",
"Sending paste…":
"Изпращане на информацията Ви…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
"Вашата връзка е <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Натиснете [Ctrl]+[c] за да копирате)</span>",
"Delete data":
"Изтриване на информацията",
"Could not create paste: %s":
"Създаването на връзката ви беше неуспешно: %s",
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
"Дешифроването на информацията беше неуспешно: Ключа за декриптиране липсва във връзката (Да не сте използвали услуга за пренасочване или скъсяване на връзката, което би изрязало части от нея?)",
"Format": "Format",
"Plain Text": "Чист текст",
"Source Code": "Изходен код",
"Markdown": "Markdown",
"Download attachment": "Свали прикачения файл",
"Cloned: '%s'": "Дублирано: '%s'",
"The cloned file '%s' was attached to this paste.": "Дублирания файл '%s' беше прикачен.",
"Attach a file": "Прикачи файл",
"alternatively drag & drop a file or paste an image from the clipboard": "Също можеш да пуснеш файла върху този прозорец или да поставиш изображение от клипборда",
"File too large, to display a preview. Please download the attachment.": "Файла е твърде голям, за да се представи визуализация. Моля, свалете файла.",
"Remove attachment": "Премахнете файла",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
"Браузърът ви не поддържа прикачване на шифровани файлове. Моля, използвайте по-нов браузър",
"Invalid attachment.": "Невалидно прикачване.",
"Options": "Настройки",
"Shorten URL": "Скъси връзката",
"Editor": "Редактор",
"Preview": "Визуализация",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
"PATH трябва да е във края на \"%s\" за да може %s да работи правилно. Моля обновете PATH във вашият index.php .",
"Decrypt":
"Дешифровай",
"Enter password":
"Въведи паролата",
"Loading…": "Зареждане…",
"Decrypting paste…": "Дешифроване на информацията…",
"Preparing new paste…": "Приготвяне на връзката Ви…",
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
"Във случай, че това съобщение не изчезне след време, моля прегледайте <a href=\"%s\">този FAQ (Английски)</a>, за информация, която би ви помогнала.",
"+++ no paste text +++": "+++ няма текстово съдържание +++",
"Could not get paste data: %s":
"Взимането на информацията беше неуспешно: %s",
"QR code": "QR код",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"Този сайт използва несигурна HTTP връзка. Моля използвайте само за проби.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"<a href=\"%s\">Вижте тази страница</a> за повече информация.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Браузъра ви може да се нуждае от HTTPS връзка за да използва WebCrypto API. Пробвай <a href=\"%s\">да минеш на HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"Wrong deletion token. Paste was not deleted.",
"Paste was properly deleted.":
"Paste was properly deleted.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript is required for %s to work. Sorry for the inconvenience.",
"%s requires a modern browser to work.":
"%%s requires a modern browser to work.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:",
"New":
"Nový",
"Send":
@@ -155,11 +153,36 @@
"Could not get paste data: %s":
"Could not get paste data: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"Falscher Lösch-Code. Text wurde nicht gelöscht.",
"Paste was properly deleted.":
"Text wurde erfolgreich gelöscht.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript ist eine Voraussetzung, um %s zu nutzen.<br />Bitte entschuldige die Unannehmlichkeiten.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript ist eine Voraussetzung, um %s zu nutzen. Bitte entschuldige die Unannehmlichkeiten.",
"%s requires a modern browser to work.":
"%s setzt einen modernen Browser voraus, um funktionieren zu können.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Du benutzt immer noch den Internet Explorer? Tu Dir einen Gefallen und wechsle zu einem moderneren Browser:",
"New":
"Neu",
"Send":
@@ -155,11 +153,36 @@
"Could not get paste data: %s":
"Text konnte nicht geladen werden: %s",
"QR code": "QR code",
"I love you too, bot…": "Ich mag Dich auch, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"Diese Webseite verwendet eine unsichere HTTP Verbindung! Bitte benutze sie nur zum Testen.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"<a href=\"%s\">Besuche diesen FAQ Eintrag</a> für weitere Informationen dazu.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Dein Browser benötigt möglicherweise eine HTTPS Verbindung um das WebCrypto API nutzen zu können. Versuche <a href=\"%s\">auf HTTPS zu wechseln</a>."
"Dein Browser benötigt möglicherweise eine HTTPS Verbindung um das WebCrypto API nutzen zu können. Versuche <a href=\"%s\">auf HTTPS zu wechseln</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Dein Browser unterstützt WebAssembly nicht, welches für zlib Komprimierung benötigt wird. Du kannst unkomprimierte Dokumente erzeugen, aber keine komprimierten lesen.",
"waiting on user to provide a password":
"warte auf Passworteingabe durch Benutzer",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Konnte Daten nicht entschlüsseln. Hast Du das falsche Passwort eingegeben? Wiederhole den Vorgang mit dem oben stehenden Knopf.",
"Retry":
"Wiederholen",
"Showing raw text…":
"Zeige reinen Text an…",
"Notice:":
"Hinweis:",
"This link will expire after %s.":
"Dieser Link wird um %s ablaufen.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"Dieser Link kann nur einmal geöffnet werden, verwende nicht den Zurück- oder Neu-laden-Knopf Deines Browsers.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Der Empfänger könnte Deine Zeitzone erfahren, möchtest Du die Zeit in UTC umwandeln?",
"Use Current Timezone":
"Aktuelle Zeitzone verwenden",
"Convert To UTC":
"In UTC Umwandeln",
"Close":
"Schliessen"
}

View File

@@ -31,12 +31,10 @@
"Token de eliminación erróneo. El \"paste\" no fue eliminado.",
"Paste was properly deleted.":
"El \"paste\" se ha eliminado correctamente.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript es necesario para que %s funcione.<br />Sentimos los inconvenientes ocasionados.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript es necesario para que %s funcione. Sentimos los inconvenientes ocasionados.",
"%s requires a modern browser to work.":
"%s requiere un navegador moderno para funcionar.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"¿Sigues usando Internet Explorer? Hazte un favor, cambia a un navegador moderno:",
"New":
"Nuevo",
"Send":
@@ -155,11 +153,36 @@
"Could not get paste data: %s":
"No se pudieron obtener los datos: %s",
"QR code": "Código QR",
"I love you too, bot…": "I love you too, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"Jeton de suppression incorrect. Le paste n'a pas été supprimé.",
"Paste was properly deleted.":
"Le paste a été correctement supprimé.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript est requis pour faire fonctionner %s. <br />Désolé pour cet inconvénient.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript est requis pour faire fonctionner %s. Désolé pour cet inconvénient.",
"%s requires a modern browser to work.":
"%s nécessite un navigateur moderne pour fonctionner.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Encore sur Internet Explorer ? Faites-vous une faveur, passez à un navigateur moderne :",
"New":
"Nouveau",
"Send":
@@ -139,12 +137,12 @@
"Cloned: '%s'": "Cloner '%s'",
"The cloned file '%s' was attached to this paste.": "Le fichier cloné '%s' a été attaché à ce paste.",
"Attach a file": "Attacher un fichier ",
"alternatively drag & drop a file or paste an image from the clipboard": "alternativement, glisser & déposer un fichier ou coller une image à partir du presse-papiers",
"alternatively drag & drop a file or paste an image from the clipboard": "au choix, glisser & déposer un fichier ou coller une image à partir du presse-papiers",
"File too large, to display a preview. Please download the attachment.": "Fichier trop volumineux, pour afficher un aperçu. Veuillez télécharger la pièce jointe.",
"Remove attachment": "Enlever l'attachement",
"Remove attachment": "Enlever la pièce jointe",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
"Votre navigateur ne supporte pas l'envoi de fichiers chiffrés. Merci d'utiliser un navigateur plus récent.",
"Invalid attachment.": "Attachement invalide.",
"Invalid attachment.": "Pièce jointe invalide.",
"Options": "Options",
"Shorten URL": "Raccourcir URL",
"Editor": "Éditer",
@@ -160,15 +158,40 @@
"Preparing new paste…": "Préparation du paste…",
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
"Si ce message ne disparaîssait pas, jetez un oeil à <a href=\"%s\">cette FAQ pour des idées de résolution</a> (en Anglais).",
"+++ no paste text +++": "+++ pas de paste-text +++",
"+++ no paste text +++": "+++ pas de texte copié +++",
"Could not get paste data: %s":
"Impossible d'obtenir les données du paste: %s",
"QR code": "QR code",
"I love you too, bot…": "Je taime aussi, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"Ce site web utilise une connexion HTTP non sécurisée ! Veuillez lutiliser uniquement pour des tests.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"Pour plus d'informations <a href=\"%s\">consultez cette rubrique de la FAQ</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Votre navigateur peut nécessiter une connexion HTTPS pour prendre en charge lAPI WebCrypto. Essayez <a href=\"%s\">de passer en HTTPS</a>."
"Votre navigateur peut nécessiter une connexion HTTPS pour prendre en charge lAPI WebCrypto. Essayez <a href=\"%s\">de passer en HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Votre navigateur ne prend pas en charge WebAssembly, utilisé pour la compression zlib. Vous pouvez créer des documents non compressés, mais vous ne pouvez pas lire les documents compressés.",
"waiting on user to provide a password":
"en attendant que l'utilisateur fournisse un mot de passe",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Impossible de décrypter les données. Vous avez saisi un mot de passe incorrect ? Réessayez avec le bouton en haut.",
"Retry":
"Réessayer",
"Showing raw text…":
"Affichage du texte brut…",
"Notice:":
"Avertissement:",
"This link will expire after %s.":
"Ce lien expire après le %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"Vous ne pouvez accéder à ce lien qu'une seule fois, n'utilisez pas le bouton précédent ou rafraîchir de votre navigateur.",
"Link:":
"Lien:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Le destinataire peut connaître votre fuseau horaire, convertir l'heure au format UTC?",
"Use Current Timezone":
"Conserver l'actuel",
"Convert To UTC":
"Convertir en UTC",
"Close":
"Fermer"
}

View File

@@ -31,12 +31,10 @@
"Hibás törlési azonosító. A bejegyzés nem lett törölve.",
"Paste was properly deleted.":
"A bejegyzés sikeresen törölve.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript szükséges a %s működéséhez. Elnézést a fennakadásért.",
"%s requires a modern browser to work.":
"A %s működéséhez a jelenleginél újabb böngészőre van szükség.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Még mindig Internet Explorert használsz? Ideje váltani:",
"New":
"Új",
"Send":
@@ -155,11 +153,36 @@
"Could not get paste data: %s":
"Could not get paste data: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"Codice cancellazione errato. Il messaggio NON è stato cancellato.",
"Paste was properly deleted.":
"Il messaggio è stato correttamente cancellato.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"%s funziona solo con JavaScript attivo.<br />Ci dispiace per l'inconveniente.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"%s funziona solo con JavaScript attivo. Ci dispiace per l'inconveniente.",
"%s requires a modern browser to work.":
"%s richiede un browser moderno e aggiornato per funzionare.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Usi ancora Internet Explorer? Ti consigliamo di passare ad un browser più sicuro:",
"New":
"Nuovo",
"Send":
@@ -155,11 +153,36 @@
"Could not get paste data: %s":
"Could not get paste data: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"Foutieve verwijdercode. Geplakte tekst is niet verwijderd.",
"Paste was properly deleted.":
"Geplakte tekst is correct verwijderd.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript vereist om %s te laten werken.<br />Sorry voor het ongemak.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript vereist om %s te laten werken. Sorry voor het ongemak.",
"%s requires a modern browser to work.":
"%s vereist een moderne browser om te kunnen werken ",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Gebruik je nog steeds Internet explorer? Doe jezelf een plezier en maak gebruik van een moderne browser:",
"New":
"Nieuw",
"Send":
@@ -155,11 +153,36 @@
"Could not get paste data: %s":
"Could not get paste data: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"Feil slettingsnøkkel. Innlegg ble ikke fjernet.",
"Paste was properly deleted.":
"Innlegget er slettet.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"Javascript kreves for at %s skal fungere<br />Beklager.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"Javascript kreves for at %s skal fungere. Beklager.",
"%s requires a modern browser to work.":
"%s krever en moderne nettleser for å fungere.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Fortsatt bruker av Internet Explorer? Gjør deg selv en tjeneste og bytt til en moderne nettleser:",
"New":
"Ny",
"Send":
@@ -154,12 +152,37 @@
"+++ no paste text +++": "+++ ingen innleggstekst +++",
"Could not get paste data: %s":
"Kunne ikke hente utklippsdata: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"QR code": "QR kode",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"Denne websiden bruker usikker HTTP tilkobling! Bruk den kun for testing.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"For mer informasjon <a href=\"%s\">se ofte stilte spørsmål</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Din nettleser har behov for HTTPS tilkobling for å støtte WebCrypto biblioteket. Prøv å <a href=\"%s\">bytt til HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"Geton de supression incorrècte. Lo tèxte es pas estat suprimit.",
"Paste was properly deleted.":
"Lo tèxte es estat corrèctament suprimit.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript es requesit per far foncionar %s. <br />O planhèm per linconvenient.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript es requesit per far foncionar %s. O planhèm per linconvenient.",
"%s requires a modern browser to work.":
"%s necessita un navigator modèrn per foncionar.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Encora sus Internet Explorer?Fasètz-vos una favor, passatz a un navigator modèrn:",
"New":
"Nòu",
"Send":
@@ -164,11 +162,36 @@
"Could not get paste data: %s":
"Recuperacion impossibla de las donadas copiadas: %s",
"QR code": "Còdi QR",
"I love you too, bot…": "Taimi tanben, robòt…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"Aqueste site utiliza una connexion HTTP pas segura ! Mercés de lutilizar pas que per densages.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"Per mai dinformacions <a href=\"%s\">vejatz aqueste article de FAQ</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Se pòt que vòstre navigator faga besonh duna connexion HTTPS per èsser compatible amb lAPI WebCrypto. Ensajatz de <a href=\"%s\">passar al HTTPS</a>."
"Se pòt que vòstre navigator faga besonh duna connexion HTTPS per èsser compatible amb lAPI WebCrypto. Ensajatz de <a href=\"%s\">passar al HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Vòstre navigator es pas compatible amb WebAssembly, utilizat per la compression zlib. Podètz crear de documents pas compressat, mas ne podètz pas legir de compressats.",
"waiting on user to provide a password":
"en espèra que lutilizaire fornisca un senhal",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Deschiframent de las donadas impossible. Avètz picat un marrit senhal? Tornatz ensajar amb lo boton ennaut.",
"Retry":
"Tornar ensajar",
"Showing raw text…":
"Afichatge del tèxte brut…",
"Notice:":
"Avertiment:",
"This link will expire after %s.":
"Aqueste ligam expirarà aprèp %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"Òm pòt pas quaccedir a aqueste ligam quun còp, utilizetz pas lo boton precedent o actualizar del navigator.",
"Link:":
"Ligam:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Lo destinatari pòt savisar de vòstre fus orari, convertir en UTC?",
"Use Current Timezone":
"Utilizar lactual",
"Convert To UTC":
"Convertir en UTC",
"Close":
"Tampar"
}

View File

@@ -31,12 +31,10 @@
"Nieprawidłowy token usuwania. Wklejka nie została usunięta.",
"Paste was properly deleted.":
"Wklejka usunięta poprawnie.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"Do działania %sa jest wymagany JavaScript. Przepraszamy za tę niedogodność.",
"%s requires a modern browser to work.":
"%s wymaga do działania nowoczesnej przeglądarki.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Cały czas używasz Internet Explorera? Zrób sobie przysługę, przesiądź się na nowoczesną przeglądarkę:",
"New":
"Nowa",
"Send":
@@ -155,11 +153,36 @@
"Could not get paste data: %s":
"Nie można było pobrać danych wklejki: %s",
"QR code": "Kod QR",
"I love you too, bot…": "I love you too, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"Token de remoção inválido. A cópia não foi excluída.",
"Paste was properly deleted.":
"A cópia foi devidamente excluída.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"JavaScript é necessário para que %s funcione.<br />Pedimos desculpas pela inconveniência.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"JavaScript é necessário para que %s funcione. Pedimos desculpas pela inconveniência.",
"%s requires a modern browser to work.":
"%s requer um navegador moderno para funcionar.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Ainda usando Internet Explorer? Faça-se um favor, mude para um navegador moderno:",
"New":
"Novo",
"Send":
@@ -153,13 +151,38 @@
"Caso essa mensagem nunca desapareça, por favor veja <a href=\"%s\">este FAQ para saber como resolver os problemas</a>.",
"+++ no paste text +++": "+++ sem texto de cópia +++",
"Could not get paste data: %s":
"Could not get paste data: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"Não foi possível obter dados de cópia: %s",
"QR code": "Código QR",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"Esse site usa uma conexão HTTP insegura! Use-o apenas para testes.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Para mais informações <a href=\"%s\">veja esse item do FAQ</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Seu navegador pode exigir uma conexão HTTPS para dar suporte à API WebCrypto. Tente <a href=\"%s\">mudar para HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Seu navagador não suporta WebAssembly, usado para compressão zlib. Você pode criar documentos não compactados, mas não pode lê-los.",
"waiting on user to provide a password":
"esperando que o usuário digite uma senha",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Não foi possível decifrar os dados. Você digitou a senha corretamente? Tente novamente com o botão ao topo.",
"Retry":
"Tentar Novamente",
"Showing raw text…":
"Mostrando texto bruto…",
"Notice:":
"Aviso:",
"This link will expire after %s.":
"Esse link vai expirar após %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"Esse link só pode ser acessado uma vez, não utilize o botão de voltar ou atualizar do seu navegador.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"O recipiente pode ter ciência de seu fuso horário, converter hora para UTC?",
"Use Current Timezone":
"Usar Fuso Horário Atual",
"Convert To UTC":
"Converter para UTC",
"Close":
"Fechar"
}

View File

@@ -31,12 +31,10 @@
"Неверный ключ удаления записи. Запись не удалена.",
"Paste was properly deleted.":
"Запись была успешно удалена.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"Для работы %s требуется включенный JavaScript.<br />Приносим извинения за неудобства.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"Для работы %s требуется включенный JavaScript. Приносим извинения за неудобства.",
"%s requires a modern browser to work.":
"Для работы %s требуется более современный браузер.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"До сих пор используете Internet Explorer? Пожалейте себя, перейдите на более современный браузер:",
"New":
"Новая запись",
"Send":
@@ -164,12 +162,37 @@
"+++ no paste text +++": "+++ в записи нет текста +++",
"Could not get paste data: %s":
"Не удалось получить данные записи: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"QR code": "QR код",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"Данный сайт использует незащищенное HTTP подключение! Пожалуйста используйте его только для тестирования.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Для продробностей <a href=\"%s\">прочтите информацию в FAQ</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Ваш браузер требует использования HTTPS подключения для поддержки WebCrypto API. Попробуйте <a href=\"%s\">переключиться на HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -1,7 +1,7 @@
{
"PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
"%s je minimalističen, odprtokodni spletni 'pastebin', kjer server ne ve ničesar o prilepljenih podatkih. Podatki so zakodirani/odkodirani <i>v brskalniku</i> z uporabo 256 bitnega AES. Več informacij na < href=\"https://privatebin.info/\">spletni strani projekta.</a>.",
"%s je minimalističen, odprtokodni spletni 'pastebin', kjer server ne ve ničesar o prilepljenih podatkih. Podatki so zakodirani/odkodirani <i>v brskalniku</i> z uporabo 256 bitnega AES. Več informacij na <a href=\"https://privatebin.info/\">spletni strani projekta.</a>.",
"Because ignorance is bliss":
"Ker kar ne veš ne boli.",
"en": "sl",
@@ -31,12 +31,10 @@
"Napačen token za izbris. Prilepek ni bil izbrisan..",
"Paste was properly deleted.":
"Prilepek je uspešno izbrisan.",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"Da %s deluje, moraš vklopiti JavaScript.<br />Oprosti za povročene nevšečnosti.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"Da %s deluje, moraš vklopiti JavaScript. Oprosti za povročene nevšečnosti.",
"%s requires a modern browser to work.":
"%s za svoje delovanje potrebuje moderen brskalnik.",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"Še vedno uporabljaš Internet Explorer? Naredi si uslugo, preklopi na moderen brskalnik:",
"New":
"Nov prilepek",
"Send":
@@ -164,11 +162,36 @@
"Could not get paste data: %s":
"Could not get paste data: %s",
"QR code": "QR code",
"I love you too, bot…": "I love you too, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

198
i18n/uk.json Normal file
View File

@@ -0,0 +1,198 @@
{
"PrivateBin": "PrivateBin",
"%s is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted <i>in the browser</i> using 256 bits AES. More information on the <a href=\"https://privatebin.info/\">project page</a>.":
"%s це мінімалістичний Open Source проєкт для створення нотаток, де сервер не знає нічого про дані, що зберігаються. Дані шифруються/розшифровуються <i>у переглядачі</i> з використанням 256-бітного шифрувания AES. Подробиці можна дізнатися на <a href=\"https://privatebin.info/\">сайті проєкту</a>.",
"Because ignorance is bliss":
"Бо незнання - благо",
"en": "uk",
"Paste does not exist, has expired or has been deleted.":
"Допис не існує, протермінований чи був видалений.",
"%s requires php %s or above to work. Sorry.":
"Для роботи %s потрібен php %s и вище. Вибачте.",
"%s requires configuration section [%s] to be present in configuration file.":
"%s потрібна секція [%s] в конфігураційному файлі.",
"Please wait %d seconds between each post.":
["Будь ласка, зачекайте %d секунду між дописами.", "Будь ласка, зачекайте %d секунди між дописами.", "Будь ласка, зачекайте %d секунд між дописами."],
"Paste is limited to %s of encrypted data.":
"Розмір допису обмежений %s зашифрованих даних.",
"Invalid data.":
"Неправильні дані.",
"You are unlucky. Try again.":
"Вам не пощастило. Спробуйте ще раз.",
"Error saving comment. Sorry.":
"Помилка при збереженні коментаря. Вибачте.",
"Error saving paste. Sorry.":
"Помилка при збереженні допису. Вибачте.",
"Invalid paste ID.":
"Неправильний ID допису.",
"Paste is not of burn-after-reading type.":
"Тип допису не \"Знищити після прочитання\".",
"Wrong deletion token. Paste was not deleted.":
"Неправильний ключ вилучення допису. Допис не вилучено.",
"Paste was properly deleted.":
"Допис був вилучений повністю.",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"Для роботи %s потрібен увімкнутий JavaScript. Вибачте.",
"%s requires a modern browser to work.":
"Для роботи %s потрібен більш сучасний переглядач.",
"New":
"Новий допис",
"Send":
"Відправити",
"Clone":
"Дублювати",
"Raw text":
"Початковий текст",
"Expires":
"Вилучити через",
"Burn after reading":
"Знищити після прочитання",
"Open discussion":
"Відкрити обговорення",
"Password (recommended)":
"Пароль (рекомендується)",
"Discussion":
"Обговорення",
"Toggle navigation":
"Перемкнути навігацію",
"%d seconds": ["%d секунду", "%d секунди", "%d секунд"],
"%d minutes": ["%d хвилину", "%d хвилини", "%d хвилин"],
"%d hours": ["%d годину", "%d години", "%d годин"],
"%d days": ["%d день", "%d дні", "%d днів"],
"%d weeks": ["%d тиждень", "%d тижні", "%d тижнів"],
"%d months": ["%d місяць", "%d місяці", "%d місяців"],
"%d years": ["%d рік", "%d роки", "%d років"],
"Never":
"Ніколи",
"Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.":
"Примітка: Це тестовий сервіс: Дані можуть бути вилучені в будь який момент. Кошенята помруть, якщо ви будете зловживати сервісом.",
"This document will expire in %d seconds.":
["Документ буде вилучений через %d секунду.", "Документ буде вилучений через %d секунди.", "Документ буде вилучений через %d секунд."],
"This document will expire in %d minutes.":
["Документ буде вилучений через %d хвилину.", "Документ буде вилучений через %d хвилини.", "Документ буде вилучений через %d хвилин."],
"This document will expire in %d hours.":
["Документ буде вилучений через %d годину.", "Документ буде вилучений через %d години.", "Документ буде вилучений через %d годин."],
"This document will expire in %d days.":
["Документ буде вилучений через %d день.", "Документ буде вилучений через %d дні.", "Документ буде вилучений через %d днів."],
"This document will expire in %d months.":
["Документ буде вилучений через %d місяць.", "Документ буде вилучений через %d місяці.", "Документ буде вилучений через %d місяців."],
"Please enter the password for this paste:":
"Будь ласка, введіть пароль від допису:",
"Could not decrypt data (Wrong key?)":
"Неможливо розшифрувати дані (Неправильний ключ?)",
"Could not delete the paste, it was not stored in burn after reading mode.":
"Неможливо вилучити допис, він не був збережений в режимі знищити після прочитання.",
"FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.":
"ЛИШЕ ДЛЯ ВАШИХ ОЧЕЙ. Не закривайте це вікно, це повідомлення не може бути показано знову.",
"Could not decrypt comment; Wrong key?":
"Неможливо розшифрувати коментар; Неправильний ключ?",
"Reply":
"Відповісти",
"Anonymous":
"Анонім",
"Avatar generated from IP address":
"Аватар зґенерований з IP-адреси",
"Add comment":
"Додати коментар",
"Optional nickname…":
"Необов’язкове прізвисько…",
"Post comment":
"Відправити коментар",
"Sending comment…":
"Відправка коментаря…",
"Comment posted.":
"Коментар опублікований.",
"Could not refresh display: %s":
"Не вдалося оновити екран: %s",
"unknown status":
"невідома причина",
"server error or not responding":
"помилка на сервері чи немає відповіді",
"Could not post comment: %s":
"Не вдалося опублікувати коментар: %s",
"Sending paste…":
"Відправка допису…",
"Your paste is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit [Ctrl]+[c] to copy)</span>":
"Посилання на допис <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Тисніть [Ctrl]+[c], щоб скопіювати посилання)</span>",
"Delete data":
"Видалити допис",
"Could not create paste: %s":
"Не вдалося опублікувати допис: %s",
"Cannot decrypt paste: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)":
"Неможливо розшифрувати запис: Ключ дешифрування відсутній в посиланні (Можливо, ви використовуєте скорочувач посилань, що видаляє частину посилання?)",
"B": "байт",
"KiB": "Кбайт",
"MiB": "Мбайт",
"GiB": "Гбайт",
"TiB": "Тбайт",
"PiB": "Пбайт",
"EiB": "Ебайт",
"ZiB": "Збайт",
"YiB": "Йбайт",
"Format": "Формат",
"Plain Text": "Звичайний текст",
"Source Code": "Джерельний код",
"Markdown": "Мова розмітки",
"Download attachment": "Звантажити прикріплений файл",
"Cloned: '%s'": "Дубльовано: '%s'",
"The cloned file '%s' was attached to this paste.":
"Дублікат файлу '%s' був прикріплений до цього запису.",
"Attach a file": "Прикріпити файл",
"alternatively drag & drop a file or paste an image from the clipboard": "також можна перенести файл у вікно переглядача чи вставити зображення з буфера",
"File too large, to display a preview. Please download the attachment.": "Файл завеликий для відображення передогляду. Будь ласка, звантажте прикріплений файл.",
"Remove attachment": "Видалити вкладення",
"Your browser does not support uploading encrypted files. Please use a newer browser.":
"Ваш переглядач не підтримує відправлення зашифрованих файлів. Використовуйте сучасніший переглядач.",
"Invalid attachment.": "Невідоме вкладення.",
"Options": "Опції",
"Shorten URL": "Коротке посилання",
"Editor": "Редактор",
"Preview": "Передогляд",
"%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.":
"Змінна PATH необхідна %s в конці \"%s\". Будь ласка, оновіть змінну PATH у вашому index.php.",
"Decrypt":
"Розшифрувати",
"Enter password":
"Введіть пароль",
"Loading…": "Завантаження…",
"Decrypting paste…": "Розшифровування допису…",
"Preparing new paste…": "Приготування нового допису…",
"In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.":
"Якщо це повідомлення не зникатиме тривалий час, подивіться <a href=\"%s\">цей FAQ з інформацією про можливе вирішення проблеми</a>.",
"+++ no paste text +++": "+++ у дописі немає тексту +++",
"Could not get paste data: %s":
"Не вдалося отримати дані допису: %s",
"QR code": "QR код",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"Цей сайт використовує незахищене HTTP підключення! Будь ласка, використовуйте його лише для тестування.",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"Для подробиць <a href=\"%s\">дивіться інформацію в FAQ</a>.",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Ваш переглядач вимагає підключення HTTPS для підтримки WebCrypto API. Спробуйте <a href=\"%s\">перемкнутися на HTTPS</a>.",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"Ваш переглядач не підтримує WebAssembly, що використовується для стиснення zlib. Ви можете створювати нестиснені документи, але не зможете читати стиснені.",
"waiting on user to provide a password":
"waiting on user to provide a password",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.",
"Retry":
"Retry",
"Showing raw text…":
"Showing raw text…",
"Notice:":
"Notice:",
"This link will expire after %s.":
"This link will expire after %s.",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"This link can only be accessed once, do not use back or refresh button in your browser.",
"Link:":
"Link:",
"Recipient may become aware of your timezone, convert time to UTC?":
"Recipient may become aware of your timezone, convert time to UTC?",
"Use Current Timezone":
"Use Current Timezone",
"Convert To UTC":
"Convert To UTC",
"Close":
"Close"
}

View File

@@ -31,12 +31,10 @@
"错误的删除token粘贴内容没有被删除。",
"Paste was properly deleted.":
"粘贴内容已被正确删除。",
"JavaScript is required for %s to work.<br />Sorry for the inconvenience.":
"%s需要JavaScript来进行加解密。<br />给你带来的不便敬请谅解。",
"JavaScript is required for %s to work. Sorry for the inconvenience.":
"%s需要JavaScript来进行加解密。 给你带来的不便敬请谅解。",
"%s requires a modern browser to work.":
"%s需要在现代浏览器上工作。",
"Still using Internet Explorer? Do yourself a favor, switch to a modern browser:":
"还在使用Internet Explorer对自己好点换一个现代浏览器",
"New":
"新建",
"Send":
@@ -155,11 +153,36 @@
"Could not get paste data: %s":
"无法获取粘贴数据:%s",
"QR code": "二维码",
"I love you too, bot…": "I love you too, bot…",
"This website is using an insecure HTTP connection! Please use it only for testing.":
"This website is using an insecure HTTP connection! Please use it only for testing.",
"该网站使用了不安全的HTTP连接 请仅将其用于测试。",
"For more information <a href=\"%s\">see this FAQ entry</a>.":
"For more information <a href=\"%s\">see this FAQ entry</a>.",
"有关更多信息,<a href=\"%s\">请参阅此常见问题解答</a>",
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>.":
"Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href=\"%s\">switching to HTTPS</a>."
"您的浏览器可能需要HTTPS连接才能支持WebCrypto API。 尝试<a href=\"%s\">切换到HTTPS </a>",
"Your browser doesn't support WebAssembly, used for zlib compression. You can create uncompressed documents, but can't read compressed ones.":
"您的浏览器不支持用于zlib压缩的WebAssembly。 您可以创建未压缩的文档,但不能读取压缩的文档。",
"waiting on user to provide a password":
"请输入密码",
"Could not decrypt data. Did you enter a wrong password? Retry with the button at the top.":
"无法解密数据。 您输入了错误的密码吗? 点顶部的按钮重试。",
"Retry":
"重试",
"Showing raw text…":
"显示原始文字…",
"Notice:":
"注意:",
"This link will expire after %s.":
"这个链接将会在 %s 过期。",
"This link can only be accessed once, do not use back or refresh button in your browser.":
"这个链接只能被访问一次,请勿使用浏览器中的返回和刷新按钮。",
"Link:":
"链接地址:",
"Recipient may become aware of your timezone, convert time to UTC?":
"收件人可能会知道您的时区将时间转换为UTC",
"Use Current Timezone":
"使用当前时区",
"Convert To UTC":
"转换为UTC",
"Close":
"关闭"
}

90
img/browserstack.svg Normal file
View File

@@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 21.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 490.1 105.6" style="enable-background:new 0 0 490.1 105.6;" xml:space="preserve">
<style type="text/css">
.st0{fill:#F4B960;}
.st1{fill:#E66F32;}
.st2{fill:#E43C41;}
.st3{fill:#BDD041;}
.st4{fill:#6DB54C;}
.st5{fill:#AEDAE6;}
.st6{fill:#56B8DE;}
.st7{fill:#00B1D5;}
.st8{fill:url(#SVGID_1_);}
.st9{fill:#221F1F;}
.st10{fill:#FFFFFF;}
.st11{fill:#000111;}
</style>
<title>Browserstack-logo-white</title>
<circle class="st0" cx="52.8" cy="52.8" r="52.8"/>
<circle class="st1" cx="47.5" cy="47.5" r="47.5"/>
<circle class="st2" cx="53.8" cy="41.1" r="41.1"/>
<circle class="st3" cx="57.1" cy="44.4" r="37.8"/>
<circle class="st4" cx="54.3" cy="47.2" r="35.1"/>
<circle class="st5" cx="48.8" cy="41.7" r="29.5"/>
<circle class="st6" cx="53.6" cy="36.8" r="24.7"/>
<circle class="st7" cx="56.6" cy="39.9" r="21.7"/>
<radialGradient id="SVGID_1_" cx="53.45" cy="63.02" r="18.57" gradientTransform="matrix(1 0 0 -1 0 106)" gradientUnits="userSpaceOnUse">
<stop offset="0" style="stop-color:#797979"/>
<stop offset="1" style="stop-color:#4C4C4C"/>
</radialGradient>
<circle class="st8" cx="53.5" cy="43" r="18.6"/>
<circle class="st9" cx="53.5" cy="43" r="18.6"/>
<ellipse transform="matrix(0.4094 -0.9123 0.9123 0.4094 2.8913 76.9251)" class="st10" cx="60.9" cy="36.2" rx="5.7" ry="3.7"/>
<path class="st11" d="M122.5,32.6c0-0.3,0.3-0.6,0.6-0.6c0,0,0,0,0.1,0h16.6c9.5,0,13.9,4.4,13.9,11c0.2,3.7-1.8,7.2-5.2,8.8v0.1
c3.7,1.5,6.1,5.2,6,9.3c0,8.2-5.6,12.2-15.4,12.2h-16c-0.3,0-0.6-0.2-0.7-0.5c0,0,0,0,0-0.1L122.5,32.6L122.5,32.6z M139.6,49.1
c3.9,0,6.4-2.2,6.4-5.4s-2.4-5.5-6.4-5.5h-8.9c-0.2,0-0.4,0.1-0.4,0.3c0,0,0,0,0,0.1v10.2c0,0.2,0.1,0.3,0.3,0.4c0,0,0,0,0.1,0
H139.6L139.6,49.1z M130.6,66.9h9.3c4.3,0,6.8-2.3,6.8-5.8s-2.4-5.7-6.7-5.7h-9.3c-0.2,0-0.4,0.1-0.4,0.3c0,0,0,0,0,0.1v10.7
C130.3,66.8,130.4,66.9,130.6,66.9C130.6,66.9,130.6,66.9,130.6,66.9L130.6,66.9z"/>
<path class="st11" d="M159.9,73.3c-0.3,0-0.6-0.2-0.7-0.5c0,0,0,0,0-0.1V44.6c0-0.3,0.3-0.6,0.6-0.6c0,0,0,0,0.1,0h6
c0.3,0,0.6,0.2,0.7,0.5c0,0,0,0,0,0.1v2.5h0.1c1.5-2.2,4.2-3.8,8.2-3.8c2.4,0,4.8,0.8,6.6,2.4c0.3,0.3,0.4,0.5,0.1,0.8l-3.5,4.1
c-0.2,0.3-0.6,0.4-0.9,0.2c0,0,0,0-0.1,0c-1.4-0.9-3-1.4-4.7-1.4c-4.1,0-6,2.7-6,7.4v15.9c0,0.3-0.3,0.6-0.6,0.6c0,0,0,0-0.1,0
H159.9L159.9,73.3z"/>
<path class="st11" d="M182.9,65.8c-0.8-2.3-1.1-4.8-1.1-7.2c-0.1-2.5,0.3-4.9,1.1-7.2c1.8-5.1,6.6-8.1,13.1-8.1s11.2,3,13,8.1
c0.8,2.3,1.1,4.8,1.1,7.2c0.1,2.5-0.3,4.9-1.1,7.2c-1.8,5.1-6.6,8.1-13,8.1S184.7,71,182.9,65.8z M201.9,64c0.5-1.7,0.8-3.6,0.7-5.4
c0.1-1.8-0.1-3.7-0.7-5.4c-0.9-2.5-3.3-4-5.9-3.8c-2.6-0.2-5.1,1.4-6,3.8c-0.5,1.8-0.8,3.6-0.7,5.4c-0.1,1.8,0.1,3.7,0.7,5.4
c0.9,2.5,3.4,4,6,3.8C198.6,68,201,66.5,201.9,64L201.9,64z"/>
<path class="st11" d="M241.9,73.3c-0.4,0-0.7-0.3-0.8-0.6L235,53.9h-0.1l-6.2,18.7c-0.1,0.4-0.4,0.6-0.8,0.6h-5.4
c-0.4,0-0.7-0.3-0.8-0.6l-10-28.1c-0.1-0.2,0-0.5,0.2-0.6c0.1,0,0.2-0.1,0.3,0h6.3c0.4,0,0.8,0.2,0.9,0.6l6.1,19.3h0.1l6-19.3
c0.1-0.4,0.5-0.6,0.9-0.6h4.7c0.4,0,0.7,0.2,0.9,0.6l6.4,19.3h0.1l5.8-19.3c0.1-0.4,0.5-0.7,0.9-0.6h6.3c0.2-0.1,0.5,0.1,0.5,0.3
c0,0.1,0,0.2,0,0.3l-10,28.1c-0.1,0.4-0.4,0.6-0.8,0.6L241.9,73.3L241.9,73.3z"/>
<path class="st11" d="M259.3,69.3c-0.2-0.2-0.3-0.6-0.1-0.8c0,0,0,0,0.1-0.1l3.7-3.6c0.3-0.2,0.7-0.2,0.9,0c2.6,2.1,5.9,3.3,9.3,3.3
c3.9,0,5.9-1.5,5.9-3.5c0-1.8-1.1-2.9-5.2-3.2l-3.4-0.3c-6.4-0.6-9.7-3.6-9.7-8.6c0-5.7,4.4-9.2,12.3-9.2c4.2-0.1,8.4,1.2,11.9,3.6
c0.3,0.2,0.3,0.5,0.2,0.8c0,0,0,0,0,0.1l-3.2,3.6c-0.2,0.3-0.6,0.3-0.9,0.1c-2.5-1.5-5.4-2.4-8.3-2.4c-3.1,0-4.8,1.3-4.8,3
s1.1,2.7,5.2,3.1l3.4,0.3c6.6,0.6,9.8,3.8,9.8,8.6c0,5.8-4.6,9.9-13.3,9.9C268,74,263.2,72.4,259.3,69.3z"/>
<path class="st11" d="M291.2,65.8c-0.8-2.3-1.2-4.7-1.1-7.2c-0.1-2.5,0.3-4.9,1-7.2c1.8-5.1,6.6-8.1,12.9-8.1c6.5,0,11.2,3.1,13,8.1
c0.7,2.1,1,4.1,1,8.8c0,0.3-0.3,0.6-0.6,0.6c0,0-0.1,0-0.1,0h-19.5c-0.2,0-0.4,0.1-0.4,0.3c0,0,0,0,0,0.1c0,0.8,0.2,1.5,0.5,2.2
c1,2.9,3.5,4.4,7.1,4.4c2.7,0.1,5.4-0.9,7.4-2.8c0.2-0.3,0.7-0.4,1-0.1c0,0,0,0,0,0l3.9,3.2c0.2,0.1,0.3,0.5,0.2,0.7
c0,0.1-0.1,0.1-0.1,0.1c-2.7,2.9-7.2,5-13,5C297.8,73.9,293,70.9,291.2,65.8z M310.4,52.8c-0.9-2.4-3.2-3.8-6.2-3.8
s-5.4,1.4-6.2,3.8c-0.3,0.8-0.4,1.6-0.4,2.5c0,0.2,0.1,0.3,0.3,0.4c0,0,0,0,0.1,0h12.4c0.2,0,0.4-0.1,0.4-0.3c0,0,0,0,0-0.1
C310.8,54.5,310.6,53.6,310.4,52.8L310.4,52.8z"/>
<path class="st11" d="M323.6,73.3c-0.3,0-0.6-0.2-0.7-0.5c0,0,0,0,0-0.1V44.6c0-0.3,0.3-0.6,0.6-0.6c0,0,0,0,0.1,0h6
c0.3,0,0.6,0.2,0.7,0.5c0,0,0,0,0,0.1v2.5h0.1c1.5-2.2,4.2-3.8,8.2-3.8c2.4,0,4.8,0.8,6.6,2.4c0.3,0.3,0.4,0.5,0.1,0.8l-3.5,4.1
c-0.2,0.3-0.6,0.4-0.9,0.2c0,0,0,0-0.1,0c-1.4-0.9-3-1.4-4.7-1.4c-4.1,0-6,2.7-6,7.4v15.9c0,0.3-0.3,0.6-0.6,0.6c0,0,0,0-0.1,0
H323.6L323.6,73.3z"/>
<path class="st11" d="M346.5,68.5c-0.3-0.2-0.4-0.6-0.2-0.9c0,0,0,0,0,0l4.1-4.4c0.2-0.3,0.6-0.3,0.9-0.1c0,0,0,0,0,0
c3.5,2.7,7.7,4.2,12.1,4.4c5.3,0,8.4-2.5,8.4-6c0-3-2-4.9-8.1-5.7l-2.4-0.3c-8.6-1.1-13.5-4.9-13.5-11.8c0-7.5,5.9-12.4,15.1-12.4
c5.1-0.1,10.1,1.4,14.5,4.2c0.3,0.1,0.4,0.4,0.2,0.7c0,0.1-0.1,0.1-0.1,0.2l-3.1,4.5c-0.2,0.3-0.6,0.4-0.9,0.2
c-3.2-2.1-6.9-3.2-10.7-3.2c-4.5,0-7,2.3-7,5.5c0,2.9,2.2,4.8,8.2,5.6l2.4,0.3c8.6,1.1,13.3,4.9,13.3,12c0,7.3-5.7,12.8-16.8,12.8
C356.3,73.9,350,71.5,346.5,68.5z"/>
<path class="st11" d="M393.3,73.8c-6.4,0-8.8-2.9-8.8-8.6V49.8c0-0.2-0.1-0.3-0.3-0.4c0,0,0,0-0.1,0H382c-0.3,0-0.6-0.2-0.7-0.5
c0,0,0,0,0-0.1v-4.1c0-0.3,0.3-0.6,0.6-0.6c0,0,0,0,0.1,0h2.1c0.2,0,0.4-0.1,0.4-0.3c0,0,0,0,0-0.1v-8c0-0.3,0.3-0.6,0.6-0.6
c0,0,0,0,0.1,0h6c0.3,0,0.6,0.2,0.7,0.5c0,0,0,0,0,0.1v8c0,0.2,0.1,0.3,0.3,0.4c0,0,0,0,0.1,0h4.2c0.3,0,0.6,0.2,0.7,0.5
c0,0,0,0,0,0.1v4.1c0,0.3-0.3,0.6-0.6,0.6c0,0,0,0-0.1,0h-4.2c-0.2,0-0.4,0.1-0.4,0.3c0,0,0,0,0,0.1V65c0,2.1,0.9,2.7,3,2.7h1.6
c0.3,0,0.6,0.2,0.7,0.5c0,0,0,0,0,0.1v4.9c0,0.3-0.3,0.6-0.6,0.6c0,0,0,0-0.1,0L393.3,73.8L393.3,73.8z"/>
<path class="st11" d="M421.2,73.3c-0.3,0-0.6-0.2-0.7-0.5c0,0,0,0,0-0.1v-2.1h0c-1.5,2-4.5,3.4-8.9,3.4c-5.8,0-10.6-2.8-10.6-8.9
c0-6.4,4.9-9.3,12.7-9.3h6.4c0.2,0,0.4-0.1,0.4-0.3c0,0,0,0,0-0.1v-1.4c0-3.3-1.7-4.9-7-4.9c-2.6-0.1-5.1,0.6-7.2,2
c-0.3,0.2-0.7,0.2-0.9-0.1c0,0,0,0,0-0.1l-2.4-4c-0.2-0.2-0.1-0.6,0.1-0.8c0,0,0,0,0,0c2.6-1.7,6-2.9,11.2-2.9
c9.6,0,13.2,3,13.2,10.2v19.1c0,0.3-0.3,0.6-0.6,0.6c0,0,0,0-0.1,0H421.2L421.2,73.3z M420.4,63.4v-2.2c0-0.2-0.1-0.3-0.3-0.4
c0,0,0,0-0.1,0h-5.2c-4.7,0-6.8,1.2-6.8,3.9c0,2.4,1.9,3.6,5.5,3.6C417.9,68.4,420.4,66.8,420.4,63.4L420.4,63.4z"/>
<path class="st11" d="M433.1,65.8c-0.7-2.3-1.1-4.8-1-7.2c-0.1-2.4,0.3-4.9,1-7.2c1.8-5.2,6.7-8.1,13.1-8.1c4.2-0.2,8.2,1.5,11,4.6
c0.2,0.2,0.2,0.6,0,0.8c0,0,0,0-0.1,0.1l-4.1,3.3c-0.3,0.2-0.7,0.2-0.9-0.1c0,0,0,0,0-0.1c-1.5-1.7-3.6-2.6-5.9-2.5
c-2.8,0-5,1.3-5.9,3.8c-0.5,1.8-0.8,3.6-0.7,5.4c-0.1,1.8,0.1,3.7,0.7,5.5c0.9,2.5,3.1,3.8,5.9,3.8c2.2,0.1,4.4-0.9,5.9-2.6
c0.2-0.3,0.6-0.3,0.9-0.1c0,0,0,0,0,0l4.1,3.3c0.3,0.2,0.3,0.5,0.1,0.8c0,0,0,0-0.1,0.1c-2.9,3-6.9,4.6-11,4.5
C439.8,73.9,435,71.1,433.1,65.8z"/>
<path class="st11" d="M482.8,73.3c-0.4,0-0.8-0.2-1-0.6l-8-12.3l-4.3,4.6v7.7c0,0.3-0.3,0.6-0.6,0.6c0,0,0,0-0.1,0h-6
c-0.3,0-0.6-0.2-0.7-0.5c0,0,0,0,0-0.1V32.6c0-0.3,0.3-0.6,0.6-0.6c0,0,0,0,0.1,0h6c0.3,0,0.6,0.2,0.7,0.5c0,0,0,0,0,0.1v23.8
l10.8-11.8c0.3-0.4,0.8-0.6,1.2-0.6h6.7c0.2,0,0.4,0.1,0.4,0.3c0,0.1,0,0.3-0.1,0.3l-10.1,10.7L490,72.7c0.1,0.2,0.1,0.4,0,0.5
c-0.1,0.1-0.2,0.1-0.3,0.1H482.8L482.8,73.3z"/>
</svg>

After

Width:  |  Height:  |  Size: 7.4 KiB

BIN
img/icon_email.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 B

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
// change this, if your php files and data is outside of your webservers document root

View File

@@ -1,5 +1,6 @@
---
include:
- legacy.js
- privatebin.js
reporter:
- text

View File

@@ -1,151 +0,0 @@
// base-x encoding / decoding
// based on https://github.com/cryptocoinjs/base-x 3.0.5
// modification: removed Buffer dependency and node.modules entry
// Copyright (c) 2018 base-x contributors
// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
// Distributed under the MIT software license, see the accompanying
// file LICENSE or http://www.opensource.org/licenses/mit-license.php.
(function(){
'use strict';
this.baseX = function base (ALPHABET) {
if (ALPHABET.length >= 255) throw new TypeError('Alphabet too long')
const BASE_MAP = new Uint8Array(256)
BASE_MAP.fill(255)
for (let i = 0; i < ALPHABET.length; i++) {
const x = ALPHABET.charAt(i)
const xc = x.charCodeAt(0)
if (BASE_MAP[xc] !== 255) throw new TypeError(x + ' is ambiguous')
BASE_MAP[xc] = i
}
const BASE = ALPHABET.length
const LEADER = ALPHABET.charAt(0)
const FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up
const iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up
function encode (source) {
if (source.length === 0) return ''
// Skip & count leading zeroes.
let zeroes = 0
let length = 0
let pbegin = 0
const pend = source.length
while (pbegin !== pend && source[pbegin] === 0) {
pbegin++
zeroes++
}
// Allocate enough space in big-endian base58 representation.
const size = ((pend - pbegin) * iFACTOR + 1) >>> 0
const b58 = new Uint8Array(size)
// Process the bytes.
while (pbegin !== pend) {
let carry = source[pbegin]
// Apply "b58 = b58 * 256 + ch".
let i = 0
for (let it = size - 1; (carry !== 0 || i < length) && (it !== -1); it--, i++) {
carry += (256 * b58[it]) >>> 0
b58[it] = (carry % BASE) >>> 0
carry = (carry / BASE) >>> 0
}
if (carry !== 0) throw new Error('Non-zero carry')
length = i
pbegin++
}
// Skip leading zeroes in base58 result.
let it = size - length
while (it !== size && b58[it] === 0) {
it++
}
// Translate the result into a string.
let str = LEADER.repeat(zeroes)
for (; it < size; ++it) str += ALPHABET.charAt(b58[it])
return str
}
function decodeUnsafe (source) {
if (typeof source !== 'string') throw new TypeError('Expected String')
if (source.length === 0) return ''
let psz = 0
// Skip leading spaces.
if (source[psz] === ' ') return
// Skip and count leading '1's.
let zeroes = 0
let length = 0
while (source[psz] === LEADER) {
zeroes++
psz++
}
// Allocate enough space in big-endian base256 representation.
const size = (((source.length - psz) * FACTOR) + 1) >>> 0 // log(58) / log(256), rounded up.
const b256 = new Uint8Array(size)
// Process the characters.
while (source[psz]) {
// Decode character
let carry = BASE_MAP[source.charCodeAt(psz)]
// Invalid character
if (carry === 255) return
let i = 0
for (let it = size - 1; (carry !== 0 || i < length) && (it !== -1); it--, i++) {
carry += (BASE * b256[it]) >>> 0
b256[it] = (carry % 256) >>> 0
carry = (carry / 256) >>> 0
}
if (carry !== 0) throw new Error('Non-zero carry')
length = i
psz++
}
// Skip trailing spaces.
if (source[psz] === ' ') return
// Skip leading zeroes in b256.
let it = size - length
while (it !== size && b256[it] === 0) {
it++
}
var vch = [];
let j = zeroes
while (it !== size) {
vch[j++] = b256[it++]
}
return vch
}
function decode (string) {
const buffer = decodeUnsafe(string)
if (buffer) return buffer
throw new Error('Non-base' + BASE + ' character')
}
return {
encode: encode,
decodeUnsafe: decodeUnsafe,
decode: decode
}
}
}).call(this);

120
js/base-x-3.0.7.js Normal file
View File

@@ -0,0 +1,120 @@
'use strict';
// base-x encoding / decoding
// based on https://github.com/cryptocoinjs/base-x 3.0.7
// modification: removed Buffer dependency and node.modules entry
// Copyright (c) 2018 base-x contributors
// Copyright (c) 2014-2018 The Bitcoin Core developers (base58.cpp)
// Distributed under the MIT software license, see the accompanying
// file LICENSE or http://www.opensource.org/licenses/mit-license.php.
(function(){
this.baseX = function base (ALPHABET) {
if (ALPHABET.length >= 255) { throw new TypeError('Alphabet too long') }
var BASE_MAP = new Uint8Array(256)
BASE_MAP.fill(255)
for (var i = 0; i < ALPHABET.length; i++) {
var x = ALPHABET.charAt(i)
var xc = x.charCodeAt(0)
if (BASE_MAP[xc] !== 255) { throw new TypeError(x + ' is ambiguous') }
BASE_MAP[xc] = i
}
var BASE = ALPHABET.length
var LEADER = ALPHABET.charAt(0)
var FACTOR = Math.log(BASE) / Math.log(256) // log(BASE) / log(256), rounded up
var iFACTOR = Math.log(256) / Math.log(BASE) // log(256) / log(BASE), rounded up
function encode (source) {
if (source.length === 0) { return '' }
// Skip & count leading zeroes.
var zeroes = 0
var length = 0
var pbegin = 0
var pend = source.length
while (pbegin !== pend && source[pbegin] === 0) {
pbegin++
zeroes++
}
// Allocate enough space in big-endian base58 representation.
var size = ((pend - pbegin) * iFACTOR + 1) >>> 0
var b58 = new Uint8Array(size)
// Process the bytes.
while (pbegin !== pend) {
var carry = source[pbegin]
// Apply "b58 = b58 * 256 + ch".
var i = 0
for (var it1 = size - 1; (carry !== 0 || i < length) && (it1 !== -1); it1--, i++) {
carry += (256 * b58[it1]) >>> 0
b58[it1] = (carry % BASE) >>> 0
carry = (carry / BASE) >>> 0
}
if (carry !== 0) { throw new Error('Non-zero carry') }
length = i
pbegin++
}
// Skip leading zeroes in base58 result.
var it2 = size - length
while (it2 !== size && b58[it2] === 0) {
it2++
}
// Translate the result into a string.
var str = LEADER.repeat(zeroes)
for (; it2 < size; ++it2) { str += ALPHABET.charAt(b58[it2]) }
return str
}
function decodeUnsafe (source) {
if (typeof source !== 'string') { throw new TypeError('Expected String') }
if (source.length === 0) { return '' }
var psz = 0
// Skip leading spaces.
if (source[psz] === ' ') { return }
// Skip and count leading '1's.
var zeroes = 0
var length = 0
while (source[psz] === LEADER) {
zeroes++
psz++
}
// Allocate enough space in big-endian base256 representation.
var size = (((source.length - psz) * FACTOR) + 1) >>> 0 // log(58) / log(256), rounded up.
var b256 = new Uint8Array(size)
// Process the characters.
while (source[psz]) {
// Decode character
var carry = BASE_MAP[source.charCodeAt(psz)]
// Invalid character
if (carry === 255) { return }
var i = 0
for (var it3 = size - 1; (carry !== 0 || i < length) && (it3 !== -1); it3--, i++) {
carry += (BASE * b256[it3]) >>> 0
b256[it3] = (carry % 256) >>> 0
carry = (carry / 256) >>> 0
}
if (carry !== 0) { throw new Error('Non-zero carry') }
length = i
psz++
}
// Skip trailing spaces.
if (source[psz] === ' ') { return }
// Skip leading zeroes in b256.
var it4 = size - length
while (it4 !== size && b256[it4] === 0) {
it4++
}
var vch = []
var j = zeroes
while (it4 !== size) {
vch[j++] = b256[it4++]
}
return vch
}
function decode (string) {
var buffer = decodeUnsafe(string)
if (buffer) { return buffer }
throw new Error('Non-base' + BASE + ' character')
}
return {
encode: encode,
decodeUnsafe: decodeUnsafe,
decode: decode
}
}
}).call(this);

View File

@@ -16,9 +16,10 @@ global.zlib = require('./zlib-1.2.11').zlib;
require('./prettify');
global.prettyPrint = window.PR.prettyPrint;
global.prettyPrintOne = window.PR.prettyPrintOne;
global.showdown = require('./showdown-1.9.0');
global.DOMPurify = require('./purify-1.0.11');
global.baseX = require('./base-x-3.0.5.1').baseX;
global.showdown = require('./showdown-1.9.1');
global.DOMPurify = require('./purify-2.0.8');
global.baseX = require('./base-x-3.0.7').baseX;
global.Legacy = require('./legacy').Legacy;
require('./bootstrap-3.3.7');
require('./privatebin');
@@ -35,25 +36,10 @@ var a2zString = ['a','b','c','d','e','f','g','h','i','j','k','l','m',
return c.toUpperCase();
})
),
schemas = ['ftp','gopher','http','https','ws','wss'],
schemas = ['ftp','http','https'],
supportedLanguages = ['de', 'es', 'fr', 'it', 'no', 'pl', 'pt', 'oc', 'ru', 'sl', 'zh'],
mimeTypes = ['image/png', 'application/octet-stream'],
formats = ['plaintext', 'markdown', 'syntaxhighlighting'],
/**
* character to HTML entity lookup table
*
* @see {@link https://github.com/janl/mustache.js/blob/master/mustache.js#L60}
*/
entityMap = {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
"'": '&#39;',
'/': '&#x2F;',
'`': '&#x60;',
'=': '&#x3D;'
},
mimeFile = fs.createReadStream('/etc/mime.types'),
mimeLine = '';
@@ -96,22 +82,6 @@ function parseMime(line) {
exports.atob = atob;
exports.btoa = btoa;
/**
* convert all applicable characters to HTML entities
*
* @see {@link https://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet#RULE_.231_-_HTML_Escape_Before_Inserting_Untrusted_Data_into_HTML_Element_Content}
* @name htmlEntities
* @function
* @param {string} str
* @return {string} escaped HTML
*/
exports.htmlEntities = function(str) {
return String(str).replace(
/[&<>"'`=\/]/g, function(s) {
return entityMap[s];
});
};
// provides random lowercase characters from a to z
exports.jscA2zString = function() {
return jsc.elements(a2zString);

311
js/legacy.js Normal file
View File

@@ -0,0 +1,311 @@
/**
* PrivateBin
*
* a zero-knowledge paste bin
*
* @see {@link https://github.com/PrivateBin/PrivateBin}
* @copyright 2012 Sébastien SAUVAGE ({@link http://sebsauvage.net})
* @license {@link https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License}
* @version 1.3.1
* @name Legacy
* @namespace
*/
/**
* IMPORTANT NOTICE FOR DEVELOPERS:
* The logic in this file is intended to run in legacy browsers. Avoid any use of:
* - jQuery (doesn't work in older browsers)
* - ES5 or newer in general
* - const/let, use the traditional var declarations instead
* - async/await or Promises, use traditional callbacks
* - shorthand function notation "() => output", use the full "function() {return output;}" style
* - IE doesn't support:
* - URL(), use the traditional window.location object
* - endsWith(), use indexof()
* - yes, this logic needs to support IE 6, to at least display the error message
*/
'use strict';
(function() {
/**
* compatibility check
*
* @name Check
* @class
*/
var Check = (function () {
var me = {};
/**
* Status of the initial check, true means it passed
*
* @private
* @prop {bool}
*/
var status = false;
/**
* Initialization check did run
*
* @private
* @prop {bool}
*/
var init = false;
/**
* blacklist of UserAgents (parts) known to belong to a bot
*
* @private
* @enum {Array}
* @readonly
*/
var badBotUA = [
'Bot',
'bot'
];
/**
* whitelist of top level domains to consider a secure context,
* regardless of protocol
*
* @private
* @enum {Array}
* @readonly
*/
var tld = [
'.onion',
'.i2p'
];
/**
* whitelist of hostnames to consider a secure context,
* regardless of protocol
*
* @private
* @enum {Array}
* @readonly
*/
// whitelists of TLDs & local hostnames
var hostname = [
'localhost',
'127.0.0.1',
'[::1]'
];
/**
* check if the context is secure
*
* @private
* @name Check.isSecureContext
* @function
* @return {bool}
*/
function isSecureContext()
{
// use .isSecureContext if available
if (window.isSecureContext === true || window.isSecureContext === false) {
return window.isSecureContext;
}
// HTTP is obviously insecure
if (window.location.protocol !== 'http:') {
return true;
}
// filter out actually secure connections over HTTP
for (var i = 0; i < tld.length; i++) {
if (
window.location.hostname.indexOf(
tld[i],
window.location.hostname.length - tld[i].length
) !== -1
) {
return true;
}
}
// whitelist localhost for development
for (var j = 0; j < hostname.length; j++) {
if (window.location.hostname === hostname[j]) {
return true;
}
}
// totally INSECURE http protocol!
return false;
}
/**
* checks whether this is a bot we dislike
*
* @private
* @name Check.isBadBot
* @function
* @return {bool}
*/
function isBadBot() {
// check whether a bot user agent part can be found in the current
// user agent
for (var i = 0; i < badBotUA.length; i++) {
if (navigator.userAgent.indexOf(badBotUA[i]) !== -1) {
return true;
}
}
return false;
}
/**
* checks whether this is an unsupported browser, via feature detection
*
* @private
* @name Check.isOldBrowser
* @function
* @return {bool}
*/
function isOldBrowser() {
// webcrypto support
if (!(
'crypto' in window &&
'getRandomValues' in window.crypto &&
'subtle' in window.crypto &&
'encrypt' in window.crypto.subtle &&
'decrypt' in window.crypto.subtle &&
'Uint8Array' in window &&
'Uint32Array' in window
)) {
return true;
}
// async & ES6 support
try {
eval('async () => {}');
} catch (e) {
if (e instanceof SyntaxError) {
return true;
} else {
throw e; // throws CSP error
}
}
return false;
}
/**
* shows an error message
*
* @private
* @name Check.showError
* @param {string} message
* @function
*/
function showError(message)
{
var element = document.getElementById('errormessage');
if (message.indexOf('<a') === -1) {
element.appendChild(
document.createTextNode(message)
);
} else {
element.innerHTML = message;
}
removeHiddenFromId('errormessage');
}
/**
* removes "hidden" CSS class from element with given ID
*
* @private
* @name Check.removeHiddenFromId
* @param {string} id
* @function
*/
function removeHiddenFromId(id)
{
var element = document.getElementById(id);
if (element) {
element.className = element.className.replace(/\bhidden\b/g, '');
}
}
/**
* returns if the check has concluded
*
* @name Check.getInit
* @function
* @return {bool}
*/
me.getInit = function()
{
return init;
};
/**
* returns the current status of the check
*
* @name Check.getStatus
* @function
* @return {bool}
*/
me.getStatus = function()
{
return status;
};
/**
* init on application start, returns an all-clear signal
*
* @name Check.init
* @function
*/
me.init = function()
{
// prevent bots from viewing a paste and potentially deleting data
// when burn-after-reading is set
if (isBadBot()) {
showError('I love you too, bot…');
init = true;
return;
}
if (isOldBrowser()) {
// some browsers (Chrome based ones) would have webcrypto support if using HTTPS
if (!isSecureContext()) {
removeHiddenFromId('insecurecontextnotice');
}
removeHiddenFromId('oldnotice');
init = true;
return;
}
if (!isSecureContext()) {
removeHiddenFromId('httpnotice');
}
init = true;
// only if everything passed, we set the status to true
status = true;
};
return me;
})();
// main application start, called when DOM is fully loaded
if (document.readyState === 'complete' || (!document.attachEvent && document.readyState === 'interactive')) {
Check.init();
} else {
if (document.addEventListener) {
// first choice is DOMContentLoaded event
document.addEventListener('DOMContentLoaded', Check.init, false);
// backup is window load event
window.addEventListener('load', Check.init, false);
} else {
// must be IE
document.attachEvent('onreadystatechange', Check.init);
window.attachEvent('onload', Check.init);
}
}
this.Legacy = {
Check: Check
};
}).call(this);

View File

@@ -1,6 +1,6 @@
{
"name": "privatebin",
"version": "1.3",
"version": "1.3.0",
"description": "PrivateBin is a minimalist, open source online pastebin where the server has zero knowledge of pasted data. Data is encrypted/decrypted in the browser using 256 bit AES in Galois Counter mode (GCM).",
"main": "privatebin.js",
"directories": {

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

1
js/purify-2.0.8.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -4,16 +4,55 @@ var common = require('../common');
describe('Alert', function () {
describe('showStatus', function () {
jsc.property(
'shows a status message',
'shows a status message (basic)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
var expected = '<div id="status" role="alert" ' +
const expected = '<div id="status">' + message + '</div>';
$('body').html(
'<div id="status"></div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showStatus(message, icon);
const result = $('body').html();
return expected === result;
}
);
jsc.property(
'shows a status message (bootstrap)',
jsc.array(common.jscAlnumString()),
function (message) {
message = message.join('');
const expected = '<div id="status" role="alert" ' +
'class="statusmessage alert alert-info"><span ' +
'class="glyphicon glyphicon-info-sign" ' +
'aria-hidden="true"></span> <span>' + message + '</span></div>';
$('body').html(
'<div id="status" role="alert" class="statusmessage ' +
'alert alert-info hidden"><span class="glyphicon ' +
'glyphicon-info-sign" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showStatus(message);
const result = $('body').html();
return expected === result;
}
);
jsc.property(
'shows a status message (bootstrap, custom icon)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
const expected = '<div id="status" role="alert" ' +
'class="statusmessage alert alert-info"><span ' +
'class="glyphicon glyphicon-' + icon +
'" aria-hidden="true"></span> ' + message + '</div>';
'" aria-hidden="true"></span> <span>' + message + '</span></div>';
$('body').html(
'<div id="status" role="alert" class="statusmessage ' +
'alert alert-info hidden"><span class="glyphicon ' +
@@ -21,28 +60,129 @@ describe('Alert', function () {
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showStatus(message, icon);
var result = $('body').html();
const result = $('body').html();
return expected === result;
}
);
});
describe('showWarning', function () {
jsc.property(
'shows a warning message (basic)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
const expected = '<div id="errormessage">' + message + '</div>';
$('body').html(
'<div id="errormessage"></div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showWarning(message, icon);
const result = $('body').html();
return expected === result;
}
);
jsc.property(
'shows a warning message (bootstrap)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (message) {
message = message.join('');
const expected = '<div id="errormessage" role="alert" ' +
'class="statusmessage alert alert-danger"><span ' +
'class="glyphicon glyphicon-warning-sign" ' +
'aria-hidden="true"></span> <span>' + message + '</span></div>';
$('body').html(
'<div id="errormessage" role="alert" class="statusmessage ' +
'alert alert-danger hidden"><span class="glyphicon ' +
'glyphicon-alert" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showWarning(message);
const result = $('body').html();
return expected === result;
}
);
jsc.property(
'shows a warning message (bootstrap, custom icon)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
const expected = '<div id="errormessage" role="alert" ' +
'class="statusmessage alert alert-danger"><span ' +
'class="glyphicon glyphicon-' + icon +
'" aria-hidden="true"></span> <span>' + message + '</span></div>';
$('body').html(
'<div id="errormessage" role="alert" class="statusmessage ' +
'alert alert-danger hidden"><span class="glyphicon ' +
'glyphicon-alert" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showWarning(message, icon);
const result = $('body').html();
return expected === result;
}
);
});
describe('showError', function () {
before(function () {
cleanup();
});
jsc.property(
'shows an error message',
'shows an error message (basic)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
var expected = '<div id="errormessage" role="alert" ' +
const expected = '<div id="errormessage">' + message + '</div>';
$('body').html(
'<div id="errormessage"></div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showError(message, icon);
const result = $('body').html();
return expected === result;
}
);
jsc.property(
'shows an error message (bootstrap)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (icon, message) {
message = message.join('');
const expected = '<div id="errormessage" role="alert" ' +
'class="statusmessage alert alert-danger"><span ' +
'class="glyphicon glyphicon-alert" ' +
'aria-hidden="true"></span> <span>' + message + '</span></div>';
$('body').html(
'<div id="errormessage" role="alert" class="statusmessage ' +
'alert alert-danger hidden"><span class="glyphicon ' +
'glyphicon-alert" aria-hidden="true"></span> </div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showError(message);
const result = $('body').html();
return expected === result;
}
);
jsc.property(
'shows an error message (bootstrap, custom icon)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (icon, message) {
icon = icon.join('');
message = message.join('');
const expected = '<div id="errormessage" role="alert" ' +
'class="statusmessage alert alert-danger"><span ' +
'class="glyphicon glyphicon-' + icon +
'" aria-hidden="true"></span> ' + message + '</div>';
'" aria-hidden="true"></span> <span>' + message + '</span></div>';
$('body').html(
'<div id="errormessage" role="alert" class="statusmessage ' +
'alert alert-danger hidden"><span class="glyphicon ' +
@@ -50,29 +190,44 @@ describe('Alert', function () {
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showError(message, icon);
var result = $('body').html();
const result = $('body').html();
return expected === result;
}
);
});
describe('showRemaining', function () {
before(function () {
cleanup();
});
jsc.property(
'shows remaining time',
'shows remaining time (basic)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
'integer',
function (message, string, number) {
message = message.join('');
string = string.join('');
var expected = '<div id="remainingtime" role="alert" ' +
const expected = '<div id="remainingtime" class="">' + string + message + number + '</div>';
$('body').html(
'<div id="remainingtime" class="hidden"></div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showRemaining(['%s' + message + '%d', string, number]);
const result = $('body').html();
return expected === result;
}
);
jsc.property(
'shows remaining time (bootstrap)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
'integer',
function (message, string, number) {
message = message.join('');
string = string.join('');
const expected = '<div id="remainingtime" role="alert" ' +
'class="alert alert-info"><span ' +
'class="glyphicon glyphicon-fire" aria-hidden="true">' +
'</span> ' + string + message + number + '</div>';
'</span> <span>' + string + message + number + '</span></div>';
$('body').html(
'<div id="remainingtime" role="alert" class="hidden ' +
'alert alert-info"><span class="glyphicon ' +
@@ -80,32 +235,50 @@ describe('Alert', function () {
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showRemaining(['%s' + message + '%d', string, number]);
var result = $('body').html();
const result = $('body').html();
return expected === result;
}
);
});
describe('showLoading', function () {
before(function () {
cleanup();
});
jsc.property(
'shows a loading message',
'shows a loading message (basic)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (message, icon) {
message = message.join('');
icon = icon.join('');
var defaultMessage = 'Loading…';
const defaultMessage = 'Loading…';
if (message.length === 0) {
message = defaultMessage;
}
var expected = '<ul class="nav navbar-nav"><li ' +
const expected = '<div id="loadingindicator" class="">' + message + '</div>';
$('body').html(
'<div id="loadingindicator" class="hidden">' + defaultMessage + '</div>'
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showLoading(message, icon);
const result = $('body').html();
return expected === result;
}
);
jsc.property(
'shows a loading message (bootstrap)',
jsc.array(common.jscAlnumString()),
jsc.array(common.jscAlnumString()),
function (message, icon) {
message = message.join('');
icon = icon.join('');
const defaultMessage = 'Loading…';
if (message.length === 0) {
message = defaultMessage;
}
const expected = '<ul class="nav navbar-nav"><li ' +
'id="loadingindicator" class="navbar-text"><span ' +
'class="glyphicon glyphicon-' + icon +
'" aria-hidden="true"></span> ' + message + '</li></ul>';
'" aria-hidden="true"></span> <span>' + message + '</span></li></ul>';
$('body').html(
'<ul class="nav navbar-nav"><li id="loadingindicator" ' +
'class="navbar-text hidden"><span class="glyphicon ' +
@@ -114,17 +287,13 @@ describe('Alert', function () {
);
$.PrivateBin.Alert.init();
$.PrivateBin.Alert.showLoading(message, icon);
var result = $('body').html();
const result = $('body').html();
return expected === result;
}
);
});
describe('hideLoading', function () {
before(function () {
cleanup();
});
it(
'hides the loading message',
function() {
@@ -146,10 +315,6 @@ describe('Alert', function () {
});
describe('hideMessages', function () {
before(function () {
cleanup();
});
it(
'hides all messages',
function() {
@@ -172,17 +337,13 @@ describe('Alert', function () {
});
describe('setCustomHandler', function () {
before(function () {
cleanup();
});
jsc.property(
'calls a given handler function',
'nat 3',
jsc.array(common.jscAlnumString()),
function (trigger, message) {
message = message.join('');
var handlerCalled = false,
let handlerCalled = false,
defaultMessage = 'Loading…',
functions = [
$.PrivateBin.Alert.showStatus,

View File

@@ -4,9 +4,6 @@ var common = require('../common');
describe('AttachmentViewer', function () {
describe('setAttachment, showAttachment, removeAttachment, hideAttachment, hideAttachmentPreview, hasAttachment, getAttachment & moveAttachmentTo', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'displays & hides data as requested',
@@ -16,7 +13,7 @@ describe('AttachmentViewer', function () {
'string',
'string',
function (mimeType, rawdata, filename, prefix, postfix) {
var clean = jsdom(),
let clean = jsdom(),
data = 'data:' + mimeType + ';base64,' + btoa(rawdata),
previewSupported = (
mimeType.substring(0, 6) === 'image/' ||
@@ -24,7 +21,8 @@ describe('AttachmentViewer', function () {
mimeType.substring(0, 6) === 'video/' ||
mimeType.match(/\/pdf/i)
),
results = [];
results = [],
result = '';
prefix = prefix.replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%');
$('body').html(
@@ -57,7 +55,7 @@ describe('AttachmentViewer', function () {
}
// beyond this point we will get the blob URL instead of the data
data = window.URL.createObjectURL(data);
var attachment = $.PrivateBin.AttachmentViewer.getAttachment();
const attachment = $.PrivateBin.AttachmentViewer.getAttachment();
results.push(
$.PrivateBin.AttachmentViewer.hasAttachment() &&
$('#attachment').hasClass('hidden') &&
@@ -84,13 +82,24 @@ describe('AttachmentViewer', function () {
!$('#attachment').hasClass('hidden') &&
(previewSupported ? !$('#attachmentPreview').hasClass('hidden') : $('#attachmentPreview').hasClass('hidden'))
);
var element = $('<div></div>');
let element = $('<div>');
$.PrivateBin.AttachmentViewer.moveAttachmentTo(element, prefix + '%s' + postfix);
// messageIDs with links get a relaxed treatment
if (prefix.indexOf('<a') === -1 && postfix.indexOf('<a') === -1) {
result = $('<textarea>').text((prefix + filename + postfix)).text();
} else {
result = DOMPurify.sanitize(
prefix + $.PrivateBin.Helper.htmlEntities(filename) + postfix, {
ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
}
);
}
if (filename.length) {
results.push(
element.children()[0].href === data &&
element.children()[0].getAttribute('download') === filename &&
element.children()[0].text === prefix + filename + postfix
element.children()[0].text === result
);
} else {
results.push(element.children()[0].href === data);

80
js/test/Check.js Normal file
View File

@@ -0,0 +1,80 @@
'use strict';
var common = require('../common');
/* global Legacy, WebCrypto */
describe('Check', function () {
describe('init', function () {
this.timeout(30000);
it('returns false and shows error, if a bot UA is detected', function () {
jsc.assert(jsc.forall(
'string',
jsc.elements(['Bot', 'bot']),
'string',
function (prefix, botBit, suffix) {
const clean = jsdom(
'<html><body><div id="errormessage" class="hidden"></div>' +
'</body></html>', {
'userAgent': prefix + botBit + suffix
}
);
Legacy.Check.init();
const result1 = Legacy.Check.getInit() && !Legacy.Check.getStatus(),
result2 = (document.getElementById('errormessage').className !== 'hidden');
clean();
return result1 && result2;
}
),
{tests: 10});
});
jsc.property(
'shows error, if no webcrypto is detected',
'bool',
jsc.elements(['localhost', '127.0.0.1', '[::1]', '']),
jsc.nearray(common.jscA2zString()),
jsc.elements(['.onion', '.i2p', '']),
function (secureProtocol, localhost, domain, tld) {
const isDomain = localhost === '',
isSecureContext = secureProtocol || !isDomain || tld.length > 0,
clean = jsdom(
'<html><body><div id="errormessage" class="hidden"></div>' +
'<div id="oldnotice" class="hidden"></div>' +
'<div id="insecurecontextnotice" class="hidden"></div></body></html>',
{
'url': (secureProtocol ? 'https' : 'http' ) + '://' +
(isDomain ? domain.join('') + tld : localhost) + '/'
}
);
Legacy.Check.init();
const result1 = Legacy.Check.getInit() && !Legacy.Check.getStatus(),
result2 = isSecureContext === (document.getElementById('insecurecontextnotice').className === 'hidden'),
result3 = (document.getElementById('oldnotice').className !== 'hidden');
clean();
return result1 && result2 && result3;
}
);
jsc.property(
'shows error, if HTTP only site is detected',
'bool',
jsc.nearray(common.jscA2zString()),
function (secureProtocol, domain) {
const clean = jsdom(
'<html><body><div id="httpnotice" class="hidden"></div>' +
'</body></html>',
{
'url': (secureProtocol ? 'https' : 'http' ) + '://' + domain.join('') + '/'
}
);
window.crypto = new WebCrypto();
Legacy.Check.init();
const result1 = Legacy.Check.getInit() && Legacy.Check.getStatus(),
result2 = secureProtocol === (document.getElementById('httpnotice').className === 'hidden');
clean();
return result1 && result2;
}
);
});
});

View File

@@ -18,6 +18,8 @@ describe('CryptTool', function () {
// pause to let async functions conclude
await new Promise(resolve => setTimeout(resolve, 300));
let clean = jsdom();
// ensure zlib is getting loaded
$.PrivateBin.Controller.initZ();
window.crypto = new WebCrypto();
message = message.trim();
let cipherMessage = await $.PrivateBin.CryptTool.cipher(
@@ -179,6 +181,8 @@ describe('CryptTool', function () {
let message = fs.readFileSync('test/compression-sample.txt', 'utf8'),
clean = jsdom();
window.crypto = new WebCrypto();
// ensure zlib is getting loaded
$.PrivateBin.Controller.initZ();
let cipherMessage = await $.PrivateBin.CryptTool.cipher(
'foo', 'bar', message, []
),
@@ -222,6 +226,8 @@ isWhile : interp (while expr sBody) (MemElem mem) =
conseq_or_bottom inv (interp (nth_iterate sBody n) (MemElem mem))
`;
let clean = jsdom();
// ensure zlib is getting loaded
$.PrivateBin.Controller.initZ();
window.crypto = new WebCrypto();
let cipherMessage = await $.PrivateBin.CryptTool.cipher(
key, password, message, []

View File

@@ -4,9 +4,6 @@ var common = require('../common');
describe('DiscussionViewer', function () {
describe('handleNotification, prepareNewDiscussion, addComment, finishDiscussion, getReplyMessage, getReplyNickname, getReplyCommentId & highlightComment', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'displays & hides comments as requested',

View File

@@ -4,9 +4,6 @@ require('../common');
describe('Editor', function () {
describe('show, hide, getText, setText & isPreview', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'returns text fed into the textarea, handles editor tabs',

View File

@@ -3,10 +3,6 @@ var common = require('../common');
describe('Helper', function () {
describe('secondsToHuman', function () {
after(function () {
cleanup();
});
jsc.property('returns an array with a number and a word', 'integer', function (number) {
var result = $.PrivateBin.Helper.secondsToHuman(number);
return Array.isArray(result) &&
@@ -57,11 +53,11 @@ describe('Helper', function () {
'nearray string',
function (ids, contents) {
var html = '',
result = true;
result = true,
clean = jsdom(html);
ids.forEach(function(item, i) {
html += '<div id="' + item.join('') + '">' + common.htmlEntities(contents[i] || contents[0]) + '</div>';
html += '<div id="' + item.join('') + '">' + $.PrivateBin.Helper.htmlEntities(contents[i] || contents[0]) + '</div>';
});
var clean = jsdom(html);
// TODO: As per https://github.com/tmpvar/jsdom/issues/321 there is no getSelection in jsdom, yet.
// Once there is one, uncomment the block below to actually check the result.
/*
@@ -77,15 +73,23 @@ describe('Helper', function () {
});
describe('urls2links', function () {
after(function () {
cleanup();
before(function () {
cleanup = jsdom();
});
jsc.property(
'ignores non-URL content',
'string',
function (content) {
return content === $.PrivateBin.Helper.urls2links(content);
content = content.replace(/\r/g, '\n').replace(/\u0000/g, '');
let clean = jsdom();
$('body').html('<div id="foo"></div>');
let e = $('#foo');
e.text(content);
$.PrivateBin.Helper.urls2links(e);
let result = e.text();
clean();
return content === result;
}
);
jsc.property(
@@ -97,11 +101,14 @@ describe('Helper', function () {
jsc.array(common.jscHashString()),
'string',
function (prefix, schema, address, query, fragment, postfix) {
var query = query.join(''),
fragment = fragment.join(''),
url = schema + '://' + address.join('') + '/?' + query + '#' + fragment,
prefix = common.htmlEntities(prefix),
postfix = ' ' + common.htmlEntities(postfix);
query = query.join('');
fragment = fragment.join('');
prefix = prefix.replace(/\r/g, '\n').replace(/\u0000/g, '');
postfix = ' ' + postfix.replace(/\r/g, '\n').replace(/\u0000/g, '');
let url = schema + '://' + address.join('') + '/?' + query + '#' + fragment,
clean = jsdom();
$('body').html('<div id="foo"></div>');
let e = $('#foo');
// special cases: When the query string and fragment imply the beginning of an HTML entity, eg. &#0 or &#x
if (
@@ -112,8 +119,12 @@ describe('Helper', function () {
url = schema + '://' + address.join('') + '/?' + query.substring(0, query.length - 1);
postfix = '';
}
return prefix + '<a href="' + url + '" rel="nofollow">' + url + '</a>' + postfix === $.PrivateBin.Helper.urls2links(prefix + url + postfix);
e.text(prefix + url + postfix);
$.PrivateBin.Helper.urls2links(e);
let result = e.html();
clean();
url = $('<div />').text(url).html();
return $('<div />').text(prefix).html() + '<a href="' + url + '" rel="nofollow">' + url + '</a>' + $('<div />').text(postfix).html() === result;
}
);
jsc.property(
@@ -122,19 +133,23 @@ describe('Helper', function () {
jsc.array(common.jscQueryString()),
'string',
function (prefix, query, postfix) {
var url = 'magnet:?' + query.join('').replace(/^&+|&+$/gm,''),
prefix = common.htmlEntities(prefix),
postfix = common.htmlEntities(postfix);
return prefix + '<a href="' + url + '" rel="nofollow">' + url + '</a> ' + postfix === $.PrivateBin.Helper.urls2links(prefix + url + ' ' + postfix);
prefix = prefix.replace(/\r/g, '\n').replace(/\u0000/g, '');
postfix = ' ' + postfix.replace(/\r/g, '\n').replace(/\u0000/g, '');
let url = 'magnet:?' + query.join('').replace(/^&+|&+$/gm,''),
clean = jsdom();
$('body').html('<div id="foo"></div>');
let e = $('#foo');
e.text(prefix + url + postfix);
$.PrivateBin.Helper.urls2links(e);
let result = e.html();
clean();
url = $('<div />').text(url).html();
return $('<div />').text(prefix).html() + '<a href="' + url + '" rel="nofollow">' + url + '</a>' + $('<div />').text(postfix).html() === result;
}
);
});
describe('sprintf', function () {
after(function () {
cleanup();
});
jsc.property(
'replaces %s in strings with first given parameter',
'string',
@@ -183,9 +198,9 @@ describe('Helper', function () {
'string',
'string',
function (prefix, uint, middle, string, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%');
middle = middle.replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%');
prefix = prefix.replace(/%(s|d)/g, '');
middle = middle.replace(/%(s|d)/g, '');
postfix = postfix.replace(/%(s|d)/g, '');
var params = [prefix + '%d' + middle + '%s' + postfix, uint, string],
result = prefix + uint + middle + string + postfix;
return result === $.PrivateBin.Helper.sprintf.apply(this, params);
@@ -199,9 +214,9 @@ describe('Helper', function () {
'string',
'string',
function (prefix, uint, middle, string, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%');
middle = middle.replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%');
prefix = prefix.replace(/%(s|d)/g, '');
middle = middle.replace(/%(s|d)/g, '');
postfix = postfix.replace(/%(s|d)/g, '');
var params = [prefix + '%s' + middle + '%d' + postfix, string, uint],
result = prefix + string + middle + uint + postfix;
return result === $.PrivateBin.Helper.sprintf.apply(this, params);
@@ -211,7 +226,7 @@ describe('Helper', function () {
describe('getCookie', function () {
this.timeout(30000);
after(function () {
before(function () {
cleanup();
});
@@ -263,16 +278,16 @@ describe('Helper', function () {
});
describe('htmlEntities', function () {
after(function () {
cleanup();
before(function () {
cleanup = jsdom();
});
jsc.property(
'removes all HTML entities from any given string',
'string',
function (string) {
var result = common.htmlEntities(string);
return !(/[<>"'`=\/]/.test(result)) && !(string.indexOf('&') > -1 && !(/&amp;/.test(result)));
var result = $.PrivateBin.Helper.htmlEntities(string);
return !(/[<>]/.test(result)) && !(string.indexOf('&') > -1 && !(/&amp;/.test(result)));
}
);
});

View File

@@ -3,6 +3,7 @@ var common = require('../common');
describe('I18n', function () {
describe('translate', function () {
this.timeout(30000);
before(function () {
$.PrivateBin.I18n.reset();
});
@@ -32,13 +33,41 @@ describe('I18n', function () {
var fakeAlias = $.PrivateBin.I18n._(fake);
$.PrivateBin.I18n.reset();
if (messageId.indexOf('<a') === -1) {
messageId = $.PrivateBin.Helper.htmlEntities(messageId);
} else {
messageId = DOMPurify.sanitize(
messageId, {
ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
}
);
}
return messageId === result && messageId === alias &&
messageId === pluralResult && messageId === pluralAlias &&
messageId === fakeResult && messageId === fakeAlias;
}
);
jsc.property(
'replaces %s in strings with first given parameter',
'replaces %s in strings with first given parameter, encoding all, when no link is in the messageID',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
const translation = $.PrivateBin.Helper.htmlEntities(prefix + params[0] + postfix);
params.unshift(prefix + '%s' + postfix);
const result = $.PrivateBin.I18n.translate.apply(this, params);
$.PrivateBin.I18n.reset();
const alias = $.PrivateBin.I18n._.apply(this, params);
$.PrivateBin.I18n.reset();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter, encoding params only, when a link is part of the messageID',
'string',
'(small nearray) string',
'string',
@@ -46,15 +75,83 @@ describe('I18n', function () {
prefix = prefix.replace(/%(s|d)/g, '%%');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%');
var translation = prefix + params[0] + postfix;
params.unshift(prefix + '%s' + postfix);
var result = $.PrivateBin.I18n.translate.apply(this, params);
const translation = DOMPurify.sanitize(
prefix + '<a href="' + params[0] + '"></a>' + postfix, {
ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
}
);
params.unshift(prefix + '<a href="%s"></a>' + postfix);
const result = $.PrivateBin.I18n.translate.apply(this, params);
$.PrivateBin.I18n.reset();
var alias = $.PrivateBin.I18n._.apply(this, params);
const alias = $.PrivateBin.I18n._.apply(this, params);
$.PrivateBin.I18n.reset();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter into an element, encoding all, when no link is in the messageID',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
params[0] = params[0].replace(/%(s|d)/g, '%%');
postfix = postfix.replace(/%(s|d)/g, '%%').replace(/<a/g, '');
const translation = $('<textarea>').text((prefix + params[0] + postfix)).text();
let args = Array.prototype.slice.call(params);
args.unshift(prefix + '%s' + postfix);
let clean = jsdom();
$('body').html('<div id="i18n"></div>');
args.unshift($('#i18n'));
$.PrivateBin.I18n.translate.apply(this, args);
const result = $('#i18n').text();
$.PrivateBin.I18n.reset();
clean();
clean = jsdom();
$('body').html('<div id="i18n"></div>');
args[0] = $('#i18n');
$.PrivateBin.I18n._.apply(this, args);
const alias = $('#i18n').text();
$.PrivateBin.I18n.reset();
clean();
return translation === result && translation === alias;
}
);
jsc.property(
'replaces %s in strings with first given parameter into an element, encoding params only, when a link is part of the messageID inserted',
'string',
'(small nearray) string',
'string',
function (prefix, params, postfix) {
prefix = prefix.replace(/%(s|d)/g, '%%').trim();
params[0] = params[0].replace(/%(s|d)/g, '%%').trim();
postfix = postfix.replace(/%(s|d)/g, '%%').trim();
const translation = DOMPurify.sanitize(
prefix + '<a href="' + params[0] + '"></a>' + postfix, {
ALLOWED_TAGS: ['a', 'i', 'span'],
ALLOWED_ATTR: ['href', 'id']
}
);
let args = Array.prototype.slice.call(params);
args.unshift(prefix + '<a href="%s"></a>' + postfix);
let clean = jsdom();
$('body').html('<div id="i18n"></div>');
args.unshift($('#i18n'));
$.PrivateBin.I18n.translate.apply(this, args);
const result = $('#i18n').html();
$.PrivateBin.I18n.reset();
clean();
clean = jsdom();
$('body').html('<div id="i18n"></div>');
args[0] = $('#i18n');
$.PrivateBin.I18n._.apply(this, args);
const alias = $('#i18n').html();
$.PrivateBin.I18n.reset();
clean();
return translation === result && translation === alias;
}
);
});
describe('getPluralForm', function () {

View File

@@ -1,88 +0,0 @@
'use strict';
var common = require('../common');
describe('InitialCheck', function () {
describe('init', function () {
this.timeout(30000);
before(function () {
cleanup();
});
it('returns false and shows error, if a bot UA is detected', function () {
jsc.assert(jsc.forall(
'string',
jsc.elements(['Bot', 'bot']),
'string',
function (prefix, botBit, suffix) {
const clean = jsdom('', {
'userAgent': prefix + botBit + suffix
});
$('body').html(
'<html><body><div id="errormessage" class="hidden"></div>' +
'</body></html>'
);
$.PrivateBin.Alert.init();
window.crypto = null;
const result1 = !$.PrivateBin.InitialCheck.init(),
result2 = !$('#errormessage').hasClass('hidden');
clean();
return result1 && result2;
}
),
{tests: 10});
});
jsc.property(
'shows error, if no webcrypto is detected',
'bool',
jsc.elements(['localhost', '127.0.0.1', '[::1]', '']),
jsc.nearray(common.jscA2zString()),
jsc.elements(['.onion', '.i2p', '']),
function (secureProtocol, localhost, domain, tld) {
const isDomain = localhost === '',
isSecureContext = secureProtocol || !isDomain || tld.length > 0,
clean = jsdom('', {
'url': (secureProtocol ? 'https' : 'http' ) + '://' +
(isDomain ? domain.join('') + tld : localhost) + '/'
});
$('body').html(
'<html><body><div id="errormessage" class="hidden"></div>'+
'<div id="oldnotice" class="hidden"></div></body></html>'
);
$.PrivateBin.Alert.init();
const result1 = !$.PrivateBin.InitialCheck.init(),
result2 = isSecureContext === $('#errormessage').hasClass('hidden'),
result3 = !$('#oldnotice').hasClass('hidden');
clean();
return result1 && result2 && result3;
}
);
jsc.property(
'shows error, if HTTP only site is detected',
'bool',
jsc.elements(['localhost', '127.0.0.1', '[::1]', '']),
jsc.nearray(common.jscA2zString()),
jsc.elements(['.onion', '.i2p', '']),
function (secureProtocol, localhost, domain, tld) {
const isDomain = localhost === '',
isSecureContext = secureProtocol || !isDomain || tld.length > 0,
clean = jsdom('', {
'url': (secureProtocol ? 'https' : 'http' ) + '://' +
(isDomain ? domain.join('') + tld : localhost) + '/'
});
$('body').html(
'<html><body><div id="httpnotice" class="hidden"></div>'+
'</body></html>'
);
$.PrivateBin.Alert.init();
window.crypto = null;
const result1 = $.PrivateBin.InitialCheck.init(),
result2 = isSecureContext === $('#httpnotice').hasClass('hidden');
clean();
return result1 && result2;
}
);
});
});

View File

@@ -5,18 +5,18 @@ describe('Model', function () {
describe('getExpirationDefault', function () {
before(function () {
$.PrivateBin.Model.reset();
cleanup();
cleanup = jsdom();
});
jsc.property(
'returns the contents of the element with id "pasteExpiration"',
'array asciinestring',
'nearray asciinestring',
'string',
'small nat',
function (keys, value, key) {
keys = keys.map(common.htmlEntities);
value = common.htmlEntities(value);
var content = keys.length > key ? keys[key] : (keys.length > 0 ? keys[0] : 'null'),
keys = keys.map($.PrivateBin.Helper.htmlEntities);
value = $.PrivateBin.Helper.htmlEntities(value);
var content = keys.length > key ? keys[key] : keys[0],
contents = '<select id="pasteExpiration" name="pasteExpiration">';
keys.forEach(function(item) {
contents += '<option value="' + item + '"';
@@ -27,7 +27,7 @@ describe('Model', function () {
});
contents += '</select>';
$('body').html(contents);
var result = common.htmlEntities(
var result = $.PrivateBin.Helper.htmlEntities(
$.PrivateBin.Model.getExpirationDefault()
);
$.PrivateBin.Model.reset();
@@ -39,18 +39,20 @@ describe('Model', function () {
describe('getFormatDefault', function () {
before(function () {
$.PrivateBin.Model.reset();
});
after(function () {
cleanup();
});
jsc.property(
'returns the contents of the element with id "pasteFormatter"',
'array asciinestring',
'nearray asciinestring',
'string',
'small nat',
function (keys, value, key) {
keys = keys.map(common.htmlEntities);
value = common.htmlEntities(value);
var content = keys.length > key ? keys[key] : (keys.length > 0 ? keys[0] : 'null'),
keys = keys.map($.PrivateBin.Helper.htmlEntities);
value = $.PrivateBin.Helper.htmlEntities(value);
var content = keys.length > key ? keys[key] : keys[0],
contents = '<select id="pasteFormatter" name="pasteFormatter">';
keys.forEach(function(item) {
contents += '<option value="' + item + '"';
@@ -61,7 +63,7 @@ describe('Model', function () {
});
contents += '</select>';
$('body').html(contents);
var result = common.htmlEntities(
var result = $.PrivateBin.Helper.htmlEntities(
$.PrivateBin.Model.getFormatDefault()
);
$.PrivateBin.Model.reset();
@@ -74,7 +76,6 @@ describe('Model', function () {
this.timeout(30000);
beforeEach(function () {
$.PrivateBin.Model.reset();
cleanup();
});
jsc.property(
@@ -130,7 +131,6 @@ describe('Model', function () {
this.timeout(30000);
beforeEach(function () {
$.PrivateBin.Model.reset();
cleanup();
});
jsc.property(
@@ -238,7 +238,6 @@ describe('Model', function () {
describe('getTemplate', function () {
beforeEach(function () {
$.PrivateBin.Model.reset();
cleanup();
});
jsc.property(

View File

@@ -36,9 +36,6 @@ describe('PasteStatus', function () {
describe('showRemainingTime', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'shows burn after reading message or remaining time v1',
@@ -121,10 +118,6 @@ describe('PasteStatus', function () {
});
describe('hideMessages', function () {
before(function () {
cleanup();
});
it(
'hides all messages',
function() {

View File

@@ -4,9 +4,6 @@ var common = require('../common');
describe('PasteViewer', function () {
describe('run, hide, getText, setText, getFormat, setFormat & isPrettyPrinted', function () {
this.timeout(30000);
before(function () {
cleanup();
});
jsc.property(
'displays text according to format',

View File

@@ -6,10 +6,6 @@ describe('Prompt', function () {
// in nodejs -> replace the prompt in the "page" template with a modal
describe('requestPassword & getPassword', function () {
this.timeout(30000);
before(function () {
$.PrivateBin.Model.reset();
cleanup();
});
jsc.property(
'returns the password fed into the dialog',
@@ -26,6 +22,7 @@ describe('Prompt', function () {
'password"></div><button type="submit">Decrypt</button>' +
'</form></div></div></div></div>'
);
$.PrivateBin.Model.reset();
$.PrivateBin.Model.init();
$.PrivateBin.Prompt.init();
$.PrivateBin.Prompt.requestPassword();

View File

@@ -326,7 +326,7 @@ describe('TopNav', function () {
'returns the currently selected expiration date',
function () {
$.PrivateBin.TopNav.init();
assert.ok($.PrivateBin.TopNav.getExpiration() === '1week');
assert.ok($.PrivateBin.TopNav.getExpiration() === null);
}
);
});

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;
@@ -45,7 +45,7 @@ class Configuration
'burnafterreadingselected' => false,
'defaultformatter' => 'plaintext',
'syntaxhighlightingtheme' => null,
'sizelimit' => 2097152,
'sizelimit' => 10485760,
'template' => 'bootstrap',
'notice' => '',
'languageselection' => false,
@@ -53,7 +53,7 @@ class Configuration
'urlshortener' => '',
'qrcode' => true,
'icon' => 'identicon',
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src *; script-src \'self\' \'unsafe-eval\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals',
'cspheader' => 'default-src \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'unsafe-eval\'; style-src \'self\'; font-src \'self\'; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-popups allow-modals',
'zerobincompatibility' => false,
'httpwarning' => true,
'compression' => 'zlib',
@@ -102,8 +102,9 @@ class Configuration
public function __construct()
{
$config = array();
$configFile = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php';
$configIni = PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini';
$basePath = (getenv('CONFIG_PATH') !== false ? getenv('CONFIG_PATH') : PATH . 'cfg') . DIRECTORY_SEPARATOR;
$configIni = $basePath . 'conf.ini';
$configFile = $basePath . 'conf.php';
// rename INI files to avoid configuration leakage
if (is_readable($configIni)) {
@@ -112,7 +113,7 @@ class Configuration
// cleanup sample, too
$configIniSample = $configIni . '.sample';
if (is_readable($configIniSample)) {
DataStore::prependRename($configIniSample, PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.sample.php', ';');
DataStore::prependRename($configIniSample, $basePath . 'conf.sample.php', ';');
}
}

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;
@@ -28,14 +28,14 @@ class Controller
*
* @const string
*/
const VERSION = '1.3';
const VERSION = '1.3.4';
/**
* minimal required PHP version
*
* @const string
*/
const MIN_PHP_VERSION = '5.5.0';
const MIN_PHP_VERSION = '5.6.0';
/**
* show the same error message if the paste expired or does not exist
@@ -276,9 +276,7 @@ class Controller
// accessing this method ensures that the paste would be
// deleted if it has already expired
$paste->get();
if (
Filter::slowEquals($deletetoken, $paste->getDeleteToken())
) {
if (hash_equals($paste->getDeleteToken(), $deletetoken)) {
// Paste exists and deletion token is valid: Delete the paste.
$paste->delete();
$this->_status = 'Paste was properly deleted.';
@@ -388,6 +386,7 @@ class Controller
$page->assign('URLSHORTENER', $this->_conf->getKey('urlshortener'));
$page->assign('QRCODE', $this->_conf->getKey('qrcode'));
$page->assign('HTTPWARNING', $this->_conf->getKey('httpwarning'));
$page->assign('HTTPSLINK', 'https://' . $this->_request->getHost() . $this->_request->getRequestUri());
$page->assign('COMPRESSION', $this->_conf->getKey('compression'));
$page->draw($this->_conf->getKey('template'));
}

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Data;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Data;
@@ -597,6 +597,8 @@ class Database extends AbstractData
/**
* get the data type, depending on the database driver
*
* PostgreSQL uses a different API for BLOBs then SQL, hence we use TEXT
*
* @access private
* @static
* @return string
@@ -609,6 +611,8 @@ class Database extends AbstractData
/**
* get the attachment type, depending on the database driver
*
* PostgreSQL uses a different API for BLOBs then SQL, hence we use TEXT
*
* @access private
* @static
* @return string
@@ -628,16 +632,17 @@ class Database extends AbstractData
{
list($main_key, $after_key) = self::_getPrimaryKeyClauses();
$dataType = self::_getDataType();
$attachmentType = self::_getAttachmentType();
self::$_db->exec(
'CREATE TABLE ' . self::_sanitizeIdentifier('paste') . ' ( ' .
"dataid CHAR(16) NOT NULL$main_key, " .
"data $dataType, " .
"data $attachmentType, " .
'postdate INT, ' .
'expiredate INT, ' .
'opendiscussion INT, ' .
'burnafterreading INT, ' .
'meta TEXT, ' .
'attachment ' . self::_getAttachmentType() . ', ' .
"attachment $attachmentType, " .
"attachmentname $dataType$after_key );"
);
}
@@ -711,6 +716,7 @@ class Database extends AbstractData
private static function _upgradeDatabase($oldversion)
{
$dataType = self::_getDataType();
$attachmentType = self::_getAttachmentType();
switch ($oldversion) {
case '0.21':
// create the meta column if necessary (pre 0.21 change)
@@ -722,7 +728,7 @@ class Database extends AbstractData
// SQLite only allows one ALTER statement at a time...
self::$_db->exec(
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') .
' ADD COLUMN attachment ' . self::_getAttachmentType() . ';'
" ADD COLUMN attachment $attachmentType;"
);
self::$_db->exec(
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') . " ADD COLUMN attachmentname $dataType;"
@@ -732,7 +738,7 @@ class Database extends AbstractData
if (self::$_type !== 'sqlite') {
self::$_db->exec(
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') .
' ADD PRIMARY KEY (dataid), MODIFY COLUMN data $dataType;'
" ADD PRIMARY KEY (dataid), MODIFY COLUMN data $dataType;"
);
self::$_db->exec(
'ALTER TABLE ' . self::_sanitizeIdentifier('comment') .
@@ -754,6 +760,17 @@ class Database extends AbstractData
self::_sanitizeIdentifier('comment') . '(pasteid);'
);
// no break, continue with updates for 0.22 and later
case '1.3':
// SQLite doesn't support MODIFY, but it allows TEXT of similar
// size as BLOB and PostgreSQL uses TEXT, so there is no need
// to change it there
if (self::$_type !== 'sqlite' && self::$_type !== 'pgsql') {
self::$_db->exec(
'ALTER TABLE ' . self::_sanitizeIdentifier('paste') .
" MODIFY COLUMN data $attachmentType;"
);
}
// no break, continue with updates for all newer versions
default:
self::_exec(
'UPDATE ' . self::_sanitizeIdentifier('config') .

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Data;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;
@@ -68,23 +68,4 @@ class Filter
}
return number_format($size, ($i ? 2 : 0), '.', ' ') . ' ' . I18n::_($iec[$i]);
}
/**
* fixed time string comparison operation to prevent timing attacks
* https://crackstation.net/hashing-security.htm?=rd#slowequals
*
* @access public
* @static
* @param string $a
* @param string $b
* @return bool
*/
public static function slowEquals($a, $b)
{
$diff = strlen($a) ^ strlen($b);
for ($i = 0; $i < strlen($a) && $i < strlen($b); ++$i) {
$diff |= ord($a[$i]) ^ ord($b[$i]);
}
return $diff === 0;
}
}

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;
@@ -125,9 +125,31 @@ class I18n
} else {
$args[0] = self::$_translations[$messageId];
}
// encode any non-integer arguments and the message ID, if it doesn't contain a link
$argsCount = count($args);
if ($argsCount > 1) {
for ($i = 0; $i < $argsCount; ++$i) {
if (($i > 0 && !is_int($args[$i])) || strpos($args[0], '<a') === false) {
$args[$i] = self::encode($args[$i]);
}
}
}
return call_user_func_array('sprintf', $args);
}
/**
* encode HTML entities for output into an HTML5 document
*
* @access public
* @static
* @param string $string
* @return string
*/
public static function encode($string)
{
return htmlspecialchars($string, ENT_QUOTES | ENT_HTML5 | ENT_DISALLOWED, 'UTF-8', false);
}
/**
* loads translations
*
@@ -303,10 +325,11 @@ class I18n
case 'pl':
return $n == 1 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
case 'ru':
case 'uk':
return $n % 10 == 1 && $n % 100 != 11 ? 0 : ($n % 10 >= 2 && $n % 10 <= 4 && ($n % 100 < 10 || $n % 100 >= 20) ? 1 : 2);
case 'sl':
return $n % 100 == 1 ? 1 : ($n % 100 == 2 ? 2 : ($n % 100 == 3 || $n % 100 == 4 ? 3 : 0));
// de, en, es, hu, it, nl, no, pt
// bg, de, en, es, hu, it, nl, no, pt
default:
return $n != 1 ? 1 : 0;
}

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Model;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Model;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Model;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.1
* @version 1.3.4
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin\Persistence;

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;
@@ -193,6 +193,19 @@ class Request
$this->_params[$param] : $default;
}
/**
* Get host as requested by the client
*
* @access public
* @return string
*/
public function getHost()
{
return array_key_exists('HTTP_HOST', $_SERVER) ?
htmlspecialchars($_SERVER['HTTP_HOST']) :
'localhost';
}
/**
* Get request URI
*

View File

@@ -7,7 +7,7 @@
* @link https://github.com/PrivateBin/PrivateBin
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license http://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 1.3
* @version 1.3.4
*/
namespace PrivateBin;

View File

@@ -8,7 +8,7 @@
* @link http://sebsauvage.net/wiki/doku.php?id=php:vizhash_gd
* @copyright 2012 Sébastien SAUVAGE (sebsauvage.net)
* @license https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
* @version 0.0.5 beta PrivateBin 1.3
* @version 0.0.5 beta PrivateBin 1.3.4
*/
namespace PrivateBin;

View File

@@ -5,5 +5,4 @@
# directory.
User-agent: *
Allow: /index.php
Disallow: /

View File

@@ -4,7 +4,7 @@ $isCpct = substr($template, 9, 8) === '-compact';
$isDark = substr($template, 9, 5) === '-dark';
$isPage = substr($template, -5) === '-page';
?><!DOCTYPE html>
<html>
<html lang="<?php echo I18n::_('en'); ?>">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
@@ -55,7 +55,7 @@ if ($ZEROBINCOMPATIBILITY):
endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.2.11.js" integrity="sha512-Yey/0yoaVmSbqMEyyff3DIu8kCPwpHvHf7tY1AuZ1lrX9NPCMg87PwzngMi+VNbe4ilCApmePeuKT869RTcyCQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/base-x-3.0.5.1.js" integrity="sha512-/zL3MWKMtl1IBF0URx3laql2jUw+rWfFFabNlILY/Qm+hUsQR/XULjUyNHkW/FkrV7A0sMQ7tsppH7sj5ht8wA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/base-x-3.0.7.js" integrity="sha512-/Bi1AJIP0TtxEB+Jh6Hk809H1G7vn4iJV80qagslf0+Hm0UjUi1s3qNrn1kZULjzUYuaf6ck0ndLGJ7MxWLmgQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/bootstrap-3.3.7.js" integrity="sha512-iztkobsvnjKfAtTNdHkGVjAYTrrtlC7mGp/54c40wowO7LhURYl3gVzzcEqGl/qKXQltJ2HwMrdLcNUdo+N/RQ==" crossorigin="anonymous"></script>
<?php
@@ -66,15 +66,13 @@ if ($SYNTAXHIGHLIGHTING):
endif;
if ($MARKDOWN):
?>
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.0.js" integrity="sha512-Kv8oAge9h2QmRyzb52jUomyXAvSMrpE9kWF3QRMFajo1a/TXjtY8u71vUA6t4+LE7huz4TSVH8VLJBEmcZiPRA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.1.js" integrity="sha512-nRri7kqh3iRLdHbhtjfe8w9eAQPmt+ubH5U88UZyKbz6O9Q0q4haaXF0krOUclKmRJou/kKZYulgBHvHXPqOvg==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.11.js" integrity="sha512-p7UyJuyBkhMcMgE4mDsgK0Lz70OvetLefua1oXs1OujWv9gOxh4xy8InFux7bZ4/DAZsTmO4rgVwZW9BHKaTaw==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-dNBKGlXagUZhkKcI+HhEH0otOswA5g2QnJV8BxYxNK/piW9jJWZvADCbzDJNRjt6A6QgMwBM8+lH7K3lgsOuQw==" crossorigin="anonymous"></script>
<!--[if IE]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;}</style>
<![endif]-->
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.8.js" integrity="sha512-QwcEKGuEmKtMguCO9pqNtUtZqq9b/tJ8gNr5qhY8hykq3zKTlDOvpZAmf6Rs8yH35Bz1ZdctUjj2qEWxT5aXCg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-+4ay2Dw/9w/DOTutdpoiHvF6RxqV0V8ABSXHlebjGbQ7Td+3If7mOZ5OIu/lWCifcgP6vyhJuiB8+jl8FGtuwg==" crossorigin="anonymous"></script>
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
@@ -120,13 +118,41 @@ if ($QRCODE):
<div class="modal-body">
<div class="mx-auto" id="qrcode-display"></div>
</div>
<div class="row">
<div class="btn-group col-xs-12">
<span class="col-xs-12">
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal"><?php echo I18n::_('Close') ?></button>
</span>
</div>
</div>
</div>
</div>
</div>
<?php
endif;
?>
<div id="emailconfirmmodal" tabindex="-1" class="modal fade" aria-labelledby="emailconfirmmodalTitle" role="dialog" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-body">
<div id="emailconfirm-display"></div>
</div>
<div class="row">
<div class="btn-group col-xs-12" data-toggle="buttons">
<span class="col-xs-12 col-md-4">
<button id="emailconfirm-timezone-current" type="button" class="btn btn-danger btn-block" data-dismiss="modal"><?php echo I18n::_('Use Current Timezone') ?></button>
</span>
<span class="col-xs-12 col-md-4">
<button id="emailconfirm-timezone-utc" type="button" class="btn btn-default btn-block" data-dismiss="modal"><?php echo I18n::_('Convert To UTC') ?></button>
</span>
<span class="col-xs-12 col-md-4">
<button type="button" class="btn btn-primary btn-block" data-dismiss="modal"><?php echo I18n::_('Close') ?></button>
</span>
</div>
</div>
</div>
</div>
</div>
<nav class="navbar navbar-<?php echo $isDark ? 'inverse' : 'default'; ?> navbar-<?php echo $isCpct ? 'fixed' : 'static'; ?>-top"><?php
if ($isCpct):
?><div class="container"><?php
@@ -173,6 +199,9 @@ endif;
<button id="rawtextbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
<span class="glyphicon glyphicon-text-background" aria-hidden="true"></span> <?php echo I18n::_('Raw text'), PHP_EOL; ?>
</button>
<button id="emaillink" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
<span class="glyphicon glyphicon-envelope" aria-hidden="true"></span> <?php echo I18n::_('Email'), PHP_EOL; ?>
</button>
<?php
if ($QRCODE):
?>
@@ -397,20 +426,6 @@ if (strlen($LANGUAGESELECTION)):
<?php
endif;
?>
<li>
<?php
if ($isPage):
?>
<button id="newbutton" type="button" class="reloadlink hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?> navbar-btn">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL;
else:
?>
<button id="sendbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> navbar-btn">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL;
endif;
?>
</button>
</li>
</ul>
</div>
<?php
@@ -425,7 +440,7 @@ if (strlen($NOTICE)):
?>
<div role="alert" class="alert alert-info">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
<?php echo htmlspecialchars($NOTICE), PHP_EOL; ?>
<?php echo I18n::encode($NOTICE), PHP_EOL; ?>
</div>
<?php
endif;
@@ -445,28 +460,25 @@ endif;
?>
<div id="status" role="alert" class="alert alert-info<?php echo empty($STATUS) ? ' hidden' : '' ?>">
<span class="glyphicon glyphicon-info-sign" aria-hidden="true"></span>
<?php echo htmlspecialchars($STATUS), PHP_EOL; ?>
<?php echo I18n::encode($STATUS), PHP_EOL; ?>
</div>
<div id="errormessage" role="alert" class="<?php echo empty($ERROR) ? 'hidden' : '' ?> alert alert-danger">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<?php echo htmlspecialchars($ERROR), PHP_EOL; ?>
<?php echo I18n::encode($ERROR), PHP_EOL; ?>
</div>
<noscript>
<div id="noscript" role="alert" class="alert alert-<?php echo $isDark ? 'error' : 'warning'; ?>">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)), PHP_EOL; ?>
<?php echo I18n::_('JavaScript is required for %s to work. Sorry for the inconvenience.', I18n::_($NAME)), PHP_EOL; ?>
</div>
</noscript>
<div id="oldnotice" role="alert" class="hidden alert alert-danger">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?>
</div>
<div id="ienotice" role="alert" class="hidden alert alert-danger">
<span class="glyphicon glyphicon-question-sign" aria-hidden="true"></span>
<?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
<a href="https://www.mozilla.org/firefox/">Firefox</a>,
<a href="https://www.opera.com/">Opera</a>,
<a href="https://www.google.com/chrome">Chrome</a>…
<a href="https://www.google.com/chrome">Chrome</a>…<br />
<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-the-error-privatebin-requires-a-modern-browser-to-work'); ?></span>
</div>
<?php
if ($HTTPWARNING):
@@ -476,26 +488,52 @@ if ($HTTPWARNING):
<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'), PHP_EOL; ?><br />
<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection'); ?></span>
</div>
<div id="insecurecontextnotice" role="alert" class="hidden alert alert-danger">
<span class="glyphicon glyphicon-alert" aria-hidden="true"></span>
<?php echo I18n::_('Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.', $HTTPSLINK); ?>
</div>
<?php
endif;
?>
<div id="pastesuccess" role="alert" class="hidden alert alert-success">
<div id="pastesuccess" class="hidden">
<div role="alert" class="alert alert-success">
<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>
<div id="deletelink"></div>
<div id="pastelink"></div>
</div>
<?php
if (strlen($URLSHORTENER)):
?>
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?>">
<p>
<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>" type="button" class="btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?> btn-block">
<span class="glyphicon glyphicon-send" aria-hidden="true"></span> <?php echo I18n::_('Shorten URL'), PHP_EOL; ?>
</button>
</p>
<div role="alert" class="alert alert-danger">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<?php echo I18n::_('URL shortener may expose your decrypt key in URL.'), PHP_EOL; ?>
</div>
<?php
endif;
?>
</div>
<ul id="editorTabs" class="nav nav-tabs hidden">
<li role="presentation" class="active"><a id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
<li role="presentation"><a id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
<li role="presentation" class="active"><a role="tab" aria-selected="true" aria-controls="editorTabs" id="messageedit" href="#"><?php echo I18n::_('Editor'); ?></a></li>
<li role="presentation"><a role="tab" aria-selected="false" aria-controls="editorTabs" id="messagepreview" href="#"><?php echo I18n::_('Preview'); ?></a></li>
<li role="presentation" class="pull-right">
<?php
if ($isPage):
?>
<button id="newbutton" type="button" class="reloadlink hidden btn btn-<?php echo $isDark ? 'warning' : 'default'; ?>">
<span class="glyphicon glyphicon-file" aria-hidden="true"></span> <?php echo I18n::_('New'), PHP_EOL;
else:
?>
<button id="sendbutton" type="button" class="hidden btn btn-<?php echo $isDark ? 'warning' : 'primary'; ?>">
<span class="glyphicon glyphicon-upload" aria-hidden="true"></span> <?php echo I18n::_('Send'), PHP_EOL;
endif;
?>
</button>
</li>
</ul>
</section>
<section class="container">
@@ -519,7 +557,7 @@ endif;
<div id="noscript" role="alert" class="alert alert-info noscript-hide">
<span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>
<?php echo I18n::_('Loading…'); ?><br />
<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away'); ?></span>
<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-the-loading-message-not-go-away'); ?></span>
</div>
</section>
<footer class="container">
@@ -544,6 +582,13 @@ if ($DISCUSSION):
</div>
<?php
endif;
?>
<?php
if ($FILEUPLOAD):
?>
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
<?php
endif;
?>
</body>
</html>

View File

@@ -1,7 +1,7 @@
<?php
use PrivateBin\I18n;
?><!DOCTYPE html>
<html lang="en">
<html lang="<?php echo I18n::_('en'); ?>">
<head>
<meta charset="utf-8" />
<meta name="robots" content="noindex" />
@@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY):
endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/zlib-1.2.11.js" integrity="sha512-Yey/0yoaVmSbqMEyyff3DIu8kCPwpHvHf7tY1AuZ1lrX9NPCMg87PwzngMi+VNbe4ilCApmePeuKT869RTcyCQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/base-x-3.0.5.1.js" integrity="sha512-/zL3MWKMtl1IBF0URx3laql2jUw+rWfFFabNlILY/Qm+hUsQR/XULjUyNHkW/FkrV7A0sMQ7tsppH7sj5ht8wA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/base-x-3.0.7.js" integrity="sha512-/Bi1AJIP0TtxEB+Jh6Hk809H1G7vn4iJV80qagslf0+Hm0UjUi1s3qNrn1kZULjzUYuaf6ck0ndLGJ7MxWLmgQ==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/rawinflate-0.3.js" integrity="sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==" crossorigin="anonymous"></script>
<?php
if ($SYNTAXHIGHLIGHTING):
@@ -44,15 +44,13 @@ if ($SYNTAXHIGHLIGHTING):
endif;
if ($MARKDOWN):
?>
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.0.js" integrity="sha512-Kv8oAge9h2QmRyzb52jUomyXAvSMrpE9kWF3QRMFajo1a/TXjtY8u71vUA6t4+LE7huz4TSVH8VLJBEmcZiPRA==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/showdown-1.9.1.js" integrity="sha512-nRri7kqh3iRLdHbhtjfe8w9eAQPmt+ubH5U88UZyKbz6O9Q0q4haaXF0krOUclKmRJou/kKZYulgBHvHXPqOvg==" crossorigin="anonymous"></script>
<?php
endif;
?>
<script type="text/javascript" data-cfasync="false" src="js/purify-1.0.11.js" integrity="sha512-p7UyJuyBkhMcMgE4mDsgK0Lz70OvetLefua1oXs1OujWv9gOxh4xy8InFux7bZ4/DAZsTmO4rgVwZW9BHKaTaw==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-dNBKGlXagUZhkKcI+HhEH0otOswA5g2QnJV8BxYxNK/piW9jJWZvADCbzDJNRjt6A6QgMwBM8+lH7K3lgsOuQw==" crossorigin="anonymous"></script>
<!--[if IE]>
<style type="text/css">body {padding-left:60px;padding-right:60px;} #ienotice {display:block;}</style>
<![endif]-->
<script type="text/javascript" data-cfasync="false" src="js/purify-2.0.8.js" integrity="sha512-QwcEKGuEmKtMguCO9pqNtUtZqq9b/tJ8gNr5qhY8hykq3zKTlDOvpZAmf6Rs8yH35Bz1ZdctUjj2qEWxT5aXCg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-+4ay2Dw/9w/DOTutdpoiHvF6RxqV0V8ABSXHlebjGbQ7Td+3If7mOZ5OIu/lWCifcgP6vyhJuiB8+jl8FGtuwg==" crossorigin="anonymous"></script>
<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />
<link rel="icon" type="image/png" href="img/favicon-16x16.png?<?php echo rawurlencode($VERSION); ?>" sizes="16x16" />
@@ -69,27 +67,31 @@ endif;
<?php
if (strlen($NOTICE)):
?>
<span class="blink">▶</span> <?php echo htmlspecialchars($NOTICE);
<span class="blink">▶</span> <?php echo I18n::encode($NOTICE);
endif;
?>
</div>
<h1 class="title reloadlink"><?php echo I18n::_($NAME); ?></h1><br />
<h2 class="title"><?php echo I18n::_('Because ignorance is bliss'); ?></h2><br />
<h3 class="title"><?php echo $VERSION; ?></h3>
<noscript><div id="noscript" class="nonworking"><?php echo I18n::_('JavaScript is required for %s to work.<br />Sorry for the inconvenience.', I18n::_($NAME)); ?></div></noscript>
<div id="oldnotice" class="nonworking"><?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)); ?></div>
<div id="ienotice" class="nonworking"><?php echo I18n::_('Still using Internet Explorer? Do yourself a favor, switch to a modern browser:'), PHP_EOL; ?>
<noscript><div id="noscript" class="nonworking"><?php echo I18n::_('JavaScript is required for %s to work. Sorry for the inconvenience.', I18n::_($NAME)); ?></div></noscript>
<div id="oldnotice" class="nonworking hidden">
<?php echo I18n::_('%s requires a modern browser to work.', I18n::_($NAME)), PHP_EOL; ?>
<a href="https://www.mozilla.org/firefox/">Firefox</a>,
<a href="https://www.opera.com/">Opera</a>,
<a href="https://www.google.com/chrome">Chrome</a>…
<a href="https://www.google.com/chrome">Chrome</a>…<br />
<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-the-error-privatebin-requires-a-modern-browser-to-work'); ?></span>
</div>
<?php
if ($HTTPWARNING):
?>
<div id="httpnotice" class="errorMessage">
<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'); ?>
<div id="httpnotice" class="errorMessage hidden">
<?php echo I18n::_('This website is using an insecure connection! Please only use it for testing.'); ?><br />
<span class="small"><?php echo I18n::_('For more information <a href="%s">see this FAQ entry</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-it-show-me-an-error-about-an-insecure-connection'); ?></span>
</div>
<div id="insecurecontextnotice" class="errorMessage hidden">
<?php echo I18n::_('Your browser may require an HTTPS connection to support the WebCrypto API. Try <a href="%s">switching to HTTPS</a>.', $HTTPSLINK); ?>
</div>
<?php
endif;
?>
@@ -97,14 +99,15 @@ endif;
<section>
<article>
<div id="loadingindicator" class="hidden"><?php echo I18n::_('Loading…'); ?></div>
<div id="status"><?php echo htmlspecialchars($STATUS); ?></div>
<div id="errormessage" class="hidden"><?php echo htmlspecialchars($ERROR); ?></div>
<div id="status"><?php echo I18n::encode($STATUS); ?></div>
<div id="errormessage" class="hidden"><?php echo I18n::encode($ERROR); ?></div>
<div id="toolbar">
<button id="newbutton" class="reloadlink hidden"><img src="img/icon_new.png" width="11" height="15" alt="" /><?php echo I18n::_('New'); ?></button>
<button id="retrybutton" class="reloadlink hidden"><?php echo I18n::_('Retry'), PHP_EOL; ?></button>
<button id="sendbutton" class="hidden"><img src="img/icon_send.png" width="18" height="15" alt="" /><?php echo I18n::_('Send'); ?></button>
<button id="clonebutton" class="hidden"><img src="img/icon_clone.png" width="15" height="17" alt="" /><?php echo I18n::_('Clone'); ?></button>
<button id="rawtextbutton" class="hidden"><img src="img/icon_raw.png" width="15" height="15" alt="" /><?php echo I18n::_('Raw text'); ?></button>
<button id="emaillink" class="hidden"><img src="img/icon_email.png" width="15" height="15" alt="" /><?php echo I18n::_('Email'); ?></button>
<?php
if ($QRCODE):
?>
@@ -206,7 +209,7 @@ endif;
<?php
if (strlen($URLSHORTENER)):
?>
<button id="shortenbutton" data-shortener="<?php echo htmlspecialchars($URLSHORTENER); ?>"><img src="img/icon_shorten.png" width="13" height="15" /><?php echo I18n::_('Shorten URL'); ?></button>
<button id="shortenbutton" data-shortener="<?php echo I18n::encode($URLSHORTENER); ?>"><img src="img/icon_shorten.png" width="13" height="15" /><?php echo I18n::_('Shorten URL'); ?></button>
<?php
endif;
?>
@@ -254,11 +257,18 @@ if ($DISCUSSION):
</div>
<?php
endif;
?>
<?php
if ($FILEUPLOAD):
?>
<div id="dropzone" class="hidden" tabindex="-1" aria-hidden="true"></div>
<?php
endif;
?>
<section class="container">
<div id="noscript" role="alert" class="nonworking alert alert-info noscript-hide"><span class="glyphicon glyphicon-exclamation-sign" aria-hidden="true">
<span> <?php echo I18n::_('Loading…'); ?></span><br>
<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-not-the-loading-message-go-away">this FAQ for information to troubleshoot</a>.'); ?></span>
<span class="small"><?php echo I18n::_('In case this message never disappears please have a look at <a href="%s">this FAQ for information to troubleshoot</a>.', 'https://github.com/PrivateBin/PrivateBin/wiki/FAQ#why-does-the-loading-message-not-go-away'); ?></span>
</div>
</section>
</body>

View File

@@ -4,24 +4,31 @@ use PrivateBin\Configuration;
class ConfigurationTest extends PHPUnit_Framework_TestCase
{
private $_minimalConfig;
private $_options;
private $_minimalConfig;
private $_path;
public function setUp()
{
/* Setup Routine */
Helper::confBackup();
$this->_minimalConfig = '[main]' . PHP_EOL . '[model]' . PHP_EOL . '[model_options]';
$this->_options = Configuration::getDefaults();
$this->_options['model_options']['dir'] = PATH . $this->_options['model_options']['dir'];
$this->_options['traffic']['dir'] = PATH . $this->_options['traffic']['dir'];
$this->_options['purge']['dir'] = PATH . $this->_options['purge']['dir'];
$this->_minimalConfig = '[main]' . PHP_EOL . '[model]' . PHP_EOL . '[model_options]';
$this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_cfg';
if (!is_dir($this->_path)) {
mkdir($this->_path);
}
}
public function tearDown()
{
/* Tear Down Routine */
Helper::rmDir($this->_path);
if (is_file(CONF)) {
unlink(CONF);
}
@@ -177,4 +184,49 @@ class ConfigurationTest extends PHPUnit_Framework_TestCase
$this->assertFileExists(CONF, 'old configuration file gets converted');
$this->assertFileNotExists(PATH . 'cfg' . DIRECTORY_SEPARATOR . 'conf.ini', 'old configuration file gets removed');
}
public function testConfigPath()
{
// setup
$configFile = $this->_path . DIRECTORY_SEPARATOR . 'conf.php';
$options = $this->_options;
$options['main']['name'] = 'OtherBin';
Helper::createIniFile($configFile, $options);
// test
putenv('CONFIG_PATH=' . $this->_path);
$conf = new Configuration;
$this->assertEquals('OtherBin', $conf->getKey('name'), 'changing config path is supported');
// cleanup environment
if (is_file($configFile)) {
unlink($configFile);
}
putenv('CONFIG_PATH');
}
public function testConfigPathIni()
{
// setup
$configFile = $this->_path . DIRECTORY_SEPARATOR . 'conf.ini';
$configMigrated = $this->_path . DIRECTORY_SEPARATOR . 'conf.php';
$options = $this->_options;
$options['main']['name'] = 'OtherBin';
Helper::createIniFile($configFile, $options);
$this->assertFileNotExists(CONF, 'configuration in the default location is non existing');
// test
putenv('CONFIG_PATH=' . $this->_path);
$conf = new Configuration;
$this->assertEquals('OtherBin', $conf->getKey('name'), 'changing config path is supported for ini files as well');
$this->assertFileExists($configMigrated, 'old configuration file gets converted');
$this->assertFileNotExists($configFile, 'old configuration file gets removed');
$this->assertFileNotExists(CONF, 'configuration is not created in the default location');
// cleanup environment
if (is_file($configFile)) {
unlink($configFile);
}
putenv('CONFIG_PATH');
}
}

View File

@@ -56,18 +56,4 @@ class FilterTest extends PHPUnit_Framework_TestCase
$this->assertEquals('1.00 YiB', Filter::formatHumanReadableSize(1024 * $exponent));
$this->assertEquals('1.21 YiB', Filter::formatHumanReadableSize(1234 * $exponent));
}
public function testSlowEquals()
{
$this->assertTrue(Filter::slowEquals('foo', 'foo'), 'same string');
$this->assertFalse(Filter::slowEquals('foo', true), 'string and boolean');
$this->assertFalse(Filter::slowEquals('foo', 0), 'string and integer');
$this->assertFalse(Filter::slowEquals('123foo', 123), 'string and integer');
$this->assertFalse(Filter::slowEquals('123foo', '123'), 'different strings');
$this->assertFalse(Filter::slowEquals('6', ' 6'), 'strings with space');
$this->assertFalse(Filter::slowEquals('4.2', '4.20'), 'floats as strings');
$this->assertFalse(Filter::slowEquals('1e3', '1000'), 'integers as strings');
$this->assertFalse(Filter::slowEquals('9223372036854775807', '9223372036854775808'), 'large integers as strings');
$this->assertFalse(Filter::slowEquals('61529519452809720693702583126814', '61529519452809720000000000000000'), 'larger integers as strings');
}
}

View File

@@ -155,6 +155,17 @@ class I18nTest extends PHPUnit_Framework_TestCase
$this->assertEquals('some string + 1', I18n::_('some %s + %d', 'string', 1), 'browser language en');
}
public function testHtmlEntityEncoding()
{
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'foobar';
I18n::loadTranslations();
$input = '&<>"\'/`=';
$result = htmlspecialchars($input, ENT_QUOTES | ENT_HTML5 | ENT_DISALLOWED, 'UTF-8', false);
$this->assertEquals($result, I18n::encode($input), 'encodes HTML entities');
$this->assertEquals('<a>some ' . $result . ' + 1</a>', I18n::_('<a>some %s + %d</a>', $input, 1), 'encodes parameters in translations');
$this->assertEquals($result . $result, I18n::_($input . '%s', $input), 'encodes message ID as well, when no link');
}
public function testMessageIdsExistInAllLanguages()
{
$messageIds = array();

View File

@@ -56,6 +56,7 @@ class ViewTest extends PHPUnit_Framework_TestCase
$page->assign('URLSHORTENER', '');
$page->assign('QRCODE', true);
$page->assign('HTTPWARNING', true);
$page->assign('HTTPSLINK', 'https://example.com/');
$page->assign('COMPRESSION', 'zlib');
$dir = dir(PATH . 'tpl');

View File

@@ -46,25 +46,28 @@ class SvgGenerator extends BaseGenerator implements GeneratorInterface
// prepare image
$w = $this->getPixelRatio() * 5;
$h = $this->getPixelRatio() * 5;
$svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="'.$w.'" height="'.$h.'">';
$svg = '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="'.$w.'" height="'.$h.'" viewBox="0 0 5 5">';
$backgroundColor = '#FFFFFF';
$backgroundColor = '#FFF';
$rgbBackgroundColor = $this->getBackgroundColor();
if (!is_null($rgbBackgroundColor)) {
$backgroundColor = $this->_toUnderstandableColor($rgbBackgroundColor);
}
$svg .= '<rect width="'.$w.'" height="'.$h.'" style="fill:'.$backgroundColor.';stroke-width:1;stroke:'.$backgroundColor.'"/>';
$rgbColor = $this->_toUnderstandableColor($this->getColor());
$svg .= '<rect width="5" height="5" fill="'.$backgroundColor.'" stroke-width="0"/>';
$rects = [];
// draw content
foreach ($this->getArrayOfSquare() as $lineKey => $lineValue) {
foreach ($lineValue as $colKey => $colValue) {
if (true === $colValue) {
$svg .= '<rect x="'.$colKey * $this->getPixelRatio().'" y="'.$lineKey * $this->getPixelRatio().'" width="'.($this->getPixelRatio()).'" height="'.$this->getPixelRatio().'" style="fill:'.$rgbColor.';stroke-width:0;"/>';
$rects[] = 'M'.$colKey.','.$lineKey.'h1v1h-1v-1';
}
}
}
$rgbColor = $this->_toUnderstandableColor($this->getColor());
$svg .= '<path fill="'.$rgbColor.'" stroke-width="0" d="' . implode('', $rects) . '"/>';
$svg .= '</svg>';
$this->generatedImage = $svg;
@@ -80,7 +83,7 @@ class SvgGenerator extends BaseGenerator implements GeneratorInterface
protected function _toUnderstandableColor($color)
{
if (is_array($color)) {
return 'rgb('.implode(', ', $color).')';
return sprintf('#%X%X%X', $color[0], $color[1], $color[2]);
}
return $color;

View File

@@ -48,7 +48,7 @@ class Identicon
*
* @param string $string
* @param int $size
* @param string $color
* @param string|array $color
* @param string $backgroundColor
*/
public function displayImage($string, $size = 64, $color = null, $backgroundColor = null)
@@ -62,7 +62,7 @@ class Identicon
*
* @param string $string
* @param int $size
* @param string $color
* @param string|array $color
* @param string $backgroundColor
*
* @return string
@@ -77,7 +77,7 @@ class Identicon
*
* @param string $string
* @param int $size
* @param string $color
* @param string|array $color
* @param string $backgroundColor
*
* @return string
@@ -92,7 +92,7 @@ class Identicon
*
* @param string $string
* @param int $size
* @param string $color
* @param string|array $color
* @param string $backgroundColor
*
* @return string