Bladeren bron

Merge branch 'master' into js/removeJQuery

# Conflicts:
#	lib/Configuration.php
#	tpl/bootstrap.php
#	tst/ViewTest.php
rugk 1 week geleden
bovenliggende
commit
6580d2c6b2
56 gewijzigde bestanden met toevoegingen van 819 en 808 verwijderingen
  1. 1 1
      .github/workflows/eslint.yml
  2. 1 1
      .github/workflows/tests.yml
  3. 0 2
      .styleci.yml
  4. 5 0
      CHANGELOG.md
  5. 15 32
      composer.lock
  6. 198 198
      i18n/ko.json
  7. 3 3
      i18n/sl.json
  8. 2 2
      i18n/sv.json
  9. 1 1
      js/common.js
  10. 0 1
      js/purify-3.4.1.js
  11. 1 0
      js/purify-3.4.12.js
  12. 41 41
      lib/Configuration.php
  13. 17 18
      lib/Controller.php
  14. 1 1
      lib/Data/AbstractData.php
  15. 28 28
      lib/Data/Database.php
  16. 4 4
      lib/Data/Filesystem.php
  17. 22 22
      lib/Data/GoogleCloudStorage.php
  18. 32 32
      lib/Data/S3Storage.php
  19. 0 38
      lib/Exception/JsonException.php
  20. 2 2
      lib/Filter.php
  21. 21 6
      lib/FormatV2.php
  22. 10 10
      lib/I18n.php
  23. 2 24
      lib/Json.php
  24. 1 1
      lib/Model/AbstractModel.php
  25. 5 5
      lib/Model/Comment.php
  26. 2 2
      lib/Persistence/TrafficLimiter.php
  27. 4 4
      lib/Proxy/AbstractProxy.php
  28. 6 6
      lib/Proxy/ShlinkProxy.php
  29. 5 5
      lib/Proxy/YourlsProxy.php
  30. 14 11
      lib/Request.php
  31. 1 1
      lib/TemplateSwitcher.php
  32. 1 1
      lib/View.php
  33. 5 5
      lib/Vizhash16x16.php
  34. 1 1
      tpl/bootstrap5.php
  35. 101 101
      tst/Bootstrap.php
  36. 10 10
      tst/ControllerTest.php
  37. 6 6
      tst/ControllerWithDbTest.php
  38. 7 7
      tst/ControllerWithGcsTest.php
  39. 36 36
      tst/Data/DatabaseTest.php
  40. 16 16
      tst/Data/FilesystemTest.php
  41. 14 14
      tst/Data/GoogleCloudStorageTest.php
  42. 37 0
      tst/FormatV2Test.php
  43. 4 4
      tst/I18nTest.php
  44. 18 18
      tst/JsonApiTest.php
  45. 5 5
      tst/MigrateTest.php
  46. 36 36
      tst/ModelTest.php
  47. 1 1
      tst/Persistence/PurgeLimiterTest.php
  48. 9 9
      tst/Persistence/ServerSaltTest.php
  49. 1 1
      tst/Persistence/TrafficLimiterTest.php
  50. 25 5
      tst/RequestTest.php
  51. 6 6
      tst/ViewTest.php
  52. 1 1
      tst/Vizhash16x16Test.php
  53. 32 19
      tst/YourlsProxyTest.php
  54. 0 1
      vendor/composer/autoload_classmap.php
  55. 0 1
      vendor/composer/autoload_static.php
  56. 2 2
      vendor/composer/installed.php

+ 1 - 1
.github/workflows/eslint.yml

@@ -24,7 +24,7 @@ jobs:
           persist-credentials: false
 
       - name: Set up Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@v7
         with:
           node-version: '20'
 

+ 1 - 1
.github/workflows/tests.yml

@@ -224,7 +224,7 @@ jobs:
         persist-credentials: false
 
     - name: Setup Node
-      uses: actions/setup-node@v6
+      uses: actions/setup-node@v7
       with:
         node-version: '20'
         cache: 'npm'

+ 0 - 2
.styleci.yml

@@ -5,7 +5,6 @@ risky: false
 enabled:
   - align_equals
   - concat_with_spaces
-  - long_array_syntax
   - no_empty_comment
   - pre_increment
 
@@ -26,7 +25,6 @@ disabled:
   - phpdoc_single_line_var_spacing
   - phpdoc_summary
   - post_increment
-  - short_array_syntax
   - single_line_after_imports
   - unalign_equals
 

+ 5 - 0
CHANGELOG.md

@@ -7,6 +7,11 @@
 * CHANGED: Removed support for Bootstrap 3 as it requires jQuery.
 
 ## 2.0.6 (not yet released)
+* CHANGED: Upgrading libraries to: DOMpurify 3.4.12
+* CHANGED: Switch to PHP native JsonException type
+* FIXED: Gracefully handle YOURLS replies with a 200 status code but no shorturl, instead of raising a TypeError
+* FIXED: Return "Invalid data." instead of HTTP 500 on malformed v2 JSON payloads (#1883)
+* FIXED: Dead PATH validation guard in Controller, the check for a missing trailing directory separator never ran (#1887)
 
 ## 2.0.5 (2026-07-11)
 * CHANGED: Show OS-specific copy hotkey hint (Cmd+c on Mac, Ctrl+c on others) (#1506)

+ 15 - 32
composer.lock

@@ -396,20 +396,19 @@
         },
         {
             "name": "nikic/php-parser",
-            "version": "v5.7.0",
+            "version": "v5.8.0",
             "source": {
                 "type": "git",
                 "url": "https://github.com/nikic/PHP-Parser.git",
-                "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
+                "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
-                "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
+                "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f",
+                "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f",
                 "shasum": ""
             },
             "require": {
-                "ext-ctype": "*",
                 "ext-json": "*",
                 "ext-tokenizer": "*",
                 "php": ">=7.4"
@@ -448,9 +447,9 @@
             ],
             "support": {
                 "issues": "https://github.com/nikic/PHP-Parser/issues",
-                "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
+                "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0"
             },
-            "time": "2025-12-06T11:56:16+00:00"
+            "time": "2026-07-04T14:30:18+00:00"
         },
         {
             "name": "phar-io/manifest",
@@ -891,25 +890,25 @@
         },
         {
             "name": "phpunit/phpunit",
-            "version": "9.6.34",
+            "version": "9.6.35",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "b36f02317466907a230d3aa1d34467041271ef4a"
+                "reference": "0edba2f3a0c48df3553cb9b640810b30df60302b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/b36f02317466907a230d3aa1d34467041271ef4a",
-                "reference": "b36f02317466907a230d3aa1d34467041271ef4a",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0edba2f3a0c48df3553cb9b640810b30df60302b",
+                "reference": "0edba2f3a0c48df3553cb9b640810b30df60302b",
                 "shasum": ""
             },
             "require": {
                 "doctrine/instantiator": "^1.5.0 || ^2",
                 "ext-dom": "*",
+                "ext-filter": "*",
                 "ext-json": "*",
                 "ext-libxml": "*",
                 "ext-mbstring": "*",
-                "ext-xml": "*",
                 "ext-xmlwriter": "*",
                 "myclabs/deep-copy": "^1.13.4",
                 "phar-io/manifest": "^2.0.4",
@@ -974,31 +973,15 @@
             "support": {
                 "issues": "https://github.com/sebastianbergmann/phpunit/issues",
                 "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
-                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.34"
+                "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.35"
             },
             "funding": [
                 {
-                    "url": "https://phpunit.de/sponsors.html",
-                    "type": "custom"
-                },
-                {
-                    "url": "https://github.com/sebastianbergmann",
-                    "type": "github"
-                },
-                {
-                    "url": "https://liberapay.com/sebastianbergmann",
-                    "type": "liberapay"
-                },
-                {
-                    "url": "https://thanks.dev/u/gh/sebastianbergmann",
-                    "type": "thanks_dev"
-                },
-                {
-                    "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit",
-                    "type": "tidelift"
+                    "url": "https://phpunit.de/sponsoring.html",
+                    "type": "other"
                 }
             ],
-            "time": "2026-01-27T05:45:00+00:00"
+            "time": "2026-07-06T14:48:07+00:00"
         },
         {
             "name": "sebastian/cli-parser",

+ 198 - 198
i18n/ko.json

@@ -1,160 +1,160 @@
 {
     "PrivateBin": "PrivateBin",
-    "%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.",
-    "More information on the <a href=\"https://privatebin.info/\">project page</a>.": "More information on the <a href=\"https://privatebin.info/\">project page</a>.",
-    "Because ignorance is bliss": "Because ignorance is bliss",
-    "Document does not exist, has expired or has been deleted.": "Document does not exist, has expired or has been deleted.",
-    "%s requires php %s or above to work. Sorry.": "%s requires php %s or above to work. Sorry.",
-    "%s requires configuration section [%s] to be present in configuration file.": "%s requires configuration section [%s] to be present in configuration file.",
+    "%s is a minimalist, open source online pastebin where the server has zero knowledge of stored data. Data is encrypted/decrypted %sin the browser%s using 256 bits AES.": "%s은 서버가 저장된 데이터에 대해 전혀 알 수 없는 미니멀한 오픈소스 온라인 텍스트 공유 플랫폼(페이스트빈)입니다. 데이터는 256비트 AES를 사용하여 %s브라우저에서%s 암호화/복호화됩니다.",
+    "More information on the <a href=\"https://privatebin.info/\">project page</a>.": "자세한 정보는 <a href=\"https://privatebin.info/\">프로젝트 페이지</a>에서 확인하세요.",
+    "Because ignorance is bliss": "모르는 게 약이니까요",
+    "Document 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.": [
-        "Please wait %d second between each post. (singular)",
-        "Please wait %d seconds between each post. (1st plural)",
-        "Please wait %d seconds between each post. (2nd plural)",
-        "Please wait %d seconds between each post. (3rd plural)",
-        "Please wait %d seconds between each post. (4th plural)",
-        "Please wait %d seconds between each post. (5th plural)"
+        "다음 게시글을 작성할 때까지 %d초 동안 기다려 주세요.",
+        "다음 게시글을 작성할 때까지 %d초 동안 기다려 주세요.",
+        "다음 게시글을 작성할 때까지 %d초 동안 기다려 주세요.",
+        "다음 게시글을 작성할 때까지 %d초 동안 기다려 주세요.",
+        "다음 게시글을 작성할 때까지 %d초 동안 기다려 주세요.",
+        "다음 게시글을 작성할 때까지 %d초 동안 기다려 주세요."
     ],
-    "Document is limited to %s of encrypted data.": "Document is limited to %s of encrypted data.",
-    "Invalid data.": "Invalid data.",
-    "You are unlucky. Try again.": "You are unlucky. Try again.",
-    "Error saving comment. Sorry.": "Error saving comment. Sorry.",
-    "Error saving document. Sorry.": "Error saving document. Sorry.",
-    "Invalid document ID.": "Invalid document ID.",
-    "Document is not of burn-after-reading type.": "Document is not of burn-after-reading type.",
-    "Wrong deletion token. Document was not deleted.": "Wrong deletion token. Document was not deleted.",
-    "Document was properly deleted.": "Document was properly deleted.",
-    "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.",
-    "New": "New",
-    "Create": "Create",
-    "Clone": "Clone",
-    "Raw text": "Raw text",
-    "Expires": "Expires",
-    "Burn after reading": "Burn after reading",
-    "Open discussion": "Open discussion",
-    "Password (recommended)": "Password (recommended)",
-    "Discussion": "Discussion",
-    "Toggle navigation": "Toggle navigation",
+    "Document is limited to %s of encrypted data.": "문서 크기는 암호화된 데이터 기준 %s로 제한됩니다.",
+    "Invalid data.": "유효하지 않은 데이터입니다.",
+    "You are unlucky. Try again.": "운이 나빴네요. 다시 시도해 주세요.",
+    "Error saving comment. Sorry.": "댓글을 저장하는 중 오류가 발생했습니다. 죄송합니다.",
+    "Error saving document. Sorry.": "문서를 저장하는 중 오류가 발생했습니다. 죄송합니다.",
+    "Invalid document ID.": "유효하지 않은 문서 ID입니다.",
+    "Document is not of burn-after-reading type.": "이 문서는 '읽은 후 삭제' 설정이 적용되지 않았습니다.",
+    "Wrong deletion token. Document was not deleted.": "삭제 토큰이 일치하지 않습니다. 문서가 삭제되지 않았습니다.",
+    "Document 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": "새 문서",
+    "Create": "생성",
+    "Clone": "복제",
+    "Raw text": "원본 텍스트",
+    "Expires": "만료 기간",
+    "Burn after reading": "읽은 후 삭제",
+    "Open discussion": "댓글 허용",
+    "Password (recommended)": "비밀번호 (권장)",
+    "Discussion": "댓글",
+    "Toggle navigation": "네비게이션 토글",
     "%d seconds": [
-        "%d second (singular)",
-        "%d seconds (1st plural)",
-        "%d seconds (2nd plural)",
-        "%d seconds (3rd plural)",
-        "%d seconds (4th plural)",
-        "%d seconds (5th plural)"
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d"
     ],
     "%d minutes": [
-        "%d minute (singular)",
-        "%d minutes (1st plural)",
-        "%d minutes (2nd plural)",
-        "%d minutes (3rd plural)",
-        "%d minutes (4th plural)",
-        "%d minutes (5th plural)"
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d"
     ],
     "%d hours": [
-        "%d hour (singular)",
-        "%d hours (1st plural)",
-        "%d hours (2nd plural)",
-        "%d hours (3rd plural)",
-        "%d hours (4th plural)",
-        "%d hours (5th plural)"
+        "%d시간",
+        "%d시간",
+        "%d시간",
+        "%d시간",
+        "%d시간",
+        "%d시간"
     ],
     "%d days": [
-        "%d day (singular)",
-        "%d days (1st plural)",
-        "%d days (2nd plural)",
-        "%d days (3rd plural)",
-        "%d days (4th plural)",
-        "%d days (5th plural)"
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d"
     ],
     "%d weeks": [
-        "%d week (singular)",
-        "%d weeks (1st plural)",
-        "%d weeks (2nd plural)",
-        "%d weeks (3rd plural)",
-        "%d weeks (4th plural)",
-        "%d weeks (5th plural)"
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d"
     ],
     "%d months": [
-        "%d month (singular)",
-        "%d months (1st plural)",
-        "%d months (2nd plural)",
-        "%d months (3rd plural)",
-        "%d months (4th plural)",
-        "%d months (5th plural)"
+        "%d개월",
+        "%d개월",
+        "%d개월",
+        "%d개월",
+        "%d개월",
+        "%d개월"
     ],
     "%d years": [
-        "%d year (singular)",
-        "%d years (1st plural)",
-        "%d years (2nd plural)",
-        "%d years (3rd plural)",
-        "%d years (4th plural)",
-        "%d years (5th plural)"
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d",
+        "%d"
     ],
-    "Never": "Never",
-    "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.": "Note: This is a test service: Data may be deleted anytime. Kittens will die if you abuse this service.",
+    "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.": [
-        "This document will expire in %d second. (singular)",
-        "This document will expire in %d seconds. (1st plural)",
-        "This document will expire in %d seconds. (2nd plural)",
-        "This document will expire in %d seconds. (3rd plural)",
-        "This document will expire in %d seconds. (4th plural)",
-        "This document will expire in %d seconds. (5th plural)"
+        "이 문서는 %d초 후에 만료됩니다.",
+        "이 문서는 %d초 후에 만료됩니다.",
+        "이 문서는 %d초 후에 만료됩니다.",
+        "이 문서는 %d초 후에 만료됩니다.",
+        "이 문서는 %d초 후에 만료됩니다.",
+        "이 문서는 %d초 후에 만료됩니다."
     ],
     "This document will expire in %d minutes.": [
-        "This document will expire in %d minute. (singular)",
-        "This document will expire in %d minutes. (1st plural)",
-        "This document will expire in %d minutes. (2nd plural)",
-        "This document will expire in %d minutes. (3rd plural)",
-        "This document will expire in %d minutes. (4th plural)",
-        "This document will expire in %d minutes. (5th plural)"
+        "이 문서는 %d분 후에 만료됩니다.",
+        "이 문서는 %d분 후에 만료됩니다.",
+        "이 문서는 %d분 후에 만료됩니다.",
+        "이 문서는 %d분 후에 만료됩니다.",
+        "이 문서는 %d분 후에 만료됩니다.",
+        "이 문서는 %d분 후에 만료됩니다."
     ],
     "This document will expire in %d hours.": [
-        "This document will expire in %d hour. (singular)",
-        "This document will expire in %d hours. (1st plural)",
-        "This document will expire in %d hours. (2nd plural)",
-        "This document will expire in %d hours. (3rd plural)",
-        "This document will expire in %d hours. (4th plural)",
-        "This document will expire in %d hours. (5th plural)"
+        "이 문서는 %d시간 후에 만료됩니다.",
+        "이 문서는 %d시간 후에 만료됩니다.",
+        "이 문서는 %d시간 후에 만료됩니다.",
+        "이 문서는 %d시간 후에 만료됩니다.",
+        "이 문서는 %d시간 후에 만료됩니다.",
+        "이 문서는 %d시간 후에 만료됩니다."
     ],
     "This document will expire in %d days.": [
-        "This document will expire in %d day. (singular)",
-        "This document will expire in %d days. (1st plural)",
-        "This document will expire in %d days. (2nd plural)",
-        "This document will expire in %d days. (3rd plural)",
-        "This document will expire in %d days. (4th plural)",
-        "This document will expire in %d days. (5th plural)"
+        "이 문서는 %d일 후에 만료됩니다.",
+        "이 문서는 %d일 후에 만료됩니다.",
+        "이 문서는 %d일 후에 만료됩니다.",
+        "이 문서는 %d일 후에 만료됩니다.",
+        "이 문서는 %d일 후에 만료됩니다.",
+        "이 문서는 %d일 후에 만료됩니다."
     ],
     "This document will expire in %d months.": [
-        "This document will expire in %d month. (singular)",
-        "This document will expire in %d months. (1st plural)",
-        "This document will expire in %d months. (2nd plural)",
-        "This document will expire in %d months. (3rd plural)",
-        "This document will expire in %d months. (4th plural)",
-        "This document will expire in %d months. (5th plural)"
+        "이 문서는 %d개월 후에 만료됩니다.",
+        "이 문서는 %d개월 후에 만료됩니다.",
+        "이 문서는 %d개월 후에 만료됩니다.",
+        "이 문서는 %d개월 후에 만료됩니다.",
+        "이 문서는 %d개월 후에 만료됩니다.",
+        "이 문서는 %d개월 후에 만료됩니다."
     ],
-    "Please enter the password for this document:": "Please enter the password for this document:",
-    "Could not decrypt data (Wrong key?)": "Could not decrypt data (Wrong key?)",
-    "Could not delete the document, it was not stored in burn after reading mode.": "Could not delete the document, 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.": "FOR YOUR EYES ONLY. Don't close this window, this message can't be displayed again.",
-    "Could not decrypt comment; Wrong key?": "Could not decrypt comment; Wrong key?",
-    "Reply": "Reply",
-    "Anonymous": "Anonymous",
-    "Avatar generated from IP address": "Avatar generated from IP address",
-    "Add comment": "Add comment",
-    "Optional nickname…": "Optional nickname…",
-    "Post comment": "Post comment",
-    "Sending comment…": "Sending comment…",
-    "Comment posted.": "Comment posted.",
-    "Could not refresh display: %s": "Could not refresh display: %s",
-    "unknown status": "unknown status",
-    "server error or not responding": "server error or not responding",
-    "Could not post comment: %s": "Could not post comment: %s",
-    "Sending document…": "Sending document…",
-    "Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>%s</kbd>+<kbd>c</kbd> to copy)</span>": "Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>%s</kbd>+<kbd>c</kbd> to copy)</span>",
-    "Delete data": "Delete data",
-    "Could not create document: %s": "Could not create document: %s",
-    "Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)",
+    "Please enter the password for this document:": "이 문서의 비밀번호를 입력해 주세요:",
+    "Could not decrypt data (Wrong key?)": "데이터를 복호화할 수 없음 (잘못된 키인지 확인해 주세요.)",
+    "Could not delete the document, 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 document…": "문서 전송 중…",
+    "Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>%s</kbd>+<kbd>c</kbd> to copy)</span>": "문서 주소: <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(복사하려면 <kbd>%s</kbd>+<kbd>c</kbd> 키를 누르세요)</span>",
+    "Delete data": "데이터 삭제",
+    "Could not create document: %s": "문서를 생성할 수 없음: %s",
+    "Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "문서를 복호화할 수 없음: URL에 복호화 키가 없습니다 (URL의 일부를 누락시키는 리다이렉터나 URL 단축 서비스를 사용하셨나요?)",
     "B": "B",
     "kB": "kB",
     "MB": "MB",
@@ -164,75 +164,75 @@
     "EB": "EB",
     "ZB": "ZB",
     "YB": "YB",
-    "Format": "Format",
-    "Plain Text": "Plain Text",
-    "Source Code": "Source Code",
-    "Markdown": "Markdown",
-    "Download attachment": "Download attachment",
-    "Cloned: '%s'": "Cloned: '%s'",
-    "The cloned file '%s' was attached to this document.": "The cloned file '%s' was attached to this document.",
-    "Attach a file": "Attach a file",
-    "alternatively drag & drop a file or paste an image from the clipboard": "alternatively drag & drop a file or paste an image from the clipboard",
-    "File too large, to display a preview. Please download the attachment.": "File too large, to display a preview. Please download the attachment.",
-    "Remove attachment": "Remove attachment",
-    "Your browser does not support uploading encrypted files. Please use a newer browser.": "Your browser does not support uploading encrypted files. Please use a newer browser.",
-    "Invalid attachment.": "Invalid attachment.",
-    "Options": "Options",
-    "Shorten URL": "Shorten URL",
-    "Editor": "Editor",
-    "Preview": "Preview",
-    "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.",
-    "Decrypt": "Decrypt",
-    "Enter password": "Enter password",
-    "Loading…": "Loading…",
-    "Decrypting document…": "Decrypting document…",
-    "Preparing new document…": "Preparing new document…",
-    "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.": "In case this message never disappears please have a look at <a href=\"%s\">this FAQ for information to troubleshoot</a>.",
-    "+++ no document text +++": "+++ no document text +++",
-    "Could not get document data: %s": "Could not get document data: %s",
-    "QR code": "QR code",
-    "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 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",
-    "Encrypted note on %s": "Encrypted note on %s",
-    "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.",
-    "URL shortener may expose your decrypt key in URL.": "URL shortener may expose your decrypt key in URL.",
-    "URL shortener is enabled by default.": "URL shortener is enabled by default.",
-    "Save document": "Save document",
-    "Your IP is not authorized to create documents.": "Your IP is not authorized to create documents.",
-    "Trying to shorten a URL that isn't pointing at our instance.": "Trying to shorten a URL that isn't pointing at our instance.",
-    "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.",
-    "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.",
-    "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.",
-    "This secret message can only be displayed once. Would you like to see it now?": "This secret message can only be displayed once. Would you like to see it now?",
-    "Yes, see it": "Yes, see it",
-    "Dark Mode": "Dark Mode",
-    "Error compressing document, due to missing WebAssembly support.": "Error compressing document, due to missing WebAssembly support.",
-    "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.",
-    "Start over": "Start over",
-    "Document copied to clipboard": "Document copied to clipboard",
-    "To copy document press on the copy button or use the clipboard shortcut <kbd>%s</kbd>+<kbd>c</kbd>": "To copy document press on the copy button or use the clipboard shortcut <kbd>%s</kbd>+<kbd>c</kbd>",
-    "Copy link": "Copy link",
-    "Link copied to clipboard": "Link copied to clipboard",
-    "Document text": "Document text",
-    "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)",
-    "Show password": "Show password",
-    "Hide password": "Hide password",
-    "Theme": "Theme",
-    "Copy": "Copy",
+    "Format": "형식",
+    "Plain Text": "일반 텍스트",
+    "Source Code": "소스 코드",
+    "Markdown": "마크다운",
+    "Download attachment": "첨부 파일 다운로드",
+    "Cloned: '%s'": "복제됨: '%s'",
+    "The cloned file '%s' was attached to this document.": "복제된 파일 '%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": "URL 단축",
+    "Editor": "편집기",
+    "Preview": "미리 보기",
+    "%s requires the PATH to end in a \"%s\". Please update the PATH in your index.php.": "%s을(를) 실행하려면 PATH가 \"%s\"(으)로 끝나야 합니다. index.php 파일의 PATH 설정을 업데이트해 주세요.",
+    "Decrypt": "복호화",
+    "Enter password": "비밀번호 입력",
+    "Loading…": "로딩 중…",
+    "Decrypting document…": "문서 복호화 중…",
+    "Preparing new document…": "새 문서 준비 중…",
+    "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 document text +++": "+++ 문서 내용 없음 +++",
+    "Could not get document 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>.": "WebCrypto API를 지원하려면 브라우저에서 HTTPS 연결이 필요할 수 있습니다. <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": "닫기",
+    "Encrypted note on %s": "%s에 작성된 암호화된 메모",
+    "Visit this link to see the note. Giving the URL to anyone allows them to access the note, too.": "메모를 확인하려면 이 링크를 방문하세요. 다른 사람에게 URL을 공유하면 그 사람도 메모에 접근할 수 있게 됩니다.",
+    "URL shortener may expose your decrypt key in URL.": "URL 단축 서비스를 사용하면 URL에 포함된 복호화 키가 노출될 수 있습니다.",
+    "URL shortener is enabled by default.": "URL 단축 기능이 기본으로 활성화되어 있습니다.",
+    "Save document": "문서 저장",
+    "Your IP is not authorized to create documents.": "귀하의 IP는 문서 생성 권한이 없습니다.",
+    "Trying to shorten a URL that isn't pointing at our instance.": "현재 인스턴스를 가리키지 않는 URL을 단축하려고 시도했습니다.",
+    "Proxy error: Proxy URL is empty. This can be a configuration issue, like wrong or missing config keys.": "프록시 오류: 프록시 URL이 비어 있습니다. 잘못된 설정 키이거나 누락된 설정 때문일 수 있습니다.",
+    "Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.": "프록시 오류: 프록시 응답을 구문 분석하는 중 오류가 발생했습니다. 잘못된 설정 키이거나 누락된 설정 때문일 수 있습니다.",
+    "Proxy error: Bad response. This can be a configuration issue, like wrong or missing config keys or a temporary outage.": "프록시 오류: 잘못된 응답입니다. 키 누락이나 잘못된 값 입력과 같은 설정 오류이거나 일시적인 서버 장애일 수 있습니다.",
+    "This secret message can only be displayed once. Would you like to see it now?": "이 비밀 메시지는 단 한 번만 표시됩니다. 지금 확인하시겠습니까?",
+    "Yes, see it": "네, 확인하겠습니다",
+    "Dark Mode": "다크 모드",
+    "Error compressing document, due to missing WebAssembly support.": "WebAssembly 지원이 누락되어 문서를 압축하는 동안 오류가 발생했습니다.",
+    "Error decompressing document, your browser does not support WebAssembly. Please use another browser to view this document.": "문서 압축 해제 오류: 브라우저가 WebAssembly를 지원하지 않습니다. 이 문서를 보려면 다른 브라우저를 사용해 주세요.",
+    "Start over": "처음부터 다시 시작",
+    "Document copied to clipboard": "문서가 클립보드에 복사됨",
+    "To copy document press on the copy button or use the clipboard shortcut <kbd>%s</kbd>+<kbd>c</kbd>": "문서를 복사하려면 복사 버튼을 누르거나 클립보드 단축키 <kbd>%s</kbd>+<kbd>c</kbd>를 사용하세요",
+    "Copy link": "링크 복사",
+    "Link copied to clipboard": "링크가 클립보드에 복사됨",
+    "Document text": "문서 텍스트",
+    "Tabulator key serves as character (Hit <kbd>Ctrl</kbd>+<kbd>m</kbd> or <kbd>Esc</kbd> to toggle)": "탭 키가 문자로 입력됩니다 (전환하려면 <kbd>Ctrl</kbd>+<kbd>m</kbd> 또는 <kbd>Esc</kbd> 키를 누르세요)",
+    "Show password": "비밀번호 표시",
+    "Hide password": "비밀번호 숨기기",
+    "Theme": "테마",
+    "Copy": "복사",
     "Cmd": "Cmd",
     "Ctrl": "Ctrl"
 }

+ 3 - 3
i18n/sl.json

@@ -105,7 +105,7 @@
         "Ta dokument bo potekel čez %d minuto.",
         "Ta dokument bo potekel čez %d minuti.",
         "Ta dokument bo potekel čez %d minute.",
-        "Ta dokument bo potekel čez %d minut.",
+        "Ta dokument bo potekel čez %d minute.",
         "Ta dokument bo potekel čez %d minut.",
         "Ta dokument bo potekel čez %d minut."
     ],
@@ -113,13 +113,13 @@
         "Ta dokument bo potekel čez %d uro.",
         "Ta dokument bo potekel čez %d uri.",
         "Ta dokument bo potekel čez %d ure.",
-        "Ta dokument bo potekel čez %d ur.",
+        "Ta dokument bo potekel čez %d ure.",
         "Ta dokument bo potekel čez %d ur.",
         "Ta dokument bo potekel čez %d ur."
     ],
     "This document will expire in %d days.": [
         "Ta dokument bo potekel čez %d dan.",
-        "Ta dokument bo potekel čez %d dni.",
+        "Ta dokument bo potekel čez %d dneva.",
         "Ta dokument bo potekel čez %d dni.",
         "Ta dokument bo potekel čez %d dni.",
         "Ta dokument bo potekel čez %d dni.",

+ 2 - 2
i18n/sv.json

@@ -151,7 +151,7 @@
     "server error or not responding": "serverfel eller inget svar",
     "Could not post comment: %s": "Kunde inte publicera kommentar: %s",
     "Sending document…": "Skickar dokument…",
-    "Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>%s</kbd>+<kbd>c</kbd> to copy)</span>": "Ditt dokument är <a id=\\\"pasteurl\\\" href=\\\"%s\\\">%s</a> <span id=\\\"copyhint\\\">(Tryck <kbd>%s</kbd>+<kbd>c</kbd> för att kopiera)</span>",
+    "Your document is <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Hit <kbd>%s</kbd>+<kbd>c</kbd> to copy)</span>": "Ditt dokument är <a id=\"pasteurl\" href=\"%s\">%s</a> <span id=\"copyhint\">(Tryck <kbd>%s</kbd>+<kbd>c</kbd> för att kopiera)</span>",
     "Delete data": "Radera data",
     "Could not create document: %s": "Kunde inte skapa dokument: %s",
     "Cannot decrypt document: Decryption key missing in URL (Did you use a redirector or an URL shortener which strips part of the URL?)": "Kan inte dekryptera dokument: Dekrypteringsnyckel saknas i URL:en (använde du en omdirigerare eller URL-förkortare som tar bort delar av URL:en?)",
@@ -232,7 +232,7 @@
     "Show password": "Visa lösenord",
     "Hide password": "Dölj lösenord",
     "Theme": "Tema",
-    "Copy": "Copy",
+    "Copy": "Kopiera",
     "Cmd": "Cmd",
     "Ctrl": "Ctrl"
 }

+ 1 - 1
js/common.js

@@ -31,7 +31,7 @@ require('./prettify');
 global.prettyPrint = window.PR ? window.PR.prettyPrint : function() {};
 global.prettyPrintOne = window.PR ? window.PR.prettyPrintOne : function() {};
 global.showdown = require('./showdown-2.1.0');
-global.DOMPurify = require('./purify-3.4.1');
+global.DOMPurify = require('./purify-3.4.12');
 global.baseX = require('./base-x-5.0.1').baseX;
 global.Legacy = require('./legacy').Legacy;
 require('./privatebin');

File diff suppressed because it is too large
+ 0 - 1
js/purify-3.4.1.js


File diff suppressed because it is too large
+ 1 - 0
js/purify-3.4.12.js


+ 41 - 41
lib/Configuration.php

@@ -33,8 +33,8 @@ class Configuration
      *
      * @var array
      */
-    private static $_defaults = array(
-        'main' => array(
+    private static $_defaults = [
+        'main' => [
             'name'                     => 'PrivateBin',
             'basepath'                 => '',
             'discussion'               => true,
@@ -48,7 +48,7 @@ class Configuration
             'sizelimit'                => 10485760,
             'templateselection'        => false,
             'template'                 => 'bootstrap5',
-            'availabletemplates'       => array(
+            'availabletemplates'       => [
                 'bootstrap5',
                 'bootstrap',
                 'bootstrap-page',
@@ -56,7 +56,7 @@ class Configuration
                 'bootstrap-dark-page',
                 'bootstrap-compact',
                 'bootstrap-compact-page',
-            ),
+            ],
             'info'                     => 'More information on the <a href=\'https://privatebin.info/\'>project page</a>.',
             'notice'                   => '',
             'languageselection'        => false,
@@ -69,11 +69,11 @@ class Configuration
             'cspheader'                => 'default-src \'none\'; base-uri \'self\'; form-action \'none\'; manifest-src \'self\'; connect-src * blob:; script-src \'self\' \'wasm-unsafe-eval\'; style-src \'self\'; font-src \'self\'; frame-ancestors \'none\'; frame-src blob:; img-src \'self\' data: blob:; media-src blob:; object-src blob:; sandbox allow-same-origin allow-scripts allow-forms allow-modals allow-downloads',
             'httpwarning'              => true,
             'compression'              => 'zlib',
-        ),
-        'expire' => array(
+        ],
+        'expire' => [
             'default' => '1week',
-        ),
-        'expire_options' => array(
+        ],
+        'expire_options' => [
             '5min'   => 300,
             '10min'  => 600,
             '1hour'  => 3600,
@@ -82,38 +82,38 @@ class Configuration
             '1month' => 2592000,
             '1year'  => 31536000,
             'never'  => 0,
-        ),
-        'formatter_options' => array(
+        ],
+        'formatter_options' => [
             'plaintext'          => 'Plain Text',
             'syntaxhighlighting' => 'Source Code',
             'markdown'           => 'Markdown',
-        ),
-        'traffic' => array(
+        ],
+        'traffic' => [
             'limit'     => 10,
             'header'    => '',
             'exempted'  => '',
             'creators'  => '',
-        ),
-        'purge' => array(
+        ],
+        'purge' => [
             'limit'     => 300,
             'batchsize' => 10,
-        ),
-        'model' => array(
+        ],
+        'model' => [
             'class' => 'Filesystem',
-        ),
-        'model_options' => array(
+        ],
+        'model_options' => [
             'dir' => 'data',
-        ),
-        'yourls' => array(
+        ],
+        'yourls' => [
             'signature' => '',
             'apiurl'    => '',
-        ),
-        'shlink' => array(
+        ],
+        'shlink' => [
             'apikey'    => '',
             'apiurl'    => '',
-        ),
+        ],
         // update this array when adding/changing/removing js files
-        'sri' => array(
+        'sri' => [
             'js/base-x-5.0.1.js'     => 'sha512-FmhlnjIxQyxkkxQmzf0l6IRGsGbgyCdgqPxypFsEtHMF1naRqaLLo6mcyN5rEaT16nKx1PeJ4g7+07D6gnk/Tg==',
             'js/bootstrap-5.3.8.js'  => 'sha512-BkZvJ5rZ3zbDCod5seWHpRGg+PRd6ZgE8Nua/OMtcxqm8Wtg0PqwhUUXK5bqvl3oclMt5O+3zjRVX0L+L2j7fA==',
             'js/dark-mode-switch.js' => 'sha512-BhY7dNU14aDN5L+muoUmA66x0CkYUWkQT0nxhKBLP/o2d7jE025+dvWJa4OiYffBGEFgmhrD/Sp+QMkxGMTz2g==',
@@ -121,12 +121,12 @@ class Configuration
             'js/legacy.js'           => 'sha512-pRofxsrf5UItjiP22Dcjh3FAcBjF/n7h8U9/W5xqJk17U0N2U1oajhXypq/omo9jhwS1iVGOhWrRepoPeFns+w==',
             'js/prettify.js'         => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
             'js/privatebin.js'       => 'sha512-/lTaFNkvi1jyd9K8AdzohD/8jI2RMFmsnFArbqam3GdDpP60HZGMlf5gGqjzCjHrjcuCDQM66utUv6NmK9v3IQ==',
-            'js/purify-3.4.1.js'     => 'sha512-280a/Vb6fVFsYaeRrkuDp4EDmdYlt2XS+dlDEO/U9qljPrAraA2bIzHTNmP+9dpwPDDwTML+RS+h5iaagPwTzA==',
+            'js/purify-3.4.12.js'    => 'sha512-Akf6HnAJZm0sWWWI4gp2GYff0NDnHUB02XJE5S7Hdq/Z5xtMjkuFacsDA8ZtViv1gi+onBxMhEMIaGyQeGxBng==',
             'js/showdown-2.1.0.js'   => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
             'js/zlib-1.3.2.js'       => 'sha512-RAhJgxg9siMIA8ky4c10Rc2zUgnK80olHB8Tt1IOYWY4Eh1WmrviQkDn+sgBlb38ZHq3tzufGC41kP360gmosQ==',
             'js/zlib.js'             => 'sha512-QOaEwssHqHRRcWJ2Un3Kl2Zhyprzl7T8zmsKN2FppFxW3VR+8UChYOx2iuL0HbXK42fuBWJm5PNQJxufulrt/w==',
-        ),
-    );
+        ],
+    ];
 
     /**
      * parse configuration file and ensure default configuration values are present
@@ -135,8 +135,8 @@ class Configuration
      */
     public function __construct()
     {
-        $basePaths  = array();
-        $config     = array();
+        $basePaths  = [];
+        $config     = [];
         $configPath = getenv('CONFIG_PATH');
         if ($configPath !== false && !empty($configPath)) {
             $basePaths[] = $configPath;
@@ -146,10 +146,10 @@ class Configuration
             $configFile = $basePath . DIRECTORY_SEPARATOR . 'conf.php';
             if (is_readable($configFile)) {
                 $config = parse_ini_file($configFile, true);
-                foreach (array('main', 'model', 'model_options') as $section) {
+                foreach (['main', 'model', 'model_options'] as $section) {
                     if (!array_key_exists($section, $config)) {
                         $name = $config['main']['name'] ?? self::getDefaults()['main']['name'];
-                        throw new TranslatedException(array('%s requires configuration section [%s] to be present in configuration file.', I18n::_($name), $section), 2);
+                        throw new TranslatedException(['%s requires configuration section [%s] to be present in configuration file.', I18n::_($name), $section], 2);
                     }
                 }
                 break;
@@ -171,27 +171,27 @@ class Configuration
                 $section === 'model_options' &&
                 $this->_configuration['model']['class'] === 'Database'
             ) {
-                $values = array(
+                $values = [
                     'dsn' => 'sqlite:' . PATH . 'data' . DIRECTORY_SEPARATOR . 'db.sq3',
                     'tbl' => null,
                     'usr' => null,
                     'pwd' => null,
-                    'opt' => array(),
-                );
+                    'opt' => [],
+                ];
             } elseif (
                 $section === 'model_options' &&
                 $this->_configuration['model']['class'] === 'GoogleCloudStorage'
             ) {
-                $values = array(
+                $values = [
                     'bucket'     => getenv('PRIVATEBIN_GCS_BUCKET') ? getenv('PRIVATEBIN_GCS_BUCKET') : null,
                     'prefix'     => 'pastes',
                     'uniformacl' => false,
-                );
+                ];
             } elseif (
                 $section === 'model_options' &&
                 $this->_configuration['model']['class'] === 'S3Storage'
             ) {
-                $values = array(
+                $values = [
                     'region'                  => null,
                     'version'                 => null,
                     'endpoint'                => null,
@@ -200,7 +200,7 @@ class Configuration
                     'use_path_style_endpoint' => null,
                     'bucket'                  => null,
                     'prefix'                  => '',
-                );
+                ];
             }
 
             // "*_options" sections don't require all defaults to be set
@@ -230,9 +230,9 @@ class Configuration
                             $result = $config[$section][$key];
                         } elseif (is_bool($val)) {
                             $val = strtolower($config[$section][$key]);
-                            if (in_array($val, array('true', 'yes', 'on'))) {
+                            if (in_array($val, ['true', 'yes', 'on'])) {
                                 $result = true;
-                            } elseif (in_array($val, array('false', 'no', 'off'))) {
+                            } elseif (in_array($val, ['false', 'no', 'off'])) {
                                 $result = false;
                             } else {
                                 $result = (bool) $config[$section][$key];
@@ -311,7 +311,7 @@ class Configuration
     public function getSection($section)
     {
         if (!array_key_exists($section, $this->_configuration)) {
-            throw new TranslatedException(array('%s requires configuration section [%s] to be present in configuration file.', I18n::_($this->getKey('name')), $section), 3);
+            throw new TranslatedException(['%s requires configuration section [%s] to be present in configuration file.', I18n::_($this->getKey('name')), $section], 3);
         }
         return $this->_configuration[$section];
     }

+ 17 - 18
lib/Controller.php

@@ -12,7 +12,6 @@
 namespace PrivateBin;
 
 use Exception;
-use PrivateBin\Exception\JsonException;
 use PrivateBin\Exception\TranslatedException;
 use PrivateBin\Persistence\ServerSalt;
 use PrivateBin\Persistence\TrafficLimiter;
@@ -128,7 +127,7 @@ class Controller
             error_log(I18n::_('%s requires php %s or above to work. Sorry.', I18n::_('PrivateBin'), self::MIN_PHP_VERSION));
             return;
         }
-        if (strlen(PATH) < 0 && substr(PATH, -1) !== DIRECTORY_SEPARATOR) {
+        if (strlen(PATH) > 0 && substr(PATH, -1) !== DIRECTORY_SEPARATOR) {
             error_log(I18n::_('%s requires the PATH to end in a "%s". Please update the PATH in your index.php.', I18n::_('PrivateBin'), DIRECTORY_SEPARATOR));
             return;
         }
@@ -206,7 +205,7 @@ class Controller
         // force default language, if language selection is disabled and a default is set
         if (!$this->_conf->getKey('languageselection') && strlen($lang) === 2) {
             $_COOKIE['lang'] = $lang;
-            setcookie('lang', $lang, array('SameSite' => 'Lax', 'Secure' => true));
+            setcookie('lang', $lang, ['SameSite' => 'Lax', 'Secure' => true]);
         }
     }
 
@@ -230,7 +229,7 @@ class Controller
         if (!$this->_conf->getKey('templateselection') && array_key_exists('template', $_COOKIE)) {
             unset($_COOKIE['template']); // ensure value is not re-used in template switcher
             $expiredInAllTimezones = time() - 86400;
-            setcookie('template', '', array('expires' => $expiredInAllTimezones, 'SameSite' => 'Lax', 'Secure' => true));
+            setcookie('template', '', ['expires' => $expiredInAllTimezones, 'SameSite' => 'Lax', 'Secure' => true]);
         }
     }
 
@@ -324,7 +323,7 @@ class Controller
                 $paste = $this->_model->getPaste();
                 $paste->setData($data);
                 $paste->store();
-                $this->_json_result($paste->getId(), array('deletetoken' => $paste->getDeleteToken()));
+                $this->_json_result($paste->getId(), ['deletetoken' => $paste->getDeleteToken()]);
             } catch (Exception $e) {
                 $this->_json_error($e->getMessage());
             }
@@ -418,7 +417,7 @@ class Controller
         header('X-Frame-Options: deny');
 
         // label all the expiration options
-        $expire = array();
+        $expire = [];
         foreach ($this->_conf->getSection('expire_options') as $time => $seconds) {
             $expire[$time] = ($seconds === 0) ? I18n::_(ucfirst($time)) : Filter::formatHumanReadableTime($time);
         }
@@ -430,22 +429,22 @@ class Controller
         $languageselection = '';
         if ($this->_conf->getKey('languageselection')) {
             $languageselection = I18n::getLanguage();
-            setcookie('lang', $languageselection, array('SameSite' => 'Lax', 'Secure' => true));
+            setcookie('lang', $languageselection, ['SameSite' => 'Lax', 'Secure' => true]);
         }
 
         // set template cookie if that functionality was enabled
         $templateselection = '';
         if ($this->_conf->getKey('templateselection')) {
             $templateselection = TemplateSwitcher::getTemplate();
-            setcookie('template', $templateselection, array('SameSite' => 'Lax', 'Secure' => true));
+            setcookie('template', $templateselection, ['SameSite' => 'Lax', 'Secure' => true]);
         }
 
         // strip policies that are unsupported in meta tag
         $metacspheader = str_replace(
-            array(
+            [
                 'frame-ancestors \'none\'; ',
                 '; sandbox allow-same-origin allow-scripts allow-forms allow-modals allow-downloads',
-            ),
+            ],
             '',
             $this->_conf->getKey('cspheader')
         );
@@ -454,7 +453,7 @@ class Controller
         $page->assign('CSPHEADER', $metacspheader);
         $page->assign('ERROR', I18n::_($this->_error));
         $page->assign('NAME', $this->_conf->getKey('name'));
-        if (in_array($this->_request->getOperation(), array('shlinkproxy', 'yourlsproxy'), true)) {
+        if (in_array($this->_request->getOperation(), ['shlinkproxy', 'yourlsproxy'], true)) {
             $page->assign('SHORTURL', $this->_status);
             $page->draw('shortenerproxy');
             return;
@@ -500,13 +499,13 @@ class Controller
      */
     private function _jsonld($type)
     {
-        if (!in_array($type, array(
+        if (!in_array($type, [
             'comment',
             'commentmeta',
             'paste',
             'pastemeta',
             'types',
-        ))) {
+        ])) {
             $type = '';
         }
         $content = '{}';
@@ -541,10 +540,10 @@ class Controller
      */
     private function _json_error($error)
     {
-        $result = array(
+        $result = [
             'status'  => 1,
             'message' => $error,
-        );
+        ];
         $this->_json = Json::encode($result);
     }
 
@@ -556,13 +555,13 @@ class Controller
      * @param  array $other
      * @throws JsonException
      */
-    private function _json_result($dataid, $other = array())
+    private function _json_result($dataid, $other = [])
     {
-        $result = array(
+        $result = [
             'status' => 0,
             'id'     => $dataid,
             'url'    => $this->_urlBase . '?' . $dataid,
-        ) + $other;
+        ] + $other;
         $this->_json = Json::encode($result);
     }
 

+ 1 - 1
lib/Data/AbstractData.php

@@ -24,7 +24,7 @@ abstract class AbstractData
      * @access protected
      * @var    array
      */
-    protected $_last_cache = array();
+    protected $_last_cache = [];
 
     /**
      * Create a paste.

+ 28 - 28
lib/Data/Database.php

@@ -12,10 +12,10 @@
 namespace PrivateBin\Data;
 
 use Exception;
+use JsonException;
 use PDO;
 use PDOException;
 use PrivateBin\Controller;
-use PrivateBin\Exception\JsonException;
 use PrivateBin\Json;
 
 /**
@@ -158,12 +158,12 @@ class Database extends AbstractData
             return $this->_exec(
                 'INSERT INTO "' . $this->_sanitizeIdentifier('paste') .
                 '" VALUES(?,?,?,?)',
-                array(
+                [
                     $pasteid,
                     Json::encode($paste),
                     $expire_date,
                     Json::encode($meta),
-                )
+                ]
             );
         } catch (Exception $e) {
             error_log('Error while attempting to insert a paste into the database: ' . $e->getMessage());
@@ -183,7 +183,7 @@ class Database extends AbstractData
         try {
             $row = $this->_select(
                 'SELECT * FROM "' . $this->_sanitizeIdentifier('paste') .
-                '" WHERE "dataid" = ?', array($pasteid), true
+                '" WHERE "dataid" = ?', [$pasteid], true
             );
         } catch (PDOException $e) {
             $row = false;
@@ -196,14 +196,14 @@ class Database extends AbstractData
             $paste = Json::decode($row['data']);
         } catch (JsonException $e) {
             error_log('Error while reading a paste from the database: ' . $e->getMessage());
-            $paste = array();
+            $paste = [];
         }
 
         try {
             $paste['meta'] = Json::decode($row['meta']);
         } catch (JsonException $e) {
             error_log('Error while reading a paste from the database: ' . $e->getMessage());
-            $paste['meta'] = array();
+            $paste['meta'] = [];
         }
         $expire_date = (int) $row['expiredate'];
         if ($expire_date > 0) {
@@ -223,11 +223,11 @@ class Database extends AbstractData
     {
         $this->_exec(
             'DELETE FROM "' . $this->_sanitizeIdentifier('paste') .
-            '" WHERE "dataid" = ?', array($pasteid)
+            '" WHERE "dataid" = ?', [$pasteid]
         );
         $this->_exec(
             'DELETE FROM "' . $this->_sanitizeIdentifier('comment') .
-            '" WHERE "pasteid" = ?', array($pasteid)
+            '" WHERE "pasteid" = ?', [$pasteid]
         );
     }
 
@@ -243,7 +243,7 @@ class Database extends AbstractData
         try {
             $row = $this->_select(
                 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('paste') .
-                '" WHERE "dataid" = ?', array($pasteid), true
+                '" WHERE "dataid" = ?', [$pasteid], true
             );
         } catch (PDOException $e) {
             return false;
@@ -277,14 +277,14 @@ class Database extends AbstractData
             return $this->_exec(
                 'INSERT INTO "' . $this->_sanitizeIdentifier('comment') .
                 '" VALUES(?,?,?,?,?,?)',
-                array(
+                [
                     $commentid,
                     $pasteid,
                     $parentid,
                     $data,
                     $meta['icon'],
                     $meta['created'],
-                )
+                ]
             );
         } catch (PDOException $e) {
             error_log('Error while attempting to insert a comment into the database: ' . $e->getMessage());
@@ -303,24 +303,24 @@ class Database extends AbstractData
     {
         $rows = $this->_select(
             'SELECT * FROM "' . $this->_sanitizeIdentifier('comment') .
-            '" WHERE "pasteid" = ?', array($pasteid)
+            '" WHERE "pasteid" = ?', [$pasteid]
         );
 
         // create comment list
-        $comments = array();
+        $comments = [];
         if (count($rows)) {
             foreach ($rows as $row) {
                 try {
                     $data = Json::decode($row['data']);
                 } catch (JsonException $e) {
                     error_log('Error while reading a comment from the database: ' . $e->getMessage());
-                    $data = array();
+                    $data = [];
                 }
                 $i                          = $this->getOpenSlot($comments, (int) $row['postdate']);
                 $comments[$i]               = $data;
                 $comments[$i]['id']         = $row['dataid'];
                 $comments[$i]['parentid']   = $row['parentid'];
-                $comments[$i]['meta']       = array('created' => (int) $row['postdate']);
+                $comments[$i]['meta']       = ['created' => (int) $row['postdate']];
                 if (array_key_exists('vizhash', $row) && !empty($row['vizhash'])) {
                     $comments[$i]['meta']['icon'] = $row['vizhash'];
                 }
@@ -345,7 +345,7 @@ class Database extends AbstractData
             return (bool) $this->_select(
                 'SELECT "dataid" FROM "' . $this->_sanitizeIdentifier('comment') .
                 '" WHERE "pasteid" = ? AND "parentid" = ? AND "dataid" = ?',
-                array($pasteid, $parentid, $commentid), true
+                [$pasteid, $parentid, $commentid], true
             );
         } catch (PDOException $e) {
             return false;
@@ -375,7 +375,7 @@ class Database extends AbstractData
         return $this->_exec(
             'UPDATE "' . $this->_sanitizeIdentifier('config') .
             '" SET "value" = ? WHERE "id" = ?',
-            array($value, strtoupper($namespace))
+            [$value, strtoupper($namespace)]
         );
     }
 
@@ -396,13 +396,13 @@ class Database extends AbstractData
             $this->_exec(
                 'INSERT INTO "' . $this->_sanitizeIdentifier('config') .
                 '" VALUES(?,?)',
-                array($configKey, '')
+                [$configKey, '']
             );
 
             // migrate filesystem based salt into database
             $file = 'data' . DIRECTORY_SEPARATOR . 'salt.php';
             if ($namespace === 'salt' && is_readable($file)) {
-                $fs    = new Filesystem(array('dir' => 'data'));
+                $fs    = new Filesystem(['dir' => 'data']);
                 $value = $fs->getValue('salt');
                 $this->setValue($value, 'salt');
                 if (!unlink($file)) {
@@ -416,7 +416,7 @@ class Database extends AbstractData
                 $this->_last_cache = Json::decode($value);
             } catch (JsonException $e) {
                 error_log('Error decoding JSON from table "config", row "traffic_limiter": ' . $e->getMessage());
-                $this->_last_cache = array();
+                $this->_last_cache = [];
             }
             if (array_key_exists($key, $this->_last_cache)) {
                 return $this->_last_cache[$key];
@@ -440,11 +440,11 @@ class Database extends AbstractData
                 '" WHERE "expiredate" < ? AND "expiredate" != ? ' .
                 ($this->_type === 'oci' ? 'FETCH NEXT ? ROWS ONLY' : 'LIMIT ?')
             );
-            $statement->execute(array(time(), 0, $batchsize));
+            $statement->execute([time(), 0, $batchsize]);
             return $statement->fetchAll(PDO::FETCH_COLUMN, 0);
         } catch (PDOException $e) {
             error_log('Error while attempting to find expired pastes in the database: ' . $e->getMessage());
-            return array();
+            return [];
         }
     }
 
@@ -508,7 +508,7 @@ class Database extends AbstractData
             }
         } elseif ($this->_type === 'oci') {
             // workaround for https://bugs.php.net/bug.php?id=46728
-            $result = array();
+            $result = [];
             while ($row = $statement->fetch(PDO::FETCH_ASSOC)) {
                 $result[] = array_map('PrivateBin\Data\Database::_sanitizeClob', $row);
             }
@@ -576,7 +576,7 @@ class Database extends AbstractData
         try {
             $row = $this->_select(
                 'SELECT "value" FROM "' . $this->_sanitizeIdentifier('config') .
-                '" WHERE "id" = ?', array($key), true
+                '" WHERE "id" = ?', [$key], true
             );
         } catch (PDOException $e) {
             error_log('Error while attempting to fetch configuration key "' . $key . '" in the database: ' . $e->getMessage());
@@ -604,7 +604,7 @@ class Database extends AbstractData
                 $main_key = ' PRIMARY KEY';
                 break;
         }
-        return array($main_key, $after_key);
+        return [$main_key, $after_key];
     }
 
     /**
@@ -743,7 +743,7 @@ class Database extends AbstractData
         $this->_exec(
             'INSERT INTO "' . $this->_sanitizeIdentifier('config') .
             '" VALUES(?,?)',
-            array('VERSION', Controller::VERSION)
+            ['VERSION', Controller::VERSION]
         );
     }
 
@@ -788,7 +788,7 @@ class Database extends AbstractData
         $supportsDropColumn = true;
         if ($this->_type === 'sqlite') {
             try {
-                $row                = $this->_select('SELECT sqlite_version() AS "v"', array(), true);
+                $row                = $this->_select('SELECT sqlite_version() AS "v"', [], true);
                 $supportsDropColumn = (bool) version_compare($row['v'], '3.35.0', '>=');
             } catch (PDOException $e) {
                 $supportsDropColumn = false;
@@ -902,7 +902,7 @@ class Database extends AbstractData
         $this->_exec(
             'UPDATE "' . $this->_sanitizeIdentifier('config') .
             '" SET "value" = ? WHERE "id" = ?',
-            array(Controller::VERSION, 'VERSION')
+            [Controller::VERSION, 'VERSION']
         );
     }
 }

+ 4 - 4
lib/Data/Filesystem.php

@@ -13,7 +13,7 @@ namespace PrivateBin\Data;
 
 use DirectoryIterator;
 use GlobIterator;
-use PrivateBin\Exception\JsonException;
+use JsonException;
 use PrivateBin\Json;
 
 /**
@@ -205,7 +205,7 @@ class Filesystem extends AbstractData
      */
     public function readComments($pasteid)
     {
-        $comments = array();
+        $comments = [];
         $discdir  = $this->_dataid2discussionpath($pasteid);
         if (is_dir($discdir)) {
             foreach (new DirectoryIterator($discdir) as $file) {
@@ -359,7 +359,7 @@ class Filesystem extends AbstractData
      */
     protected function _getExpiredPastes($batchsize)
     {
-        $pastes = array();
+        $pastes = [];
         $count  = 0;
         $opened = 0;
         $limit  = $batchsize * 10; // try at most 10 times $batchsize pastes before giving up
@@ -388,7 +388,7 @@ class Filesystem extends AbstractData
      */
     public function getAllPastes()
     {
-        $pastes = array();
+        $pastes = [];
         foreach (new GlobIterator($this->_path . self::PASTE_FILE_PATTERN) as $file) {
             if ($file->isFile()) {
                 $pastes[] = $file->getBasename('.php');

+ 22 - 22
lib/Data/GoogleCloudStorage.php

@@ -15,7 +15,7 @@ use Exception;
 use Google\Cloud\Core\Exception\NotFoundException;
 use Google\Cloud\Storage\Bucket;
 use Google\Cloud\Storage\StorageClient;
-use PrivateBin\Exception\JsonException;
+use JsonException;
 use PrivateBin\Json;
 
 class GoogleCloudStorage extends AbstractData
@@ -74,8 +74,8 @@ class GoogleCloudStorage extends AbstractData
         }
 
         $this->_client = class_exists('StorageClientStub', false) ?
-            new \StorageClientStub(array()) :
-            new StorageClient(array('suppressKeyFileNotice' => true));
+            new \StorageClientStub([]) :
+            new StorageClient(['suppressKeyFileNotice' => true]);
         if (isset($bucket)) {
             $this->_bucket = $this->_client->bucket($bucket);
         }
@@ -107,20 +107,20 @@ class GoogleCloudStorage extends AbstractData
      */
     private function _upload($key, &$payload)
     {
-        $metadata = $payload['meta'] ?? array();
+        $metadata = $payload['meta'] ?? [];
         unset($metadata['salt']);
         foreach ($metadata as $k => $v) {
             $metadata[$k] = strval($v);
         }
         try {
-            $data = array(
+            $data = [
                 'name'          => $key,
                 'chunkSize'     => 262144,
-                'metadata'      => array(
+                'metadata'      => [
                     'content-type' => 'application/json',
                     'metadata'     => $metadata,
-                ),
-            );
+                ],
+            ];
             if (!$this->_uniformacl) {
                 $data['predefinedAcl'] = 'private';
             }
@@ -171,7 +171,7 @@ class GoogleCloudStorage extends AbstractData
         $name = $this->_getKey($pasteid);
 
         try {
-            foreach ($this->_bucket->objects(array('prefix' => $name . '/discussion/')) as $comment) {
+            foreach ($this->_bucket->objects(['prefix' => $name . '/discussion/']) as $comment) {
                 try {
                     $this->_bucket->object($comment->name())->delete();
                 } catch (NotFoundException $e) {
@@ -215,16 +215,16 @@ class GoogleCloudStorage extends AbstractData
      */
     public function readComments($pasteid)
     {
-        $comments = array();
+        $comments = [];
         $prefix   = $this->_getKey($pasteid) . '/discussion/';
         try {
-            foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $key) {
+            foreach ($this->_bucket->objects(['prefix' => $prefix]) as $key) {
                 $data            = $this->_bucket->object($key->name())->downloadAsString();
                 try {
                     $comment = Json::decode($data);
                 } catch (JsonException $e) {
                     error_log('failed to read comment from ' . $key->name() . ', ' . $e->getMessage());
-                    $comment = array();
+                    $comment = [];
                 }
                 $comment['id']   = basename($key->name());
                 $slot            = $this->getOpenSlot($comments, (int) $comment['meta']['created']);
@@ -253,7 +253,7 @@ class GoogleCloudStorage extends AbstractData
     {
         $path = 'config/' . $namespace;
         try {
-            foreach ($this->_bucket->objects(array('prefix' => $path)) as $object) {
+            foreach ($this->_bucket->objects(['prefix' => $path]) as $object) {
                 $name = $object->name();
                 if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') {
                     continue;
@@ -285,19 +285,19 @@ class GoogleCloudStorage extends AbstractData
             $key = 'config/' . $namespace . '/' . $key;
         }
 
-        $metadata = array('namespace' => $namespace);
+        $metadata = ['namespace' => $namespace];
         if ($namespace !== 'salt') {
             $metadata['value'] = strval($value);
         }
         try {
-            $data = array(
+            $data = [
                 'name'          => $key,
                 'chunkSize'     => 262144,
-                'metadata'      => array(
+                'metadata'      => [
                     'content-type' => 'application/json',
                     'metadata'     => $metadata,
-                ),
-            );
+                ],
+            ];
             if (!$this->_uniformacl) {
                 $data['predefinedAcl'] = 'private';
             }
@@ -333,7 +333,7 @@ class GoogleCloudStorage extends AbstractData
      */
     protected function _getExpiredPastes($batchsize)
     {
-        $expired = array();
+        $expired = [];
 
         $now    = time();
         $prefix = $this->_prefix;
@@ -341,7 +341,7 @@ class GoogleCloudStorage extends AbstractData
             $prefix .= '/';
         }
         try {
-            foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $object) {
+            foreach ($this->_bucket->objects(['prefix' => $prefix]) as $object) {
                 $expire_at = $object->info()['metadata']['expire_date'] ?? '';
                 if (is_numeric($expire_at) && intval($expire_at) < $now) {
                     array_push($expired, basename($object->name()));
@@ -362,14 +362,14 @@ class GoogleCloudStorage extends AbstractData
      */
     public function getAllPastes()
     {
-        $pastes = array();
+        $pastes = [];
         $prefix = $this->_prefix;
         if (!empty($prefix)) {
             $prefix .= '/';
         }
 
         try {
-            foreach ($this->_bucket->objects(array('prefix' => $prefix)) as $object) {
+            foreach ($this->_bucket->objects(['prefix' => $prefix]) as $object) {
                 $candidate = substr($object->name(), strlen($prefix));
                 if (!str_contains($candidate, '/')) {
                     $pastes[] = $candidate;

+ 32 - 32
lib/Data/S3Storage.php

@@ -37,7 +37,7 @@ namespace PrivateBin\Data;
 
 use Aws\S3\Exception\S3Exception;
 use Aws\S3\S3Client;
-use PrivateBin\Exception\JsonException;
+use JsonException;
 use PrivateBin\Json;
 
 class S3Storage extends AbstractData
@@ -56,7 +56,7 @@ class S3Storage extends AbstractData
      * @access private
      * @var    array
      */
-    private $_options = array();
+    private $_options = [];
 
     /**
      * S3 bucket
@@ -85,7 +85,7 @@ class S3Storage extends AbstractData
         // AWS SDK will try to load credentials from environment if credentials are not passed via configuration
         // ref: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/guide_credentials.html#default-credential-chain
         if (isset($options['accesskey']) && isset($options['secretkey'])) {
-            $this->_options['credentials'] = array();
+            $this->_options['credentials'] = [];
 
             $this->_options['credentials']['key']    = $options['accesskey'];
             $this->_options['credentials']['secret'] = $options['secretkey'];
@@ -121,15 +121,15 @@ class S3Storage extends AbstractData
      */
     private function _listAllObjects($prefix)
     {
-        $allObjects = array();
-        $options    = array(
+        $allObjects = [];
+        $options    = [
             'Bucket' => $this->_bucket,
             'Prefix' => $prefix,
-        );
+        ];
 
         do {
             $objectsListResponse = $this->_client->listObjects($options);
-            $objects             = $objectsListResponse['Contents'] ?? array();
+            $objects             = $objectsListResponse['Contents'] ?? [];
             foreach ($objects as $object) {
                 $allObjects[]      = $object;
                 $options['Marker'] = $object['Key'];
@@ -165,19 +165,19 @@ class S3Storage extends AbstractData
      */
     private function _upload($key, &$payload)
     {
-        $metadata = $payload['meta'] ?? array();
+        $metadata = $payload['meta'] ?? [];
         unset($metadata['salt']);
         foreach ($metadata as $k => $v) {
             $metadata[$k] = strval($v);
         }
         try {
-            $this->_client->putObject(array(
+            $this->_client->putObject([
                 'Bucket'      => $this->_bucket,
                 'Key'         => $key,
                 'Body'        => Json::encode($payload),
                 'ContentType' => 'application/json',
                 'Metadata'    => $metadata,
-            ));
+            ]);
             return true;
         } catch (S3Exception $e) {
             error_log('failed to upload ' . $key . ' to ' . $this->_bucket . ', ' .
@@ -206,10 +206,10 @@ class S3Storage extends AbstractData
     public function read($pasteid)
     {
         try {
-            $object = $this->_client->getObject(array(
+            $object = $this->_client->getObject([
                 'Bucket' => $this->_bucket,
                 'Key'    => $this->_getKey($pasteid),
-            ));
+            ]);
             $data = $object['Body']->getContents();
             return Json::decode($data);
         } catch (S3Exception $e) {
@@ -232,10 +232,10 @@ class S3Storage extends AbstractData
             $comments = $this->_listAllObjects($name . '/discussion/');
             foreach ($comments as $comment) {
                 try {
-                    $this->_client->deleteObject(array(
+                    $this->_client->deleteObject([
                         'Bucket' => $this->_bucket,
                         'Key'    => $comment['Key'],
-                    ));
+                    ]);
                 } catch (S3Exception $e) {
                     // ignore if already deleted.
                 }
@@ -245,10 +245,10 @@ class S3Storage extends AbstractData
         }
 
         try {
-            $this->_client->deleteObject(array(
+            $this->_client->deleteObject([
                 'Bucket' => $this->_bucket,
                 'Key'    => $name,
-            ));
+            ]);
         } catch (S3Exception $e) {
             // ignore if already deleted
         }
@@ -279,15 +279,15 @@ class S3Storage extends AbstractData
      */
     public function readComments($pasteid)
     {
-        $comments = array();
+        $comments = [];
         $prefix   = $this->_getKey($pasteid) . '/discussion/';
         try {
             $entries = $this->_listAllObjects($prefix);
             foreach ($entries as $entry) {
-                $object = $this->_client->getObject(array(
+                $object = $this->_client->getObject([
                     'Bucket' => $this->_bucket,
                     'Key'    => $entry['Key'],
-                ));
+                ]);
                 $data             = $object['Body']->getContents();
                 $body             = JSON::decode($data);
                 $items            = explode('/', $entry['Key']);
@@ -328,17 +328,17 @@ class S3Storage extends AbstractData
                 if (strlen($name) > strlen($path) && substr($name, strlen($path), 1) !== '/') {
                     continue;
                 }
-                $head = $this->_client->headObject(array(
+                $head = $this->_client->headObject([
                     'Bucket' => $this->_bucket,
                     'Key'    => $name,
-                ));
+                ]);
                 $value = $head->get('Metadata')['value'] ?? '';
                 if (is_numeric($value) && intval($value) < $time) {
                     try {
-                        $this->_client->deleteObject(array(
+                        $this->_client->deleteObject([
                             'Bucket' => $this->_bucket,
                             'Key'    => $name,
-                        ));
+                        ]);
                     } catch (S3Exception $e) {
                         // deleted by another instance.
                     }
@@ -367,18 +367,18 @@ class S3Storage extends AbstractData
             $key = $prefix . 'config/' . $namespace . '/' . $key;
         }
 
-        $metadata = array('namespace' => $namespace);
+        $metadata = ['namespace' => $namespace];
         if ($namespace !== 'salt') {
             $metadata['value'] = strval($value);
         }
         try {
-            $this->_client->putObject(array(
+            $this->_client->putObject([
                 'Bucket'      => $this->_bucket,
                 'Key'         => $key,
                 'Body'        => $value,
                 'ContentType' => 'application/json',
                 'Metadata'    => $metadata,
-            ));
+            ]);
         } catch (S3Exception $e) {
             error_log('failed to set key ' . $key . ' to ' . $this->_bucket . ', ' .
                 trim(preg_replace('/\s\s+/', ' ', $e->getMessage())));
@@ -404,10 +404,10 @@ class S3Storage extends AbstractData
         }
 
         try {
-            $object = $this->_client->getObject(array(
+            $object = $this->_client->getObject([
                 'Bucket' => $this->_bucket,
                 'Key'    => $key,
-            ));
+            ]);
             return $object['Body']->getContents();
         } catch (S3Exception $e) {
             return '';
@@ -419,7 +419,7 @@ class S3Storage extends AbstractData
      */
     protected function _getExpiredPastes($batchsize)
     {
-        $expired = array();
+        $expired = [];
         $now     = time();
         $prefix  = $this->_prefix;
         if (!empty($prefix)) {
@@ -428,10 +428,10 @@ class S3Storage extends AbstractData
 
         try {
             foreach ($this->_listAllObjects($prefix) as $object) {
-                $head = $this->_client->headObject(array(
+                $head = $this->_client->headObject([
                     'Bucket' => $this->_bucket,
                     'Key'    => $object['Key'],
-                ));
+                ]);
                 $expire_at = $head->get('Metadata')['expire_date'] ?? '';
                 if (is_numeric($expire_at) && intval($expire_at) < $now) {
                     array_push($expired, $object['Key']);
@@ -452,7 +452,7 @@ class S3Storage extends AbstractData
      */
     public function getAllPastes()
     {
-        $pastes = array();
+        $pastes = [];
         $prefix = $this->_prefix;
         if (!empty($prefix)) {
             $prefix .= '/';

+ 0 - 38
lib/Exception/JsonException.php

@@ -1,38 +0,0 @@
-<?php declare(strict_types=1);
-/**
- * PrivateBin
- *
- * a zero-knowledge paste bin
- *
- * @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
- */
-
-namespace PrivateBin\Exception;
-
-use Exception;
-
-/**
- * JsonException
- *
- * An Exception representing JSON en- or decoding errors.
- */
-class JsonException extends Exception
-{
-    /**
-     * Exception constructor with mandatory JSON error code.
-     *
-     * @access public
-     * @param  int $code
-     */
-    public function __construct(int $code)
-    {
-        $message = 'A JSON error occurred';
-        if (function_exists('json_last_error_msg')) {
-            $message .= ': ' . json_last_error_msg();
-        }
-        $message .= ' (' . $code . ')';
-        parent::__construct($message, 90);
-    }
-}

+ 2 - 2
lib/Filter.php

@@ -46,7 +46,7 @@ class Filter
             default:
                 $unit = rtrim($matches[2], 's');
         }
-        return I18n::_(array('%d ' . $unit, '%d ' . $unit . 's'), (int) $matches[1]);
+        return I18n::_(['%d ' . $unit, '%d ' . $unit . 's'], (int) $matches[1]);
     }
 
     /**
@@ -59,7 +59,7 @@ class Filter
      */
     public static function formatHumanReadableSize($size)
     {
-        $iec = array('B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB');
+        $iec = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
         $i   = 0;
         while (($size / 1000) >= 1) {
             $size = $size / 1000;

+ 21 - 6
lib/FormatV2.php

@@ -31,7 +31,7 @@ class FormatV2
      */
     public static function isValid(&$message, $isComment = false)
     {
-        $required_keys = array('adata', 'v', 'ct');
+        $required_keys = ['adata', 'v', 'ct'];
         if ($isComment) {
             $required_keys[] = 'pasteid';
             $required_keys[] = 'parentid';
@@ -56,7 +56,21 @@ class FormatV2
             return false;
         }
 
-        $cipherParams = $isComment ? $message['adata'] : $message['adata'][0];
+        $cipherParams = $isComment ? $message['adata'] : ($message['adata'][0] ?? null);
+
+        // Make sure the cipher parameters are a properly sized array.
+        if (!is_array($cipherParams) || count($cipherParams) < 8) {
+            return false;
+        }
+
+        // Make sure the ciphertext and the cipher parameters used in the
+        // string operations below are actually strings, so that malformed
+        // input yields "Invalid data." instead of a fatal type error.
+        if (!is_string($message['ct']) ||
+            !is_string($cipherParams[0] ?? null) ||
+            !is_string($cipherParams[1] ?? null)) {
+            return false;
+        }
 
         // Make sure some fields are base64 data:
         // - initialization vector
@@ -92,11 +106,11 @@ class FormatV2
             return false;
         }
         // - key size
-        if (!in_array($cipherParams[3], array(128, 192, 256), true)) {
+        if (!in_array($cipherParams[3], [128, 192, 256], true)) {
             return false;
         }
         // - tag size
-        if (!in_array($cipherParams[4], array(64, 96, 128), true)) {
+        if (!in_array($cipherParams[4], [64, 96, 128], true)) {
             return false;
         }
         // - algorithm, must be AES
@@ -104,11 +118,11 @@ class FormatV2
             return false;
         }
         // - mode
-        if (!in_array($cipherParams[6], array('ctr', 'cbc', 'gcm'), true)) {
+        if (!in_array($cipherParams[6], ['ctr', 'cbc', 'gcm'], true)) {
             return false;
         }
         // - compression
-        if (!in_array($cipherParams[7], array('zlib', 'none'), true)) {
+        if (!in_array($cipherParams[7], ['zlib', 'none'], true)) {
             return false;
         }
 
@@ -119,6 +133,7 @@ class FormatV2
 
         // require only the key 'expire' in the metadata of pastes
         if (!$isComment && (
+            !is_array($message['meta']) ||
             count($message['meta']) === 0 ||
             !array_key_exists('expire', $message['meta']) ||
             count($message['meta']) > 1

+ 10 - 10
lib/I18n.php

@@ -46,7 +46,7 @@ class I18n
      * @static
      * @var    array
      */
-    protected static $_languageLabels = array();
+    protected static $_languageLabels = [];
 
     /**
      * available languages
@@ -55,7 +55,7 @@ class I18n
      * @static
      * @var    array
      */
-    protected static $_availableLanguages = array();
+    protected static $_availableLanguages = [];
 
     /**
      * path to language files
@@ -73,7 +73,7 @@ class I18n
      * @static
      * @var    array
      */
-    protected static $_translations = array();
+    protected static $_translations = [];
 
     /**
      * translate a string, alias for translate()
@@ -183,7 +183,7 @@ class I18n
 
         // load translations
         if (self::$_language === 'en') {
-            self::$_translations = array();
+            self::$_translations = [];
         } else {
             $data                = file_get_contents(self::_getPath(self::$_language . '.json'));
             self::$_translations = Json::decode($data);
@@ -225,7 +225,7 @@ class I18n
      */
     public static function getBrowserLanguages()
     {
-        $languages = array();
+        $languages = [];
         if (array_key_exists('HTTP_ACCEPT_LANGUAGE', $_SERVER)) {
             $languageRanges = explode(',', trim($_SERVER['HTTP_ACCEPT_LANGUAGE']));
             foreach ($languageRanges as $languageRange) {
@@ -239,7 +239,7 @@ class I18n
                         $match[2] = (string) floatval($match[2]);
                     }
                     if (!isset($languages[$match[2]])) {
-                        $languages[$match[2]] = array();
+                        $languages[$match[2]] = [];
                     }
                     $languages[$match[2]][] = strtolower($match[1]);
                 }
@@ -272,7 +272,7 @@ class I18n
      * @throws JsonException
      * @return array
      */
-    public static function getLanguageLabels($languages = array())
+    public static function getLanguageLabels($languages = [])
     {
         $file = self::_getPath('languages.json');
         if (count(self::$_languageLabels) === 0 && is_readable($file)) {
@@ -294,7 +294,7 @@ class I18n
      */
     public static function isRtl()
     {
-        return in_array(self::$_language, array('ar', 'he'));
+        return in_array(self::$_language, ['ar', 'he']);
     }
 
     /**
@@ -402,7 +402,7 @@ class I18n
      */
     protected static function _getMatchingLanguage($acceptedLanguages, $availableLanguages)
     {
-        $matches = array();
+        $matches = [];
         $any     = false;
         foreach ($acceptedLanguages as $acceptedQuality => $acceptedValues) {
             $acceptedQuality = floatval($acceptedQuality);
@@ -419,7 +419,7 @@ class I18n
                     if ($matchingGrade > 0) {
                         $q = (string) ($acceptedQuality * $availableQuality * $matchingGrade);
                         if (!isset($matches[$q])) {
-                            $matches[$q] = array();
+                            $matches[$q] = [];
                         }
                         if (!in_array($availableValue, $matches[$q])) {
                             $matches[$q][] = $availableValue;

+ 2 - 24
lib/Json.php

@@ -11,8 +11,6 @@
 
 namespace PrivateBin;
 
-use PrivateBin\Exception\JsonException;
-
 /**
  * Json
  *
@@ -31,9 +29,7 @@ class Json
      */
     public static function encode(&$input)
     {
-        $jsonString = json_encode($input);
-        self::_detectError();
-        return $jsonString;
+        return json_encode($input, JSON_THROW_ON_ERROR);
     }
 
     /**
@@ -47,24 +43,6 @@ class Json
      */
     public static function decode(&$input)
     {
-        $output = json_decode($input, true);
-        self::_detectError();
-        return $output;
-    }
-
-    /**
-     * Detects JSON errors and raises an exception if one is found
-     *
-     * @access private
-     * @static
-     * @throws JsonException
-     * @return void
-     */
-    private static function _detectError()
-    {
-        $errorCode = json_last_error();
-        if ($errorCode !== JSON_ERROR_NONE) {
-            throw new JsonException($errorCode);
-        }
+        return json_decode($input, true, 10, JSON_THROW_ON_ERROR);
     }
 }

+ 1 - 1
lib/Model/AbstractModel.php

@@ -50,7 +50,7 @@ abstract class AbstractModel
      * @access protected
      * @var array
      */
-    protected $_data = array('meta' => array());
+    protected $_data = ['meta' => []];
 
     /**
      * Configuration.

+ 5 - 5
lib/Model/Comment.php

@@ -155,14 +155,14 @@ class Comment extends AbstractModel
                 $identicon = new Identicon();
                 $pngdata   = $identicon->getImageDataUri($hmac, 16);
             } elseif ($icon === 'jdenticon') {
-                $jdenticon = new Jdenticon(array(
+                $jdenticon = new Jdenticon([
                     'hash'  => $hmac,
                     'size'  => 16,
-                    'style' => array(
+                    'style' => [
                         'backgroundColor'   => '#fff0', // fully transparent, for dark mode
                         'padding'           => 0,
-                    ),
-                ));
+                    ],
+                ]);
                 $pngdata   = $jdenticon->getImageDataUri('png');
             } elseif ($icon === 'vizhash') {
                 $vh      = new Vizhash16x16();
@@ -172,7 +172,7 @@ class Comment extends AbstractModel
             }
             if (!empty($pngdata)) {
                 if (!array_key_exists('meta', $data)) {
-                    $data['meta'] = array();
+                    $data['meta'] = [];
                 }
                 $data['meta']['icon'] = $pngdata;
             }

+ 2 - 2
lib/Persistence/TrafficLimiter.php

@@ -209,9 +209,9 @@ class TrafficLimiter extends AbstractPersistence
             }
             return true;
         }
-        throw new TranslatedException(array(
+        throw new TranslatedException([
             'Please wait %d seconds between each post.',
             self::$_limit,
-        ));
+        ]);
     }
 }

+ 4 - 4
lib/Proxy/AbstractProxy.php

@@ -11,8 +11,8 @@
 
 namespace PrivateBin\Proxy;
 
+use JsonException;
 use PrivateBin\Configuration;
-use PrivateBin\Exception\JsonException;
 use PrivateBin\Json;
 
 /**
@@ -71,14 +71,14 @@ abstract class AbstractProxy
 
         $data = file_get_contents($proxyUrl, false,
             stream_context_create(
-                array(
+                [
                     'http' => $this->_getProxyPayload($conf, $link),
-                )
+                ]
             )
         );
 
         if ($data === false) {
-            $http_response_header = $http_response_header ?? array();
+            $http_response_header = $http_response_header ?? [];
             $statusCode           = '';
             if (!empty($http_response_header) && preg_match('/HTTP\/\d+\.\d+\s+(\d+)/', $http_response_header[0], $matches)) {
                 $statusCode = $matches[1];

+ 6 - 6
lib/Proxy/ShlinkProxy.php

@@ -11,8 +11,8 @@
 
 namespace PrivateBin\Proxy;
 
+use JsonException;
 use PrivateBin\Configuration;
-use PrivateBin\Exception\JsonException;
 use PrivateBin\Json;
 
 /**
@@ -45,20 +45,20 @@ class ShlinkProxy extends AbstractProxy
     {
         $shlink_api_key = $conf->getKey('apikey', 'shlink');
 
-        $body = array(
+        $body = [
             'longUrl' => $link,
-        );
+        ];
 
         try {
-            return array(
+            return [
                 'method'  => 'POST',
                 'header'  => "Content-Type: application/json\r\n" .
                             'X-Api-Key: ' . $shlink_api_key . "\r\n",
                 'content' => Json::encode($body),
-            );
+            ];
         } catch (JsonException $e) {
             error_log('[' . get_class($this) . '] Error encoding body: ' . $e->getMessage());
-            return array();
+            return [];
         }
     }
 

+ 5 - 5
lib/Proxy/YourlsProxy.php

@@ -42,18 +42,18 @@ class YourlsProxy extends AbstractProxy
      */
     protected function _getProxyPayload(Configuration $conf, string $link): array
     {
-        return array(
+        return [
             'method'  => 'POST',
             'header'  => "Content-Type: application/x-www-form-urlencoded\r\n",
             'content' => http_build_query(
-                array(
+                [
                     'signature' => $conf->getKey('signature', 'yourls'),
                     'format'    => 'json',
                     'action'    => 'shorturl',
                     'url'       => $link,
-                )
+                ]
             ),
-        );
+        ];
     }
 
     /**
@@ -66,7 +66,7 @@ class YourlsProxy extends AbstractProxy
     protected function _extractShortUrl(array $data): ?string
     {
         if ((int) ($data['statusCode'] ?? 0) === 200) {
-            return $data['shorturl'] ?? 0;
+            return $data['shorturl'] ?? null;
         }
         return null;
     }

+ 14 - 11
lib/Request.php

@@ -11,7 +11,7 @@
 
 namespace PrivateBin;
 
-use PrivateBin\Exception\JsonException;
+use JsonException;
 use PrivateBin\Model\Paste;
 
 /**
@@ -64,7 +64,7 @@ class Request
      * @access private
      * @var array
      */
-    private $_params = array();
+    private $_params = [];
 
     /**
      * If we are in a JSON API context
@@ -113,19 +113,24 @@ class Request
                 try {
                     $data          = file_get_contents(self::$_inputStream);
                     $this->_params = Json::decode($data);
+                    // a valid JSON scalar (number, bool or string) decodes
+                    // without error, but is not a usable set of parameters
+                    if (!is_array($this->_params)) {
+                        $this->_params = [];
+                    }
                 } catch (JsonException $e) {
                     // ignore error, $this->_params will remain empty
                 }
                 break;
             default:
-                $this->_params = filter_var_array($_GET, array(
+                $this->_params = filter_var_array($_GET, [
                     'deletetoken'      => FILTER_SANITIZE_SPECIAL_CHARS,
                     'jsonld'           => FILTER_SANITIZE_SPECIAL_CHARS,
                     'link'             => FILTER_SANITIZE_URL,
                     'pasteid'          => FILTER_SANITIZE_SPECIAL_CHARS,
                     'shortenviayourls' => FILTER_SANITIZE_SPECIAL_CHARS,
                     'shortenviashlink' => FILTER_SANITIZE_SPECIAL_CHARS,
-                ), false);
+                ], false);
         }
         if (
             !array_key_exists('pasteid', $this->_params) &&
@@ -175,10 +180,10 @@ class Request
      */
     public function getData()
     {
-        $data = array(
+        $data = [
             'adata' => $this->getParam('adata'),
-        );
-        $required_keys = array('v', 'ct');
+        ];
+        $required_keys = ['v', 'ct'];
         $meta          = $this->getParam('meta');
         if (empty($meta)) {
             $required_keys[] = 'pasteid';
@@ -189,8 +194,6 @@ class Request
         foreach ($required_keys as $key) {
             $data[$key] = $this->getParam($key, $key === 'v' ? 1 : '');
         }
-        // forcing a cast to int or float
-        $data['v'] = $data['v'] + 0;
         return $data;
     }
 
@@ -278,7 +281,7 @@ class Request
 
         // advanced case: media type negotiation
         if (!empty($acceptHeader)) {
-            $mediaTypes = array();
+            $mediaTypes = [];
             foreach (explode(',', trim($acceptHeader)) as $mediaTypeRange) {
                 if (preg_match(
                     '#(\*/\*|[a-z\-]+/[a-z\-+*]+(?:\s*;\s*[^q]\S*)*)(?:\s*;\s*q\s*=\s*(0(?:\.\d{0,3})|1(?:\.0{0,3})))?#',
@@ -293,7 +296,7 @@ class Request
                         }
                     }
                     if (!isset($mediaTypes[$match[2]])) {
-                        $mediaTypes[$match[2]] = array();
+                        $mediaTypes[$match[2]] = [];
                     }
                     $mediaTypes[$match[2]][] = strtolower($match[1]);
                 }

+ 1 - 1
lib/TemplateSwitcher.php

@@ -34,7 +34,7 @@ class TemplateSwitcher
      * @static
      * @var    array
      */
-    protected static $_availableTemplates = array();
+    protected static $_availableTemplates = [];
 
     /**
      * set available templates

+ 1 - 1
lib/View.php

@@ -26,7 +26,7 @@ class View
      * @access private
      * @var    array
      */
-    private $_variables = array();
+    private $_variables = [];
 
     /**
      * assign variables to be used inside of the template

+ 5 - 5
lib/Vizhash16x16.php

@@ -85,7 +85,7 @@ class Vizhash16x16
         $textlen = strlen($text);
 
         // We convert the hash into an array of integers.
-        $this->VALUES = array();
+        $this->VALUES = [];
         for ($i = 0; $i < $textlen; $i = $i + 2) {
             array_push($this->VALUES, hexdec(substr($text, $i, 2)));
         }
@@ -106,7 +106,7 @@ class Vizhash16x16
         if (($this->getInt() % 2) === 0) {
             $op = 'h';
         }
-        $image = $this->degrade($image, $op, array($r0, $g0, $b0), array(0, 0, 0));
+        $image = $this->degrade($image, $op, [$r0, $g0, $b0], [0, 0, 0]);
 
         for ($i = 0; $i < 7; ++$i) {
             $action = $this->getInt();
@@ -186,11 +186,11 @@ class Vizhash16x16
             $size    = imagesy($img);
             $sizeinv = imagesx($img);
         }
-        $diffs = array(
+        $diffs = [
             ($color2[0] - $color1[0]) / $size,
             ($color2[1] - $color1[1]) / $size,
             ($color2[2] - $color1[2]) / $size,
-        );
+        ];
         for ($i = 0; $i < $size; ++$i) {
             $r = $color1[0] + ((int) $diffs[0] * $i);
             $g = $color1[1] + ((int) $diffs[1] * $i);
@@ -223,7 +223,7 @@ class Vizhash16x16
                 imagefilledellipse($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $color);
                 break;
             case 3:
-                $points = array($this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY());
+                $points = [$this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY(), $this->getX(), $this->getY()];
                 version_compare(PHP_VERSION, '8.1', '<') ? imagefilledpolygon($image, $points, 4, $color) : imagefilledpolygon($image, $points, $color);
                 break;
             default:

+ 1 - 1
tpl/bootstrap5.php

@@ -49,7 +49,7 @@ if ($MARKDOWN) :
 <?php
 endif;
 ?>
-		<?php $this->_scriptTag('js/purify-3.4.1.js', 'defer'); ?>
+		<?php $this->_scriptTag('js/purify-3.4.12.js', 'defer'); ?>
 		<?php $this->_scriptTag('js/legacy.js', 'defer'); ?>
 		<?php $this->_scriptTag('js/privatebin.js', 'defer'); ?>
 		<!-- icon -->

+ 101 - 101
tst/Bootstrap.php

@@ -47,9 +47,9 @@ class Helper
      *
      * @var array
      */
-    private static $pasteV2 = array(
-        'adata' => array(
-            array(
+    private static $pasteV2 = [
+        'adata' => [
+            [
                 'gMSNoLOk4z0RnmsYwXZ8mw==',
                 'TZO+JWuIuxs=',
                 100000,
@@ -58,17 +58,17 @@ class Helper
                 'aes',
                 'gcm',
                 'zlib',
-            ),
+            ],
             'plaintext',
             1,
             0,
-        ),
-        'meta' => array(
+        ],
+        'meta' => [
             'expire'  => '5min',
-        ),
+        ],
         'v'  => 2,
         'ct' => 'ME5JF/YBEijp2uYMzLZozbKtWc5wfy6R59NBb7SmRig=',
-    );
+    ];
 
     /**
      * example ID of a comment
@@ -82,17 +82,17 @@ class Helper
      *
      * @var array
      */
-    private static $commentV2 = array(
+    private static $commentV2 = [
         'icon'    => 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAABGUlEQVQokWOsl5/94983CNKQMjnxaOePf98MeKwPfNjkLZ3AgARab6b9+PeNEVnDj3/ff/z7ZiHnzsDA8Pv7H2TVPJw8EAYLAwb48OaVgIgYKycLsrYv378wMDB8//qdCVMDRA9EKSsnCwRBxNsepaLboMFlyMDAICAi9uHNK24GITQ/MDAwoNhgIGMLtwGrzegaLjw5jMz9+vUdnN17uwDCQDhJgk0O07yvX9+teDX1x79v6DYIsIjgcgMaYGFgYOBg4kJx2JejkAiBxAw+PzAwMNz4dp6wDXDw4MdNNOl0rWYsNkD89OLXI/xmo9sgzatJjAYmBgYGDiauD3/ePP18nVgb4MF89+M5ZX6js293wUMpnr8KTQMAxsCJnJ30apMAAAAASUVORK5CYII=',
         'created' => 1344803528,
-    );
+    ];
 
     /**
      * JS files and their SRI hashes
      *
      * @var array
      */
-    private static $hashes = array();
+    private static $hashes = [];
 
     /**
      * get example paste ID
@@ -110,7 +110,7 @@ class Helper
      * @param  array $meta
      * @return array
      */
-    public static function getPaste(array $meta = array()): array
+    public static function getPaste(array $meta = []): array
     {
         $example                 = self::$pasteV2;
         $example['meta']['salt'] = ServerSalt::generate();
@@ -124,10 +124,10 @@ class Helper
      * @param  array $meta
      * @return array
      */
-    public static function getPastePost(array $meta = array()): array
+    public static function getPastePost(array $meta = []): array
     {
         $example         = self::getPaste($meta);
-        $example['meta'] = array('expire' => $example['meta']['expire']);
+        $example['meta'] = ['expire' => $example['meta']['expire']];
         return $example;
     }
 
@@ -137,7 +137,7 @@ class Helper
      * @param  array $meta
      * @return string
      */
-    public static function getPasteJson(array $meta = array()): string
+    public static function getPasteJson(array $meta = []): string
     {
         return json_encode(self::getPastePost($meta));
     }
@@ -158,7 +158,7 @@ class Helper
      * @param  array $meta
      * @return array
      */
-    public static function getComment(array $meta = array()): array
+    public static function getComment(array $meta = []): array
     {
         $example            = self::$pasteV2;
         $example['adata']   = $example['adata'][0];
@@ -319,7 +319,7 @@ class Helper
     public static function varExportMin($var, $return = false): string
     {
         if (is_array($var)) {
-            $toImplode = array();
+            $toImplode = [];
             foreach ($var as $key => $value) {
                 $toImplode[] = var_export($key, true) . ' => ' . self::varExportMin($value, true);
             }
@@ -383,12 +383,12 @@ class BucketStub extends Bucket
     private $_connection;
     private $_client;
 
-    public function __construct(ConnectionInterface $connection, $name, array $info = array(), $client = null)
+    public function __construct(ConnectionInterface $connection, $name, array $info = [], $client = null)
     {
         $this->_name       = $name;
         $this->_info       = $info;
         $this->_connection = $connection;
-        $this->_objects    = array();
+        $this->_objects    = [];
         $this->_client     = $client;
     }
 
@@ -402,12 +402,12 @@ class BucketStub extends Bucket
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function exists(array $options = array())
+    public function exists(array $options = [])
     {
         return true;
     }
 
-    public function upload($data, array $options = array())
+    public function upload($data, array $options = [])
     {
         if (!is_string($data) || !array_key_exists('name', $options)) {
             throw new BadMethodCallException('not supported by this stub');
@@ -420,27 +420,27 @@ class BucketStub extends Bucket
         $o->setData($data);
     }
 
-    public function uploadAsync($data, array $options = array())
+    public function uploadAsync($data, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getResumableUploader($data, array $options = array())
+    public function getResumableUploader($data, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getStreamableUploader($data, array $options = array())
+    public function getStreamableUploader($data, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function object($name, array $options = array())
+    public function object($name, array $options = [])
     {
         return $this->_objects[$name] ?? new StorageObjectStub($this->_connection, $name, $this, null, $options);
     }
 
-    public function objects(array $options = array())
+    public function objects(array $options = [])
     {
         $prefix = $options['prefix'] ?? '';
 
@@ -452,7 +452,7 @@ class BucketStub extends Bucket
         );
     }
 
-    public function createNotification($topic, array $options = array())
+    public function createNotification($topic, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -462,32 +462,32 @@ class BucketStub extends Bucket
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function notifications(array $options = array())
+    public function notifications(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function delete(array $options = array())
+    public function delete(array $options = [])
     {
         $this->_client->deleteBucket($this->_name);
     }
 
-    public function update(array $options = array())
+    public function update(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function compose(array $sourceObjects, $name, array $options = array())
+    public function compose(array $sourceObjects, $name, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function info(array $options = array())
+    public function info(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function reload(array $options = array())
+    public function reload(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -497,12 +497,12 @@ class BucketStub extends Bucket
         return $this->_name;
     }
 
-    public static function lifecycle(array $lifecycle = array())
+    public static function lifecycle(array $lifecycle = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function currentLifecycle(array $options = array())
+    public function currentLifecycle(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -517,17 +517,17 @@ class BucketStub extends Bucket
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function lockRetentionPolicy(array $options = array())
+    public function lockRetentionPolicy(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function signedUrl($expires, array $options = array())
+    public function signedUrl($expires, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function generateSignedPostPolicyV4($objectName, $expires, array $options = array())
+    public function generateSignedPostPolicyV4($objectName, $expires, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -546,7 +546,7 @@ class StorageObjectStub extends StorageObject
     private $_exists = false;
     private $_connection;
 
-    public function __construct(ConnectionInterface $connection, $name, $bucket, $generation = null, array $info = array(), $encryptionKey = null, $encryptionKeySHA256 = null)
+    public function __construct(ConnectionInterface $connection, $name, $bucket, $generation = null, array $info = [], $encryptionKey = null, $encryptionKeySHA256 = null)
     {
         $this->_name                            = $name;
         $this->_bucket                          = $bucket;
@@ -562,7 +562,7 @@ class StorageObjectStub extends StorageObject
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function exists(array $options = array())
+    public function exists(array $options = [])
     {
         return array_key_exists($this->_name, $this->_bucket->_objects);
     }
@@ -570,7 +570,7 @@ class StorageObjectStub extends StorageObject
     /**
      * @throws NotFoundException
      */
-    public function delete(array $options = array())
+    public function delete(array $options = [])
     {
         if (array_key_exists($this->_name, $this->_bucket->_objects)) {
             unset($this->_bucket->_objects[$this->_name]);
@@ -582,7 +582,7 @@ class StorageObjectStub extends StorageObject
     /**
      * @throws NotFoundException
      */
-    public function update(array $metadata, array $options = array())
+    public function update(array $metadata, array $options = [])
     {
         if (!$this->_exists) {
             throw new NotFoundException('key ' . $this->_name . ' not found.');
@@ -590,17 +590,17 @@ class StorageObjectStub extends StorageObject
         $this->_info = $metadata;
     }
 
-    public function copy($destination, array $options = array())
+    public function copy($destination, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function rewrite($destination, array $options = array())
+    public function rewrite($destination, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function rename($name, array $options = array())
+    public function rename($name, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -608,7 +608,7 @@ class StorageObjectStub extends StorageObject
     /**
      * @throws NotFoundException
      */
-    public function downloadAsString(array $options = array())
+    public function downloadAsString(array $options = [])
     {
         if (!$this->_exists) {
             throw new NotFoundException('key ' . $this->_name . ' not found.');
@@ -616,42 +616,42 @@ class StorageObjectStub extends StorageObject
         return $this->_data;
     }
 
-    public function downloadToFile($path, array $options = array())
+    public function downloadToFile($path, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function downloadAsStream(array $options = array())
+    public function downloadAsStream(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function downloadAsStreamAsync(array $options = array())
+    public function downloadAsStreamAsync(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function signedUrl($expires, array $options = array())
+    public function signedUrl($expires, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function signedUploadUrl($expires, array $options = array())
+    public function signedUploadUrl($expires, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function beginSignedUploadSession(array $options = array())
+    public function beginSignedUploadSession(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function info(array $options = array())
+    public function info(array $options = [])
     {
-        return $this->_info['metadata'] ?? array();
+        return $this->_info['metadata'] ?? [];
     }
 
-    public function reload(array $options = array())
+    public function reload(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -687,52 +687,52 @@ class StorageObjectStub extends StorageObject
  */
 class ConnectionInterfaceStub implements ConnectionInterface
 {
-    public function deleteAcl(array $args = array())
+    public function deleteAcl(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getAcl(array $args = array())
+    public function getAcl(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function listAcl(array $args = array())
+    public function listAcl(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function insertAcl(array $args = array())
+    public function insertAcl(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function patchAcl(array $args = array())
+    public function patchAcl(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function deleteBucket(array $args = array())
+    public function deleteBucket(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function restoreBucket(array $args = array())
+    public function restoreBucket(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getBucket(array $args = array())
+    public function getBucket(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function listBuckets(array $args = array())
+    public function listBuckets(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function insertBucket(array $args = array())
+    public function insertBucket(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -752,122 +752,122 @@ class ConnectionInterfaceStub implements ConnectionInterface
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function patchBucket(array $args = array())
+    public function patchBucket(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function deleteObject(array $args = array())
+    public function deleteObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function restoreObject(array $args = array())
+    public function restoreObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function copyObject(array $args = array())
+    public function copyObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function rewriteObject(array $args = array())
+    public function rewriteObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function moveObject(array $args = array())
+    public function moveObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function composeObject(array $args = array())
+    public function composeObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getObject(array $args = array())
+    public function getObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function headObject(array $args = array()): array
+    public function headObject(array $args = []): array
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function listObjects(array $args = array())
+    public function listObjects(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function patchObject(array $args = array())
+    public function patchObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function downloadObject(array $args = array())
+    public function downloadObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function insertObject(array $args = array())
+    public function insertObject(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getNotification(array $args = array())
+    public function getNotification(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function deleteNotification(array $args = array())
+    public function deleteNotification(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function insertNotification(array $args = array())
+    public function insertNotification(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function listNotifications(array $args = array())
+    public function listNotifications(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getServiceAccount(array $args = array())
+    public function getServiceAccount(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function lockRetentionPolicy(array $args = array())
+    public function lockRetentionPolicy(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function createHmacKey(array $args = array())
+    public function createHmacKey(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function deleteHmacKey(array $args = array())
+    public function deleteHmacKey(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getHmacKey(array $args = array())
+    public function getHmacKey(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function updateHmacKey(array $args = array())
+    public function updateHmacKey(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function listHmacKeys(array $args = array())
+    public function listHmacKeys(array $args = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -880,18 +880,18 @@ class StorageClientStub extends StorageClient
 {
     private $_config         = null;
     private $_connection     = null;
-    private static $_buckets = array();
+    private static $_buckets = [];
 
-    public function __construct(array $config = array())
+    public function __construct(array $config = [])
     {
         $this->_config     = $config;
         $this->_connection =  new ConnectionInterfaceStub();
     }
 
-    public function bucket($name, $userProject = false, array $config = array())
+    public function bucket($name, $userProject = false, array $config = [])
     {
         if (!array_key_exists($name, self::$_buckets)) {
-            self::$_buckets[$name] = new BucketStub($this->_connection, $name, array(), $this);
+            self::$_buckets[$name] = new BucketStub($this->_connection, $name, [], $this);
         }
         return self::$_buckets[$name];
     }
@@ -908,7 +908,7 @@ class StorageClientStub extends StorageClient
         }
     }
 
-    public function buckets(array $options = array())
+    public function buckets(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -923,7 +923,7 @@ class StorageClientStub extends StorageClient
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function signedUrlUploader($uri, $data, array $options = array())
+    public function signedUrlUploader($uri, $data, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
@@ -933,32 +933,32 @@ class StorageClientStub extends StorageClient
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function getServiceAccount(array $options = array())
+    public function getServiceAccount(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function hmacKeys(array $options = array())
+    public function hmacKeys(array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function hmacKey($accessId, $projectId = null, array $metadata = array())
+    public function hmacKey($accessId, $projectId = null, array $metadata = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function createHmacKey($serviceAccountEmail, array $options = array())
+    public function createHmacKey($serviceAccountEmail, array $options = [])
     {
         throw new BadMethodCallException('not supported by this stub');
     }
 
-    public function createBucket($name, array $options = array())
+    public function createBucket($name, array $options = [])
     {
         if (array_key_exists($name, self::$_buckets)) {
             throw new BadRequestException('already exists');
         }
-        $b                     = new BucketStub($this->_connection, $name, array(), $this);
+        $b                     = new BucketStub($this->_connection, $name, [], $this);
         self::$_buckets[$name] = $b;
         return $b;
     }

+ 10 - 10
tst/ControllerTest.php

@@ -18,7 +18,7 @@ class ControllerTest extends TestCase
     {
         /* Setup Routine */
         $this->_path  = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
-        $this->_data  = new Filesystem(array('dir' => $this->_path));
+        $this->_data  = new Filesystem(['dir' => $this->_path]);
         ServerSalt::setStore($this->_data);
         TrafficLimiter::setStore($this->_data);
         $this->reset();
@@ -34,9 +34,9 @@ class ControllerTest extends TestCase
 
     public function reset()
     {
-        $_POST   = array();
-        $_GET    = array();
-        $_SERVER = array();
+        $_POST   = [];
+        $_GET    = [];
+        $_SERVER = [];
         if ($this->_data->exists(Helper::getPasteId())) {
             $this->_data->delete(Helper::getPasteId());
         }
@@ -202,7 +202,7 @@ class ControllerTest extends TestCase
         $options                     = parse_ini_file(CONF, true);
         $options['traffic']['limit'] = 0;
         Helper::createIniFile(CONF, $options);
-        $paste = Helper::getPasteJson(array('expire' => 25));
+        $paste = Helper::getPasteJson(['expire' => 25]);
         $file  = Helper::createTempFile();
         file_put_contents($file, $paste);
         Request::setInputStream($file);
@@ -381,7 +381,7 @@ class ControllerTest extends TestCase
         $options                     = parse_ini_file(CONF, true);
         $options['traffic']['limit'] = 0;
         Helper::createIniFile(CONF, $options);
-        $paste = Helper::getPasteJson(array('expire' => 'foo'));
+        $paste = Helper::getPasteJson(['expire' => 'foo']);
         $file  = Helper::createTempFile();
         file_put_contents($file, $paste);
         Request::setInputStream($file);
@@ -698,7 +698,7 @@ class ControllerTest extends TestCase
      */
     public function testReadExpired()
     {
-        $expiredPaste = Helper::getPaste(array('expire_date' => 1344803344));
+        $expiredPaste = Helper::getPaste(['expire_date' => 1344803344]);
         $this->_data->create(Helper::getPasteId(), $expiredPaste);
         $_SERVER['QUERY_STRING']          = Helper::getPasteId();
         $_GET[Helper::getPasteId()]       = '';
@@ -882,9 +882,9 @@ class ControllerTest extends TestCase
         $this->_data->create(Helper::getPasteId(), $paste);
         $this->assertTrue($this->_data->exists(Helper::getPasteId()), 'paste exists before deleting data');
         $file  = Helper::createTempFile();
-        file_put_contents($file, json_encode(array(
+        file_put_contents($file, json_encode([
             'deletetoken' => 'burnafterreading',
-        )));
+        ]));
         Request::setInputStream($file);
         $_SERVER['QUERY_STRING']          = Helper::getPasteId();
         $_GET[Helper::getPasteId()]       = '';
@@ -904,7 +904,7 @@ class ControllerTest extends TestCase
      */
     public function testDeleteExpired()
     {
-        $expiredPaste = Helper::getPaste(array('expire_date' => 1000));
+        $expiredPaste = Helper::getPaste(['expire_date' => 1000]);
         $this->assertFalse($this->_data->exists(Helper::getPasteId()), 'paste does not exist before being created');
         $this->_data->create(Helper::getPasteId(), $expiredPaste);
         $this->assertTrue($this->_data->exists(Helper::getPasteId()), 'paste exists before deleting data');

+ 6 - 6
tst/ControllerWithDbTest.php

@@ -8,14 +8,14 @@ require_once 'ControllerTest.php';
 
 class ControllerWithDbTest extends ControllerTest
 {
-    private $_options = array(
+    private $_options = [
         'usr' => null,
         'pwd' => null,
-        'opt' => array(
+        'opt' => [
             PDO::ATTR_ERRMODE    => PDO::ERRMODE_EXCEPTION,
             PDO::ATTR_PERSISTENT => true,
-        ),
-    );
+        ],
+    ];
 
     public function setUp(): void
     {
@@ -36,9 +36,9 @@ class ControllerWithDbTest extends ControllerTest
         parent::reset();
         // but then inject a db config
         $options          = parse_ini_file(CONF, true);
-        $options['model'] = array(
+        $options['model'] = [
             'class' => 'Database',
-        );
+        ];
         $options['model_options'] = $this->_options;
         Helper::createIniFile(CONF, $options);
     }

+ 7 - 7
tst/ControllerWithGcsTest.php

@@ -12,11 +12,11 @@ class ControllerWithGcsTest extends ControllerTest
 {
     private static $_client;
     private static $_bucket;
-    private $_options = array();
+    private $_options = [];
 
     public static function setUpBeforeClass(): void
     {
-        $httpClient = new Client(array('debug'=>false));
+        $httpClient = new Client(['debug'=>false]);
         $handler    = HttpHandlerFactory::build($httpClient);
 
         $name     = 'pb-';
@@ -24,7 +24,7 @@ class ControllerWithGcsTest extends ControllerTest
         for ($i = 0; $i < 29; ++$i) {
             $name .= $alphabet[rand(0, strlen($alphabet) - 1)];
         }
-        self::$_client = new StorageClientStub(array());
+        self::$_client = new StorageClientStub([]);
         self::$_bucket = self::$_client->createBucket($name);
     }
 
@@ -35,10 +35,10 @@ class ControllerWithGcsTest extends ControllerTest
         if (!is_dir($this->_path)) {
             mkdir($this->_path);
         }
-        $this->_options = array(
+        $this->_options = [
             'bucket' => self::$_bucket->name(),
             'prefix' => 'pastes',
-        );
+        ];
         $this->_data    = new GoogleCloudStorage($this->_options);
         ServerSalt::setStore($this->_data);
         TrafficLimiter::setStore($this->_data);
@@ -50,9 +50,9 @@ class ControllerWithGcsTest extends ControllerTest
         parent::reset();
         // but then inject a db config
         $options          = parse_ini_file(CONF, true);
-        $options['model'] = array(
+        $options['model'] = [
             'class' => 'GoogleCloudStorage',
-        );
+        ];
         $options['model_options'] = $this->_options;
         Helper::createIniFile(CONF, $options);
     }

+ 36 - 36
tst/Data/DatabaseTest.php

@@ -12,12 +12,12 @@ class DatabaseTest extends TestCase
 
     private $_path;
 
-    private $_options = array(
+    private $_options = [
         'dsn' => 'sqlite::memory:',
         'usr' => null,
         'pwd' => null,
-        'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-    );
+        'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+    ];
 
     public function setUp(): void
     {
@@ -36,7 +36,7 @@ class DatabaseTest extends TestCase
 
     public function testSaltMigration()
     {
-        ServerSalt::setStore(new Filesystem(array('dir' => 'data')));
+        ServerSalt::setStore(new Filesystem(['dir' => 'data']));
         $salt = ServerSalt::get();
         $file = 'data' . DIRECTORY_SEPARATOR . 'salt.php';
         $this->assertFileExists($file, 'ServerSalt got initialized and stored on disk');
@@ -80,10 +80,10 @@ class DatabaseTest extends TestCase
         $comment2['parentid'] = Helper::getPasteId();
         $comment2['meta']     = $meta2;
         $this->assertEquals(
-            array(
+            [
                 $comment1['meta']['created']        => $comment1,
                 $comment2['meta']['created'] . '.1' => $comment2,
-            ),
+            ],
             $this->_model->readComments(Helper::getPasteId())
         );
 
@@ -98,7 +98,7 @@ class DatabaseTest extends TestCase
     {
         $error_log_setting = ini_get('error_log');
         $this->_model->delete(Helper::getPasteId());
-        $original                          = $paste                                = Helper::getPaste(array('expire_date' => 1344803344));
+        $original                          = $paste                                = Helper::getPaste(['expire_date' => 1344803344]);
         $paste['meta']['burnafterreading'] = $original['meta']['burnafterreading'] = true;
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         $this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
@@ -115,15 +115,15 @@ class DatabaseTest extends TestCase
     public function testPurge()
     {
         $this->_model->delete(Helper::getPasteId());
-        $expired = Helper::getPaste(array('expire_date' => 1344803344));
-        $paste   = Helper::getPaste(array('expire_date' => time() + 3600));
-        $keys    = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z');
-        $ids     = array();
+        $expired = Helper::getPaste(['expire_date' => 1344803344]);
+        $paste   = Helper::getPaste(['expire_date' => time() + 3600]);
+        $keys    = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z'];
+        $ids     = [];
         foreach ($keys as $key) {
             $ids[$key] = hash('fnv164', $key);
             $this->_model->delete($ids[$key]);
             $this->assertFalse($this->_model->exists($ids[$key]), "paste $key does not yet exist");
-            if (in_array($key, array('y', 'z'))) {
+            if (in_array($key, ['y', 'z'])) {
                 $this->assertTrue($this->_model->create($ids[$key], $paste), "store $key paste");
             } elseif ($key === 'x') {
                 $data = Helper::getPaste();
@@ -135,7 +135,7 @@ class DatabaseTest extends TestCase
         }
         $this->_model->purge(10);
         foreach ($ids as $key => $id) {
-            if (in_array($key, array('x', 'y', 'z'))) {
+            if (in_array($key, ['x', 'y', 'z'])) {
                 $this->assertTrue($this->_model->exists($id), "paste $key exists after purge");
                 $this->_model->delete($id);
             } else {
@@ -148,7 +148,7 @@ class DatabaseTest extends TestCase
     {
         $error_log_setting = ini_get('error_log');
         $this->_model->delete(Helper::getPasteId());
-        $paste = Helper::getPaste(array('expire' => "Invalid UTF-8 sequence: \xB1\x31"));
+        $paste = Helper::getPaste(['expire' => "Invalid UTF-8 sequence: \xB1\x31"]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         ini_set('error_log', '/dev/null');
         $this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store broken paste');
@@ -161,7 +161,7 @@ class DatabaseTest extends TestCase
         $error_log_setting = ini_get('error_log');
         $this->_model->delete(Helper::getPasteId());
         $data    = Helper::getPaste();
-        $comment = Helper::getComment(array('icon' => "Invalid UTF-8 sequence: \xB1\x31"));
+        $comment = Helper::getComment(['icon' => "Invalid UTF-8 sequence: \xB1\x31"]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         $this->assertTrue($this->_model->create(Helper::getPasteId(), $data), 'store new paste');
         $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
@@ -175,64 +175,64 @@ class DatabaseTest extends TestCase
     public function testGetIbmInstance()
     {
         $this->expectException(PDOException::class);
-        new Database(array(
+        new Database([
             'dsn' => 'ibm:', 'usr' => null, 'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        ));
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ]);
     }
 
     public function testGetInformixInstance()
     {
         $this->expectException(PDOException::class);
-        new Database(array(
+        new Database([
             'dsn' => 'informix:', 'usr' => null, 'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        ));
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ]);
     }
 
     public function testGetMssqlInstance()
     {
         $this->expectException(PDOException::class);
-        new Database(array(
+        new Database([
             'dsn' => 'mssql:', 'usr' => null, 'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        ));
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ]);
     }
 
     public function testGetMysqlInstance()
     {
         $this->expectException(PDOException::class);
-        new Database(array(
+        new Database([
             'dsn' => 'mysql:', 'usr' => null, 'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        ));
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ]);
     }
 
     public function testGetOciInstance()
     {
         $this->expectException(PDOException::class);
-        new Database(array(
+        new Database([
             'dsn' => 'oci:', 'usr' => null, 'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        ));
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ]);
     }
 
     public function testGetPgsqlInstance()
     {
         $this->expectException(PDOException::class);
-        new Database(array(
+        new Database([
             'dsn' => 'pgsql:', 'usr' => null, 'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        ));
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ]);
     }
 
     public function testGetFooInstance()
     {
         $this->expectException(Exception::class);
         $this->expectExceptionCode(5);
-        new Database(array(
+        new Database([
             'dsn' => 'foo:', 'usr' => null, 'pwd' => null, 'opt' => null,
-        ));
+        ]);
     }
 
     public function testMissingDsn()
@@ -309,7 +309,7 @@ class DatabaseTest extends TestCase
 
         // check if version number was upgraded in created configuration table
         $statement = $db->prepare('SELECT value FROM foo_config WHERE id LIKE ?');
-        $statement->execute(array('VERSION'));
+        $statement->execute(['VERSION']);
         $result = $statement->fetch(PDO::FETCH_ASSOC);
         $statement->closeCursor();
         $this->assertEquals(Controller::VERSION, $result['value']);

+ 16 - 16
tst/Data/FilesystemTest.php

@@ -16,7 +16,7 @@ class FilesystemTest extends TestCase
         /* Setup Routine */
         $this->_path        = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
         $this->_invalidPath = $this->_path . DIRECTORY_SEPARATOR . 'bar';
-        $this->_model       = new Filesystem(array('dir' => $this->_path));
+        $this->_model       = new Filesystem(['dir' => $this->_path]);
         if (!is_dir($this->_path)) {
             mkdir($this->_path);
         }
@@ -37,7 +37,7 @@ class FilesystemTest extends TestCase
         $this->_model->delete(Helper::getPasteId());
 
         // storing pastes
-        $paste = Helper::getPaste(array('expire_date' => 1344803344));
+        $paste = Helper::getPaste(['expire_date' => 1344803344]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         $this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
         $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
@@ -53,7 +53,7 @@ class FilesystemTest extends TestCase
         $comment['id']       = Helper::getCommentId();
         $comment['parentid'] = Helper::getPasteId();
         $this->assertEquals(
-            array($comment['meta']['created'] => $comment),
+            [$comment['meta']['created'] => $comment],
             $this->_model->readComments(Helper::getPasteId())
         );
 
@@ -67,7 +67,7 @@ class FilesystemTest extends TestCase
     public function testFileBasedAttachmentStoreWorks()
     {
         $this->_model->delete(Helper::getPasteId());
-        $original = $paste = Helper::getPaste(array('expire_date' => 1344803344));
+        $original = $paste = Helper::getPaste(['expire_date' => 1344803344]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         $this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
         $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
@@ -81,14 +81,14 @@ class FilesystemTest extends TestCase
     public function testPurge()
     {
         mkdir($this->_path . DIRECTORY_SEPARATOR . '00', 0777, true);
-        $expired = Helper::getPaste(array('expire_date' => 1344803344));
-        $paste   = Helper::getPaste(array('expire_date' => time() + 3600));
-        $keys    = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z');
-        $ids     = array();
+        $expired = Helper::getPaste(['expire_date' => 1344803344]);
+        $paste   = Helper::getPaste(['expire_date' => time() + 3600]);
+        $keys    = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z'];
+        $ids     = [];
         foreach ($keys as $key) {
             $ids[$key] = hash('fnv164', $key);
             $this->assertFalse($this->_model->exists($ids[$key]), "paste $key does not yet exist");
-            if (in_array($key, array('x', 'y', 'z'))) {
+            if (in_array($key, ['x', 'y', 'z'])) {
                 $this->assertTrue($this->_model->create($ids[$key], $paste), "store $key paste");
             } elseif ($key === 'x') {
                 $data = Helper::getPaste();
@@ -100,7 +100,7 @@ class FilesystemTest extends TestCase
         }
         $this->_model->purge(10);
         foreach ($ids as $key => $id) {
-            if (in_array($key, array('x', 'y', 'z'))) {
+            if (in_array($key, ['x', 'y', 'z'])) {
                 $this->assertTrue($this->_model->exists($id), "paste $key exists after purge");
                 $this->_model->delete($id);
             } else {
@@ -113,7 +113,7 @@ class FilesystemTest extends TestCase
     {
         $error_log_setting = ini_get('error_log');
         $this->_model->delete(Helper::getPasteId());
-        $paste = Helper::getPaste(array('expire' => "Invalid UTF-8 sequence: \xB1\x31"));
+        $paste = Helper::getPaste(['expire' => "Invalid UTF-8 sequence: \xB1\x31"]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         ini_set('error_log', '/dev/null');
         $this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store broken paste');
@@ -127,7 +127,7 @@ class FilesystemTest extends TestCase
         $error_log_setting = ini_get('error_log');
         $this->_model->delete(Helper::getPasteId());
         $data    = Helper::getPaste();
-        $comment = Helper::getComment(array('icon' => "Invalid UTF-8 sequence: \xB1\x31"));
+        $comment = Helper::getComment(['icon' => "Invalid UTF-8 sequence: \xB1\x31"]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         $this->assertTrue($this->_model->create(Helper::getPasteId(), $data), 'store new paste');
         $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
@@ -144,7 +144,7 @@ class FilesystemTest extends TestCase
         $paste     = Helper::getPaste();
         $comment   = Helper::getComment();
         $commentid = Helper::getCommentId();
-        $ids       = array();
+        $ids       = [];
         for ($i = 0, $max = 10; $i < $max; ++$i) {
             $dataid     = Helper::getRandomId();
             $storagedir = $this->_path . DIRECTORY_SEPARATOR . substr($dataid, 0, 2) .
@@ -178,16 +178,16 @@ class FilesystemTest extends TestCase
             $comment             = $comment;
             $comment['id']       = $commentid;
             $comment['parentid'] = $dataid;
-            $this->assertEquals($this->_model->readComments($dataid), array($comment['meta']['created'] => $comment), "comment of $dataid wasn't modified in the conversion");
+            $this->assertEquals($this->_model->readComments($dataid), [$comment['meta']['created'] => $comment], "comment of $dataid wasn't modified in the conversion");
         }
     }
 
     public function testValueFileErrorHandling()
     {
         define('VALID', 'valid content');
-        foreach (array('purge_limiter', 'salt', 'traffic_limiter') as $namespace) {
+        foreach (['purge_limiter', 'salt', 'traffic_limiter'] as $namespace) {
             file_put_contents($this->_invalidPath . DIRECTORY_SEPARATOR . $namespace . '.php', 'invalid content');
-            $model = new Filesystem(array('dir' => $this->_invalidPath));
+            $model = new Filesystem(['dir' => $this->_invalidPath]);
             ob_start(); // hide "invalid content", when file gets included
             $this->assertEquals($model->getValue($namespace), '', 'empty default value returned, invalid content ignored');
             ob_end_clean();

+ 14 - 14
tst/Data/GoogleCloudStorageTest.php

@@ -13,7 +13,7 @@ class GoogleCloudStorageTest extends TestCase
 
     public static function setUpBeforeClass(): void
     {
-        $httpClient = new Client(array('debug'=>false));
+        $httpClient = new Client(['debug'=>false]);
         $handler    = HttpHandlerFactory::build($httpClient);
 
         $name     = 'pb-';
@@ -21,17 +21,17 @@ class GoogleCloudStorageTest extends TestCase
         for ($i = 0; $i < 29; ++$i) {
             $name .= $alphabet[rand(0, strlen($alphabet) - 1)];
         }
-        self::$_client = new StorageClientStub(array());
+        self::$_client = new StorageClientStub([]);
         self::$_bucket = self::$_client->createBucket($name);
     }
 
     public function setUp(): void
     {
         ini_set('error_log', stream_get_meta_data(tmpfile())['uri']);
-        $this->_model = new GoogleCloudStorage(array(
+        $this->_model = new GoogleCloudStorage([
             'bucket' => self::$_bucket->name(),
             'prefix' => 'pastes',
-        ));
+        ]);
     }
 
     public function tearDown(): void
@@ -51,7 +51,7 @@ class GoogleCloudStorageTest extends TestCase
         $this->_model->delete(Helper::getPasteId());
 
         // storing pastes
-        $paste = Helper::getPaste(array('expire_date' => 1344803344));
+        $paste = Helper::getPaste(['expire_date' => 1344803344]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         $this->assertTrue($this->_model->create(Helper::getPasteId(), $paste), 'store new paste');
         $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');
@@ -67,7 +67,7 @@ class GoogleCloudStorageTest extends TestCase
         $comment['id']       = Helper::getCommentId();
         $comment['parentid'] = Helper::getPasteId();
         $this->assertEquals(
-            array($comment['meta']['created'] => $comment),
+            [$comment['meta']['created'] => $comment],
             $this->_model->readComments(Helper::getPasteId())
         );
 
@@ -83,14 +83,14 @@ class GoogleCloudStorageTest extends TestCase
      */
     public function testPurge()
     {
-        $expired = Helper::getPaste(array('expire_date' => 1344803344));
-        $paste   = Helper::getPaste(array('expire_date' => time() + 3600));
-        $keys    = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z');
-        $ids     = array();
+        $expired = Helper::getPaste(['expire_date' => 1344803344]);
+        $paste   = Helper::getPaste(['expire_date' => time() + 3600]);
+        $keys    = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'x', 'y', 'z'];
+        $ids     = [];
         foreach ($keys as $key) {
             $ids[$key] = hash('fnv164', $key);
             $this->assertFalse($this->_model->exists($ids[$key]), "paste $key does not yet exist");
-            if (in_array($key, array('x', 'y', 'z'))) {
+            if (in_array($key, ['x', 'y', 'z'])) {
                 $this->assertTrue($this->_model->create($ids[$key], $paste), "store $key paste");
             } elseif ($key === 'x') {
                 $data = Helper::getPaste();
@@ -102,7 +102,7 @@ class GoogleCloudStorageTest extends TestCase
         }
         $this->_model->purge(10);
         foreach ($ids as $key => $id) {
-            if (in_array($key, array('x', 'y', 'z'))) {
+            if (in_array($key, ['x', 'y', 'z'])) {
                 $this->assertTrue($this->_model->exists($id), "paste $key exists after purge");
                 $this->_model->delete($id);
             } else {
@@ -114,7 +114,7 @@ class GoogleCloudStorageTest extends TestCase
     public function testErrorDetection()
     {
         $this->_model->delete(Helper::getPasteId());
-        $paste = Helper::getPaste(array('expire' => "Invalid UTF-8 sequence: \xB1\x31"));
+        $paste = Helper::getPaste(['expire' => "Invalid UTF-8 sequence: \xB1\x31"]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         $this->assertFalse($this->_model->create(Helper::getPasteId(), $paste), 'unable to store broken paste');
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does still not exist');
@@ -124,7 +124,7 @@ class GoogleCloudStorageTest extends TestCase
     {
         $this->_model->delete(Helper::getPasteId());
         $data    = Helper::getPaste();
-        $comment = Helper::getComment(array('icon' => "Invalid UTF-8 sequence: \xB1\x31"));
+        $comment = Helper::getComment(['icon' => "Invalid UTF-8 sequence: \xB1\x31"]);
         $this->assertFalse($this->_model->exists(Helper::getPasteId()), 'paste does not yet exist');
         $this->assertTrue($this->_model->create(Helper::getPasteId(), $data), 'store new paste');
         $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists after storing it');

+ 37 - 0
tst/FormatV2Test.php

@@ -72,4 +72,41 @@ class FormatV2Test extends TestCase
         $paste = Helper::getPaste();
         $this->assertFalse(FormatV2::isValid($paste), 'invalid meta key');
     }
+
+    public function testFormatV2ValidatorRejectsMalformedTypes()
+    {
+        // malformed input must yield "false" (Invalid data) rather than a
+        // fatal type error under strict_types
+        $paste          = Helper::getPastePost();
+        $paste['v']     = 'abc';
+        $this->assertFalse(FormatV2::isValid($paste), 'non-numeric version');
+
+        $paste          = Helper::getPastePost();
+        $paste['v']     = [];
+        $this->assertFalse(FormatV2::isValid($paste), 'array version');
+
+        $paste          = Helper::getPastePost();
+        $paste['ct']    = ['not', 'a', 'string'];
+        $this->assertFalse(FormatV2::isValid($paste), 'non-string ciphertext');
+
+        $paste          = Helper::getPastePost();
+        $paste['meta']  = 'not-an-array';
+        $this->assertFalse(FormatV2::isValid($paste), 'non-array meta');
+
+        $paste             = Helper::getPastePost();
+        $paste['adata'][0] = 'not-an-array';
+        $this->assertFalse(FormatV2::isValid($paste), 'non-array cipher parameters');
+
+        $paste             = Helper::getPastePost();
+        $paste['adata'][0] = [];
+        $this->assertFalse(FormatV2::isValid($paste), 'empty cipher parameters');
+
+        $paste                = Helper::getPastePost();
+        $paste['adata'][0][0] = [];
+        $this->assertFalse(FormatV2::isValid($paste), 'non-string iv');
+
+        $comment           = Helper::getCommentPost();
+        $comment['ct']     = 42;
+        $this->assertFalse(FormatV2::isValid($comment, true), 'non-string comment ciphertext');
+    }
 }

+ 4 - 4
tst/I18nTest.php

@@ -8,7 +8,7 @@ class I18nMock extends I18n
 {
     public static function resetAvailableLanguages()
     {
-        self::$_availableLanguages = array();
+        self::$_availableLanguages = [];
     }
 
     public static function resetPath($path = '')
@@ -24,7 +24,7 @@ class I18nMock extends I18n
 
 class I18nTest extends TestCase
 {
-    private $_translations = array();
+    private $_translations = [];
 
     public function setUp(): void
     {
@@ -248,8 +248,8 @@ class I18nTest extends TestCase
 
     public function testMessageIdsExistInAllLanguages()
     {
-        $messageIds = array();
-        $languages  = array();
+        $messageIds = [];
+        $languages  = [];
         foreach (new DirectoryIterator(PATH . 'i18n') as $file) {
             $fileNameLength = strlen($file->getFilename());
             if ($fileNameLength === 7) {       // xx.json

+ 18 - 18
tst/JsonApiTest.php

@@ -19,12 +19,12 @@ class JsonApiTest extends TestCase
         if (!is_dir($this->_path)) {
             mkdir($this->_path);
         }
-        $this->_model = new Filesystem(array('dir' => $this->_path));
+        $this->_model = new Filesystem(['dir' => $this->_path]);
         ServerSalt::setStore($this->_model);
 
-        $_POST   = array();
-        $_GET    = array();
-        $_SERVER = array();
+        $_POST   = [];
+        $_GET    = [];
+        $_SERVER = [];
         if ($this->_model->exists(Helper::getPasteId())) {
             $this->_model->delete(Helper::getPasteId());
         }
@@ -119,9 +119,9 @@ class JsonApiTest extends TestCase
         $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
         $paste = $this->_model->read(Helper::getPasteId());
         $file  = Helper::createTempFile();
-        file_put_contents($file, json_encode(array(
+        file_put_contents($file, json_encode([
             'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste['meta']['salt']),
-        )));
+        ]));
         Request::setInputStream($file);
         $_SERVER['QUERY_STRING']          = Helper::getPasteId();
         $_GET[Helper::getPasteId()]       = '';
@@ -147,10 +147,10 @@ class JsonApiTest extends TestCase
         $this->assertTrue($this->_model->exists(Helper::getPasteId()), 'paste exists before deleting data');
         $paste = $this->_model->read(Helper::getPasteId());
         $file  = Helper::createTempFile();
-        file_put_contents($file, json_encode(array(
+        file_put_contents($file, json_encode([
             'pasteid'     => Helper::getPasteId(),
             'deletetoken' => hash_hmac('sha256', Helper::getPasteId(), $paste['meta']['salt']),
-        )));
+        ]));
         Request::setInputStream($file);
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         $_SERVER['REQUEST_METHOD']        = 'POST';
@@ -397,20 +397,20 @@ class JsonApiTest extends TestCase
 
     public function baseUriProvider()
     {
-        return array(
-            array('/path/shortenviayourls?'),
-            array('/path/index.php/shortenviayourls?'),
-            array('/path?shortenviayourls&'),
-        );
+        return [
+            ['/path/shortenviayourls?'],
+            ['/path/index.php/shortenviayourls?'],
+            ['/path?shortenviayourls&'],
+        ];
     }
 
     public function baseShlinkUriProvider()
     {
-        return array(
-            array('/path/shortenviashlink?'),
-            array('/path/index.php/shortenviashlink?'),
-            array('/path?shortenviashlink&'),
-        );
+        return [
+            ['/path/shortenviashlink?'],
+            ['/path/index.php/shortenviashlink?'],
+            ['/path?shortenviashlink&'],
+        ];
     }
 
     /**

+ 5 - 5
tst/MigrateTest.php

@@ -34,15 +34,15 @@ class MigrateTest extends TestCase
         $this->_model_1                  = new Filesystem($options['model_options']);
         Helper::createIniFile($this->_path_instance_1 . DIRECTORY_SEPARATOR . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php', $options);
 
-        $options['model']          = array(
+        $options['model']          = [
             'class' => 'Database',
-        );
-        $options['model_options'] = array(
+        ];
+        $options['model_options'] = [
             'dsn' => 'sqlite:' . $this->_path_instance_2 . DIRECTORY_SEPARATOR . 'test.sq3',
             'usr' => null,
             'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        );
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ];
         $this->_model_2 = new Database($options['model_options']);
         Helper::createIniFile($this->_path_instance_2 . DIRECTORY_SEPARATOR . 'cfg' . DIRECTORY_SEPARATOR . 'conf.php', $options);
     }

+ 36 - 36
tst/ModelTest.php

@@ -28,15 +28,15 @@ class ModelTest extends TestCase
         }
         $options                   = parse_ini_file(CONF_SAMPLE, true);
         $options['purge']['limit'] = 0;
-        $options['model']          = array(
+        $options['model']          = [
             'class' => 'Database',
-        );
-        $options['model_options'] = array(
+        ];
+        $options['model_options'] = [
             'dsn' => 'sqlite::memory:',
             'usr' => null,
             'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        );
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ];
         Helper::confBackup();
         Helper::createIniFile(CONF, $options);
         ServerSalt::setStore(new Database($options['model_options']));
@@ -100,7 +100,7 @@ class ModelTest extends TestCase
         $this->_model->getPaste(Helper::getPasteId())->delete();
         $paste = $this->_model->getPaste(Helper::getPasteId());
         $this->assertFalse($paste->exists(), 'paste successfully deleted');
-        $this->assertEquals(array(), $paste->getComments(), 'comment was deleted with paste');
+        $this->assertEquals([], $paste->getComments(), 'comment was deleted with paste');
     }
 
     public function testCommentDefaults()
@@ -141,15 +141,15 @@ class ModelTest extends TestCase
         }
         $options                   = parse_ini_file(CONF_SAMPLE, true);
         $options['purge']['limit'] = 0;
-        $options['model']          = array(
+        $options['model']          = [
             'class' => 'Database',
-        );
-        $options['model_options'] = array(
+        ];
+        $options['model_options'] = [
             'dsn' => 'sqlite:' . $path,
             'usr' => null,
             'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        );
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ];
         Helper::createIniFile(CONF, $options);
         $model = new Model(new Configuration);
 
@@ -182,15 +182,15 @@ class ModelTest extends TestCase
         }
         $options                   = parse_ini_file(CONF_SAMPLE, true);
         $options['purge']['limit'] = 0;
-        $options['model']          = array(
+        $options['model']          = [
             'class' => 'Database',
-        );
-        $options['model_options'] = array(
+        ];
+        $options['model_options'] = [
             'dsn' => 'sqlite:' . $path,
             'usr' => null,
             'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        );
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ];
         Helper::createIniFile(CONF, $options);
         $model = new Model(new Configuration);
 
@@ -257,14 +257,14 @@ class ModelTest extends TestCase
         $comment->get();
         $comment->store();
 
-        $identicon = new Identicon(array(
+        $identicon = new Identicon([
             'hash'  => TrafficLimiter::getHash(),
             'size'  => 16,
-            'style' => array(
+            'style' => [
                 'backgroundColor'   => '#fff0', // fully transparent, for dark mode
                 'padding'           => 0,
-            ),
-        ));
+            ],
+        ]);
         $pngdata = $identicon->getImageDataUri('png');
         $comment = current($this->_model->getPaste(Helper::getPasteId())->get()['comments']);
         $this->assertEquals($pngdata, $comment['meta']['icon'], 'icon gets set');
@@ -371,15 +371,15 @@ class ModelTest extends TestCase
         $conf  = new Configuration;
         $store = new Database($conf->getSection('model_options'));
         $store->delete(Helper::getPasteId());
-        $expired = Helper::getPaste(array('expire_date' => 1344803344));
-        $paste   = Helper::getPaste(array('expire_date' => time() + 3600));
-        $keys    = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'x', 'y', 'z');
-        $ids     = array();
+        $expired = Helper::getPaste(['expire_date' => 1344803344]);
+        $paste   = Helper::getPaste(['expire_date' => time() + 3600]);
+        $keys    = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'x', 'y', 'z'];
+        $ids     = [];
         foreach ($keys as $key) {
             $ids[$key] = hash('fnv164', $key);
             $store->delete($ids[$key]);
             $this->assertFalse($store->exists($ids[$key]), "paste $key does not yet exist");
-            if (in_array($key, array('x', 'y', 'z'))) {
+            if (in_array($key, ['x', 'y', 'z'])) {
                 $this->assertTrue($store->create($ids[$key], $paste), "store $key paste");
             } else {
                 $this->assertTrue($store->create($ids[$key], $expired), "store $key paste");
@@ -388,7 +388,7 @@ class ModelTest extends TestCase
         }
         $this->_model->purge(10);
         foreach ($ids as $key => $id) {
-            if (in_array($key, array('x', 'y', 'z'))) {
+            if (in_array($key, ['x', 'y', 'z'])) {
                 $this->assertTrue($this->_model->getPaste($id)->exists(), "paste $key exists after purge");
                 $this->_model->getPaste($id)->delete();
             } else {
@@ -402,15 +402,15 @@ class ModelTest extends TestCase
         $options                                  = parse_ini_file(CONF, true);
         $options['main']['discussiondatedisplay'] = 'false';
         $options['main']['icon']                  = 'none';
-        $options['model']                         = array(
+        $options['model']                         = [
             'class' => 'Database',
-        );
-        $options['model_options']                 = array(
+        ];
+        $options['model_options']                 = [
             'dsn' => 'sqlite::memory:',
             'usr' => null,
             'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        );
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ];
         Helper::createIniFile(CONF, $options);
         $model = new Model(new Configuration);
 
@@ -452,15 +452,15 @@ class ModelTest extends TestCase
     {
         $options                 = parse_ini_file(CONF, true);
         $options['main']['icon'] = 'vizhash';
-        $options['model']        = array(
+        $options['model']        = [
             'class' => 'Database',
-        );
-        $options['model_options'] = array(
+        ];
+        $options['model_options'] = [
             'dsn' => 'sqlite::memory:',
             'usr' => null,
             'pwd' => null,
-            'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
-        );
+            'opt' => [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION],
+        ];
         Helper::createIniFile(CONF, $options);
         $model = new Model(new Configuration);
 

+ 1 - 1
tst/Persistence/PurgeLimiterTest.php

@@ -16,7 +16,7 @@ class PurgeLimiterTest extends TestCase
             mkdir($this->_path);
         }
         PurgeLimiter::setStore(
-            new Filesystem(array('dir' => $this->_path))
+            new Filesystem(['dir' => $this->_path])
         );
     }
 

+ 9 - 9
tst/Persistence/ServerSaltTest.php

@@ -22,7 +22,7 @@ class ServerSaltTest extends TestCase
             mkdir($this->_path);
         }
         ServerSalt::setStore(
-            new Filesystem(array('dir' => $this->_path))
+            new Filesystem(['dir' => $this->_path])
         );
 
         $this->_otherPath = $this->_path . DIRECTORY_SEPARATOR . 'foo';
@@ -45,17 +45,17 @@ class ServerSaltTest extends TestCase
     {
         // generating new salt
         ServerSalt::setStore(
-            new Filesystem(array('dir' => $this->_path))
+            new Filesystem(['dir' => $this->_path])
         );
         $salt = ServerSalt::get();
 
         // try setting a different path and resetting it
         ServerSalt::setStore(
-            new Filesystem(array('dir' => $this->_otherPath))
+            new Filesystem(['dir' => $this->_otherPath])
         );
         $this->assertNotEquals($salt, ServerSalt::get());
         ServerSalt::setStore(
-            new Filesystem(array('dir' => $this->_path))
+            new Filesystem(['dir' => $this->_path])
         );
         $this->assertEquals($salt, ServerSalt::get());
     }
@@ -64,7 +64,7 @@ class ServerSaltTest extends TestCase
     {
         // try setting an invalid path
         chmod($this->_invalidPath, 0000);
-        $store = new Filesystem(array('dir' => $this->_invalidPath));
+        $store = new Filesystem(['dir' => $this->_invalidPath]);
         ServerSalt::setStore($store);
         $salt = ServerSalt::get();
         ServerSalt::setStore($store);
@@ -77,7 +77,7 @@ class ServerSaltTest extends TestCase
         chmod($this->_invalidPath, 0700);
         file_put_contents($this->_invalidFile, '');
         chmod($this->_invalidFile, 0000);
-        $store = new Filesystem(array('dir' => $this->_invalidPath));
+        $store = new Filesystem(['dir' => $this->_invalidPath]);
         ServerSalt::setStore($store);
         $salt = ServerSalt::get();
         ServerSalt::setStore($store);
@@ -94,7 +94,7 @@ class ServerSaltTest extends TestCase
         }
         file_put_contents($this->_invalidPath . DIRECTORY_SEPARATOR . '.htaccess', '');
         chmod($this->_invalidPath, 0500);
-        $store = new Filesystem(array('dir' => $this->_invalidPath));
+        $store = new Filesystem(['dir' => $this->_invalidPath]);
         ServerSalt::setStore($store);
         $salt = ServerSalt::get();
         ServerSalt::setStore($store);
@@ -106,9 +106,9 @@ class ServerSaltTest extends TestCase
         // try creating an invalid path
         chmod($this->_invalidPath, 0000);
         ServerSalt::setStore(
-            new Filesystem(array('dir' => $this->_invalidPath . DIRECTORY_SEPARATOR . 'baz'))
+            new Filesystem(['dir' => $this->_invalidPath . DIRECTORY_SEPARATOR . 'baz'])
         );
-        $store = new Filesystem(array('dir' => $this->_invalidPath));
+        $store = new Filesystem(['dir' => $this->_invalidPath]);
         ServerSalt::setStore($store);
         $salt = ServerSalt::get();
         ServerSalt::setStore($store);

+ 1 - 1
tst/Persistence/TrafficLimiterTest.php

@@ -13,7 +13,7 @@ class TrafficLimiterTest extends TestCase
     {
         /* Setup Routine */
         $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'trafficlimit';
-        $store       = new Filesystem(array('dir' => $this->_path));
+        $store       = new Filesystem(['dir' => $this->_path]);
         ServerSalt::setStore($store);
         TrafficLimiter::setStore($store);
     }

+ 25 - 5
tst/RequestTest.php

@@ -7,9 +7,9 @@ class RequestTest extends TestCase
 {
     public function reset()
     {
-        $_SERVER = array();
-        $_GET    = array();
-        $_POST   = array();
+        $_SERVER = [];
+        $_GET    = [];
+        $_POST   = [];
     }
 
     /**
@@ -134,7 +134,7 @@ class RequestTest extends TestCase
         $_SERVER['REQUEST_METHOD']        = 'POST';
         $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
         $_SERVER['QUERY_STRING']          = $id;
-        $_GET                             = array($id => '');
+        $_GET                             = [$id => ''];
         $file                             = Helper::createTempFile();
         file_put_contents($file, '{"deletetoken":"bar"}');
         Request::setInputStream($file);
@@ -158,6 +158,26 @@ class RequestTest extends TestCase
         $this->assertEquals('create', $request->getOperation());
     }
 
+    public function testPostScalarJson()
+    {
+        // a valid JSON scalar body (number, boolean or quoted string) must not
+        // be treated as a set of parameters, so that it is rejected cleanly
+        // instead of triggering a type error further down
+        foreach (['1', '0.0', 'true', 'false', '"example"'] as $scalar) {
+            $this->reset();
+            $_SERVER['REQUEST_METHOD']        = 'POST';
+            $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
+            $file                             = Helper::createTempFile();
+            file_put_contents($file, $scalar);
+            Request::setInputStream($file);
+            $request = new Request;
+            unlink($file);
+            $this->assertTrue($request->isJsonApiCall(), 'is JSON API call');
+            $this->assertEquals('create', $request->getOperation());
+            $this->assertEquals('', $request->getParam('ct'), "scalar body {$scalar} yields no parameters");
+        }
+    }
+
     public function testReadWithNegotiation()
     {
         $this->reset();
@@ -219,7 +239,7 @@ class RequestTest extends TestCase
         $this->reset();
         $id              = Helper::getRandomId();
         $path            = '/' . $this->getRandomQueryChars() . '/';
-        $queryParams     = array($id);
+        $queryParams     = [$id];
         $queryParamCount = random_int(1, 5);
         for ($i = 0; $i < $queryParamCount; ++$i) {
             array_push($queryParams, $this->getRandomQueryChars());

+ 6 - 6
tst/ViewTest.php

@@ -12,25 +12,25 @@ class ViewTest extends TestCase
 
     private static $is_deleted = false;
 
-    private static $formatters = array(
+    private static $formatters = [
         'plaintext'          => 'Plain Text',
         'syntaxhighlighting' => 'Source Code',
         'markdown'           => 'Markdown',
-    );
+    ];
 
     private static $formatter_default = 'plaintext';
 
-    private static $expire = array(
+    private static $expire = [
         '5min'  => '5 minutes',
         '1hour' => '1 hour',
         'never' => 'Never',
-    );
+    ];
 
     private static $expire_default = '1hour';
 
     private static $version = 'Version 1.2.3';
 
-    private $_content = array();
+    private $_content = [];
 
     public function setUp(): void
     {
@@ -65,7 +65,7 @@ class ViewTest extends TestCase
         $page->assign('HTTPSLINK', 'https://example.com/');
         $page->assign('COMPRESSION', 'zlib');
         $page->assign('CSPHEADER', 'default-src \'none\'');
-        $page->assign('SRI', array());
+        $page->assign('SRI', []);
 
         foreach (new DirectoryIterator(PATH . 'tpl') as $file) {
             if ($file->getExtension() === 'php') {

+ 1 - 1
tst/Vizhash16x16Test.php

@@ -19,7 +19,7 @@ class Vizhash16x16Test extends TestCase
             mkdir($this->_path);
         }
         $this->_file = $this->_path . DIRECTORY_SEPARATOR . 'vizhash.png';
-        ServerSalt::setStore(new Filesystem(array('dir' => $this->_path)));
+        ServerSalt::setStore(new Filesystem(['dir' => $this->_path]));
     }
 
     public function tearDown(): void

+ 32 - 19
tst/YourlsProxyTest.php

@@ -73,16 +73,16 @@ class YourlsProxyTest extends TestCase
 
     public function providerInvalidUrl(): array
     {
-        return array(
-            array(''),
-            array(' '),
-            array('foo'),
-            array('https://'),
-            array('https://example.com'), // missing path and query parameter,
-            array('https://example.com/'), // missing query parameter
-            array('https://example.com?paste=something'), // missing path parameter
-            array('https://example.com@foreign.malicious.example?foo#bar'), // missing path parameter
-        );
+        return [
+            [''],
+            [' '],
+            ['foo'],
+            ['https://'],
+            ['https://example.com'], // missing path and query parameter,
+            ['https://example.com/'], // missing query parameter
+            ['https://example.com?paste=something'], // missing path parameter
+            ['https://example.com@foreign.malicious.example?foo#bar'], // missing path parameter
+        ];
     }
 
     /**
@@ -100,10 +100,10 @@ class YourlsProxyTest extends TestCase
 
     public function providerForeignUrlUsernameTrick(): array
     {
-        return array(
-            array('https://example.com@foreign.malicious.example/?foo#bar'),
-            array('https://example.com/@foreign.malicious.example?foo#bar'),
-        );
+        return [
+            ['https://example.com@foreign.malicious.example/?foo#bar'],
+            ['https://example.com/@foreign.malicious.example?foo#bar'],
+        ];
     }
 
     /**
@@ -118,11 +118,11 @@ class YourlsProxyTest extends TestCase
 
     public function providerForeignUrl(): array
     {
-        return array(
-            array('ftp://example.com/?n=np'), // wrong protocol
-            array('https://other.example.com/?foo#bar'), // wrong domain
-            array('https://other.example.com/?q=https://example.com/?foo#bar'), // domain included inside string
-        );
+        return [
+            ['ftp://example.com/?n=np'], // wrong protocol
+            ['https://other.example.com/?foo#bar'], // wrong domain
+            ['https://other.example.com/?q=https://example.com/?foo#bar'], // domain included inside string
+        ];
     }
 
     public function testYourlsError()
@@ -135,6 +135,19 @@ class YourlsProxyTest extends TestCase
         $this->assertEquals($yourls->getError(), 'Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.');
     }
 
+    public function testYourlsSuccessWithoutShortUrl()
+    {
+        // YOURLS may reply with statusCode 200 but without a shorturl field;
+        // this must be handled gracefully as an error instead of raising a
+        // TypeError (the method is declared to return ?string). YOURLS returns
+        // the status code as a string, so mirror that here.
+        file_put_contents($this->_mock_yourls_service, '{"statusCode":"200"}');
+
+        $yourls = new YourlsProxy($this->_conf, 'https://example.com/?foo#bar');
+        $this->assertTrue($yourls->isError());
+        $this->assertEquals($yourls->getError(), 'Proxy error: Error parsing proxy response. This can be a configuration issue, like wrong or missing config keys.');
+    }
+
     public function testServerError()
     {
         // simulate some other server error that results in a non-JSON reply

+ 0 - 1
vendor/composer/autoload_classmap.php

@@ -74,7 +74,6 @@ return array(
     'PrivateBin\\Data\\Filesystem' => $baseDir . '/lib/Data/Filesystem.php',
     'PrivateBin\\Data\\GoogleCloudStorage' => $baseDir . '/lib/Data/GoogleCloudStorage.php',
     'PrivateBin\\Data\\S3Storage' => $baseDir . '/lib/Data/S3Storage.php',
-    'PrivateBin\\Exception\\JsonException' => $baseDir . '/lib/Exception/JsonException.php',
     'PrivateBin\\Exception\\TranslatedException' => $baseDir . '/lib/Exception/TranslatedException.php',
     'PrivateBin\\Filter' => $baseDir . '/lib/Filter.php',
     'PrivateBin\\FormatV2' => $baseDir . '/lib/FormatV2.php',

+ 0 - 1
vendor/composer/autoload_static.php

@@ -122,7 +122,6 @@ class ComposerStaticInitDontChange
         'PrivateBin\\Data\\Filesystem' => __DIR__ . '/../..' . '/lib/Data/Filesystem.php',
         'PrivateBin\\Data\\GoogleCloudStorage' => __DIR__ . '/../..' . '/lib/Data/GoogleCloudStorage.php',
         'PrivateBin\\Data\\S3Storage' => __DIR__ . '/../..' . '/lib/Data/S3Storage.php',
-        'PrivateBin\\Exception\\JsonException' => __DIR__ . '/../..' . '/lib/Exception/JsonException.php',
         'PrivateBin\\Exception\\TranslatedException' => __DIR__ . '/../..' . '/lib/Exception/TranslatedException.php',
         'PrivateBin\\Filter' => __DIR__ . '/../..' . '/lib/Filter.php',
         'PrivateBin\\FormatV2' => __DIR__ . '/../..' . '/lib/FormatV2.php',

+ 2 - 2
vendor/composer/installed.php

@@ -3,7 +3,7 @@
         'name' => 'privatebin/privatebin',
         'pretty_version' => 'dev-master',
         'version' => 'dev-master',
-        'reference' => '67baf8cca4b7aa1bc57e631b47ab561695c8ce2b',
+        'reference' => '8a77305838325d7be15b9a96e43415a6d2796489',
         'type' => 'project',
         'install_path' => __DIR__ . '/../../',
         'aliases' => array(),
@@ -31,7 +31,7 @@
         'privatebin/privatebin' => array(
             'pretty_version' => 'dev-master',
             'version' => 'dev-master',
-            'reference' => '67baf8cca4b7aa1bc57e631b47ab561695c8ce2b',
+            'reference' => '8a77305838325d7be15b9a96e43415a6d2796489',
             'type' => 'project',
             'install_path' => __DIR__ . '/../../',
             'aliases' => array(),

Some files were not shown because too many files changed in this diff