Browse Source

Merge branch 'master' into crowdin-translation

El RIDO 1 năm trước cách đây
mục cha
commit
d8efd4cd2a

+ 3 - 0
CHANGELOG.md

@@ -2,12 +2,15 @@
 
 ## 1.7.7 (not yet released)
 * ADDED: Switching templates using the web ui (#1501)
+* ADDED: Show file name and size on download page (#603)
 * CHANGED: Passing large data structures by reference to reduce memory consumption (#858)
 * CHANGED: Removed use of ctype functions and polyfill library for ctype
 * CHANGED: Upgrading libraries to: DOMpurify 3.2.6, ip-lib 1.20.0
 * CHANGED: Support for multiple file uploads (#1060)
 * CHANGED: Documented CSP change necessary to allow PDF attachment preview (#1552)
 * FIXED: Hide Reply button in the discussions once clicked to avoid losing the text input (#1508)
+* FIXED: Bump zlib library suffix, ensuring cache refresh for WASM streaming change
+* FIXED: Handle undefined globals in file based persisted values (#1544)
 
 ## 1.7.6 (2025-02-01)
 * ADDED: Ability to copy the paste by clicking the copy icon button or using the keyboard shortcut ctrl+c/cmd+c (#1390 & #12)

+ 1 - 1
CREDITS.md

@@ -5,6 +5,7 @@
 * Simon Rupf - current developer and maintainer
 * rugk - security review, doc improvment, JS refactoring & various other stuff
 * R4SAS - python client, compression, blob URI to support larger attachments
+* Mikhail Romanov - UI improvements, theme switching, clipboard support, multi-file upload, bugfixes, code refactoring
 
 ## Past contributions
 
@@ -33,7 +34,6 @@
 * Mounir Idrassi & J. Mozdzen - secure YOURLS integration
 * Felipe Nakandakari - enabled AWS SDK to use default credential provider chain in the S3 Storage backend
 * Aaron Sherber - cache control headers for API calls & use of `shortenviayourls` in query parameters
-* Mikhail Romanov - UI improvements, theme switching, clipboard support, multi-file upload, bugfixes, code refactoring
 
 ## Translations
 * Hexalyse - French

+ 8 - 0
i18n/en.json

@@ -164,6 +164,14 @@
     "EiB": "EiB",
     "ZiB": "ZiB",
     "YiB": "YiB",
+    "kB": "kB",
+    "MB": "MB",
+    "GB": "GB",
+    "TB": "TB",
+    "PB": "PB",
+    "EB": "EB",
+    "ZB": "ZB",
+    "YB": "YB",
     "Format": "Format",
     "Plain Text": "Plain Text",
     "Source Code": "Source Code",

+ 1 - 1
js/common.js

@@ -11,7 +11,7 @@ global.WebCrypto = require('@peculiar/webcrypto').Crypto;
 // application libraries to test
 global.$ = global.jQuery = require('./jquery-3.7.1');
 global.RawDeflate = require('./rawinflate-0.3').RawDeflate;
-global.zlib = require('./zlib-1.3.1').zlib;
+global.zlib = require('./zlib-1.3.1-1').zlib;
 require('./prettify');
 global.prettyPrint = window.PR.prettyPrint;
 global.prettyPrintOne = window.PR.prettyPrintOne;

+ 29 - 1
js/privatebin.js

@@ -591,6 +591,32 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             return expirationDate;
         };
 
+        /**
+         * Convert Bytes to KiB/MiB/GiB
+         *
+         * @name   Helper.formatBytes
+         * @function
+         *
+         * @param  {number} bytes
+         * @return {string}
+         */
+        me.formatBytes = function (bytes)
+        {
+            let result = '';
+            const kilobyte = 1024;
+            const decimalPoint = 2;
+            const sizes = [I18n._('B'), I18n._('KiB'), I18n._('MiB'), I18n._('GiB')];
+            const index = Math.floor(Math.log(bytes) / Math.log(kilobyte));
+
+            if (bytes > 0) {
+                result = parseFloat((bytes / Math.pow(kilobyte, index)).toFixed(decimalPoint)) + ' ' + sizes[index];
+            } else {
+                result = `0 ${I18n._('B')}`;
+            }
+
+            return result;
+        }
+
         /**
          * resets state, used for unit testing
          *
@@ -3000,7 +3026,9 @@ jQuery.PrivateBin = (function($, RawDeflate) {
 
             if (typeof fileName !== 'undefined') {
                 attachmentLink.attr('download', fileName);
-                template.append(fileName);
+
+                const fileSize = Helper.formatBytes(decodedData.length);
+                template.append(`(${fileName}, ${fileSize})`);
             }
 
             // sanitize SVG preview

+ 26 - 0
js/test/Helper.js

@@ -290,5 +290,31 @@ describe('Helper', function () {
             }
         );
     });
+
+    describe('formatBytes', function () {
+        jsc.property('returns 0 B for 0 bytes', function () {
+            return $.PrivateBin.Helper.formatBytes(0) === '0 B';
+        });
+
+        jsc.property('formats bytes < 1000 as B', function () {
+            return $.PrivateBin.Helper.formatBytes(500) === '500 B';
+        });
+
+        jsc.property('formats kibibytes correctly', function () {
+            return $.PrivateBin.Helper.formatBytes(1500) === '1.46 KiB';
+        });
+
+        jsc.property('formats mebibytes correctly', function () {
+            return $.PrivateBin.Helper.formatBytes(2 * 1000 * 1000) === '1.91 MiB';
+        });
+
+        jsc.property('formats gibibytes correctly', function () {
+            return $.PrivateBin.Helper.formatBytes(3.45 * 1000 * 1000 * 1000) === '3.21 GiB';
+        });
+
+        jsc.property('rounds to two decimal places', function () {
+            return $.PrivateBin.Helper.formatBytes(1234567) === '1.18 MiB';
+        });
+    });
 });
 

+ 0 - 0
js/zlib-1.3.1.js → js/zlib-1.3.1-1.js


+ 2 - 2
lib/Configuration.php

@@ -119,11 +119,11 @@ class Configuration
             'js/kjua-0.9.0.js'       => 'sha512-CVn7af+vTMBd9RjoS4QM5fpLFEOtBCoB0zPtaqIDC7sF4F8qgUSRFQQpIyEDGsr6yrjbuOLzdf20tkHHmpaqwQ==',
             'js/legacy.js'           => 'sha512-UxW/TOZKon83n6dk/09GsYKIyeO5LeBHokxyIq+r7KFS5KMBeIB/EM7NrkVYIezwZBaovnyNtY2d9tKFicRlXg==',
             'js/prettify.js'         => 'sha512-puO0Ogy++IoA2Pb9IjSxV1n4+kQkKXYAEUtVzfZpQepyDPyXk8hokiYDS7ybMogYlyyEIwMLpZqVhCkARQWLMg==',
-            'js/privatebin.js'       => 'sha512-m6RrsOsz4RgIWXDzgRghQDx6aegFCpkpqURwhfXwE/rNWhe/1rPJaLR+FXII82iTWo0n9JCzSbqrDqkYVPI50w==',
+            'js/privatebin.js'       => 'sha512-zvJ6Feu2NvROB236BBxbP+8eYbUTJ5GCfhOJVL/RI6pJQpR3AS4ps0d1cVDqgUFW8wY0tiwE7JTE13gPWO3lHA==',
             'js/purify-3.2.6.js'     => 'sha512-zqwL4OoBLFx89QPewkz4Lz5CSA2ktU+f31fuECkF0iK3Id5qd3Zpq5dMby8KwHjIEpsUgOqwF58cnmcaNem0EA==',
             'js/rawinflate-0.3.js'   => 'sha512-g8uelGgJW9A/Z1tB6Izxab++oj5kdD7B4qC7DHwZkB6DGMXKyzx7v5mvap2HXueI2IIn08YlRYM56jwWdm2ucQ==',
             'js/showdown-2.1.0.js'   => 'sha512-WYXZgkTR0u/Y9SVIA4nTTOih0kXMEd8RRV6MLFdL6YU8ymhR528NLlYQt1nlJQbYz4EW+ZsS0fx1awhiQJme1Q==',
-            'js/zlib-1.3.1.js'       => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==',
+            'js/zlib-1.3.1-1.js'     => 'sha512-5bU9IIP4PgBrOKLZvGWJD4kgfQrkTz8Z3Iqeu058mbQzW3mCumOU6M3UVbVZU9rrVoVwaW4cZK8U8h5xjF88eQ==',
         ),
     );
 

+ 9 - 5
lib/Data/Filesystem.php

@@ -276,7 +276,7 @@ class Filesystem extends AbstractData
             case 'purge_limiter':
                 return $this->_storeString(
                     $this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php',
-                    '<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . $value . ';'
+                    '<?php' . PHP_EOL . '$GLOBALS[\'purge_limiter\'] = ' . var_export($value, true) . ';'
                 );
             case 'salt':
                 return $this->_storeString(
@@ -308,7 +308,9 @@ class Filesystem extends AbstractData
                 $file = $this->_path . DIRECTORY_SEPARATOR . 'purge_limiter.php';
                 if (is_readable($file)) {
                     require $file;
-                    return $GLOBALS['purge_limiter'];
+                    if (array_key_exists('purge_limiter', $GLOBALS)) {
+                        return $GLOBALS['purge_limiter'];
+                    }
                 }
                 break;
             case 'salt':
@@ -324,9 +326,11 @@ class Filesystem extends AbstractData
                 $file = $this->_path . DIRECTORY_SEPARATOR . 'traffic_limiter.php';
                 if (is_readable($file)) {
                     require $file;
-                    $this->_last_cache = $GLOBALS['traffic_limiter'];
-                    if (array_key_exists($key, $this->_last_cache)) {
-                        return $this->_last_cache[$key];
+                    if (array_key_exists('traffic_limiter', $GLOBALS)) {
+                        $this->_last_cache = $GLOBALS['traffic_limiter'];
+                        if (array_key_exists($key, $this->_last_cache)) {
+                            return $this->_last_cache[$key];
+                        }
                     }
                 }
                 break;

+ 1 - 1
tpl/bootstrap.php

@@ -55,7 +55,7 @@ if ($ZEROBINCOMPATIBILITY) :
 <?php
 endif;
 ?>
-		<?php $this->_scriptTag('js/zlib-1.3.1.js', 'async'); ?>
+		<?php $this->_scriptTag('js/zlib-1.3.1-1.js', 'async'); ?>
 		<?php $this->_scriptTag('js/base-x-4.0.0.js', 'defer'); ?>
 		<?php $this->_scriptTag('js/rawinflate-0.3.js', 'defer'); ?>
 		<?php $this->_scriptTag('js/bootstrap-3.4.1.js', 'defer'); ?>

+ 1 - 1
tpl/bootstrap5.php

@@ -38,7 +38,7 @@ if ($ZEROBINCOMPATIBILITY) :
 <?php
 endif;
 ?>
-		<?php $this->_scriptTag('js/zlib-1.3.1.js', 'defer'); ?>
+		<?php $this->_scriptTag('js/zlib-1.3.1-1.js', 'defer'); ?>
 		<?php $this->_scriptTag('js/base-x-4.0.0.js', 'defer'); ?>
 		<?php $this->_scriptTag('js/rawinflate-0.3.js', 'defer'); ?>
 		<?php $this->_scriptTag('js/bootstrap-5.3.3.js', 'async'); ?>

+ 1 - 1
tpl/page.php

@@ -34,7 +34,7 @@ if ($ZEROBINCOMPATIBILITY):
 <?php
 endif;
 ?>
-		<?php $this->_scriptTag('js/zlib-1.3.1.js', 'async'); ?>
+		<?php $this->_scriptTag('js/zlib-1.3.1-1.js', 'async'); ?>
 		<?php $this->_scriptTag('js/base-x-4.0.0.js', 'async'); ?>
 		<?php $this->_scriptTag('js/rawinflate-0.3.js', 'async'); ?>
 <?php

+ 14 - 0
tst/Data/FilesystemTest.php

@@ -178,4 +178,18 @@ class FilesystemTest extends TestCase
             $this->assertEquals($this->_model->readComments($dataid), array($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) {
+            file_put_contents($this->_invalidPath . DIRECTORY_SEPARATOR . $namespace . '.php', 'invalid content');
+            $model = new Filesystem(array('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();
+            $this->assertTrue($model->setValue(VALID, $namespace), 'setting valid value');
+            $this->assertEquals($model->getValue($namespace), VALID, 'valid value returned');
+        }
+    }
 }