Quellcode durchsuchen

Merge branch 'chrono-privacy'

El RIDO vor 2 Jahren
Ursprung
Commit
843aa00473

+ 1 - 0
CHANGELOG.md

@@ -8,6 +8,7 @@
 * CHANGED: Drop some PHP < 5.6 fallbacks, minimum version is PHP 7.3 as of release 1.6.0
 * CHANGED: Set `lang` cookie with lax `SameSite` property
 * CHANGED: Upgrading libraries to: DOMpurify 3.1.2 (#1299) & jQuery 3.7.1
+* CHANGED: `create` attribute is no longer returned in API for pastes & can be disabled for comments using `discussiondatedisplay` as well (#1290)
 * FIXED: Add cache control headers also to API calls (#1263)
 * FIXED: Shortened paste URL does not appear in email (#606)
 

+ 5 - 0
cfg/conf.sample.php

@@ -18,6 +18,11 @@ discussion = true
 ; preselect the discussion feature, defaults to false
 opendiscussion = false
 
+; enable or disable the diplay of dates & times in the comments, defaults to true
+; Note that internally the creation time will still get tracked in order to sort
+; the comments by creation time, but you can choose not to display them.
+; discussiondatedisplay = false
+
 ; enable or disable the password feature, defaults to true
 password = true
 

+ 1 - 2
doc/Installation.md

@@ -170,14 +170,13 @@ user these additional privileges:
 
 For reference or if you want to create the table schema for yourself to avoid
 having to give PrivateBin too many permissions (replace `prefix_` with your own
-table prefix and create the table schema with your favourite MariaDB/MySQL
+table prefix and create the table schema with your favorite MariaDB/MySQL
 client):
 
 ```sql
 CREATE TABLE prefix_paste (
     dataid CHAR(16) NOT NULL,
     data MEDIUMBLOB,
-    postdate INT,
     expiredate INT,
     opendiscussion INT,
     burnafterreading INT,

+ 5 - 4
js/privatebin.js

@@ -196,7 +196,7 @@ jQuery.PrivateBin = (function($, RawDeflate) {
          */
         this.getCreated = function()
         {
-            return this.meta[this.v === 1 ? 'postdate' : 'created'];
+            return this.meta[this.v === 1 ? 'postdate' : 'created'] || 0;
         }
 
         /**
@@ -2736,7 +2736,6 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             if (Editor.isPreview()) {
                 PasteViewer.run();
             }
-
         };
 
         /**
@@ -3495,9 +3494,11 @@ jQuery.PrivateBin = (function($, RawDeflate) {
             }
 
             // set date
+            const created = comment.getCreated();
+            const commentDate = created == 0 ? '' : ' (' + (new Date(created * 1000).toLocaleString()) + ')';
             $commentEntry.find('span.commentdate')
-                      .text(' (' + (new Date(comment.getCreated() * 1000).toLocaleString()) + ')')
-                      .attr('title', 'CommentID: ' + comment.id);
+                         .text(commentDate)
+                         .attr('title', 'CommentID: ' + comment.id);
 
             // if an avatar is available, display it
             const icon = comment.getIcon();

+ 1 - 0
lib/Configuration.php

@@ -40,6 +40,7 @@ class Configuration
             'basepath'                 => '',
             'discussion'               => true,
             'opendiscussion'           => false,
+            'discussiondatedisplay'    => true,
             'password'                 => true,
             'fileupload'               => false,
             'burnafterreadingselected' => false,

+ 19 - 14
lib/Data/Database.php

@@ -146,9 +146,6 @@ class Database extends AbstractData
         $attachment       = $attachmentname   = null;
         $meta             = $paste['meta'];
         $isVersion1       = array_key_exists('data', $paste);
-        list($createdKey) = $this->_getVersionedKeys($isVersion1 ? 1 : 2);
-        $created          = (int) $meta[$createdKey];
-        unset($meta[$createdKey], $paste['meta']);
         if (array_key_exists('expire_date', $meta)) {
             $expire_date = (int) $meta['expire_date'];
             unset($meta['expire_date']);
@@ -177,11 +174,10 @@ class Database extends AbstractData
         try {
             return $this->_exec(
                 'INSERT INTO "' . $this->_sanitizeIdentifier('paste') .
-                '" VALUES(?,?,?,?,?,?,?,?,?)',
+                '" VALUES(?,?,?,?,?,?,?,?)',
                 array(
                     $pasteid,
                     $isVersion1 ? $paste['data'] : Json::encode($paste),
-                    $created,
                     $expire_date,
                     (int) $opendiscussion,
                     (int) $burnafterreading,
@@ -218,13 +214,7 @@ class Database extends AbstractData
         // create array
         $data       = Json::decode($row['data']);
         $isVersion2 = array_key_exists('v', $data) && $data['v'] >= 2;
-        if ($isVersion2) {
-            $paste            = $data;
-            list($createdKey) = $this->_getVersionedKeys(2);
-        } else {
-            $paste            = array('data' => $row['data']);
-            list($createdKey) = $this->_getVersionedKeys(1);
-        }
+        $paste      = $isVersion2 ? $data : array('data' => $row['data']);
 
         try {
             $row['meta'] = Json::decode($row['meta']);
@@ -233,7 +223,6 @@ class Database extends AbstractData
         }
         $row                        = self::upgradePreV1Format($row);
         $paste['meta']              = $row['meta'];
-        $paste['meta'][$createdKey] = (int) $row['postdate'];
         $expire_date                = (int) $row['expiredate'];
         if ($expire_date > 0) {
             $paste['meta']['expire_date'] = $expire_date;
@@ -751,7 +740,6 @@ class Database extends AbstractData
             'CREATE TABLE "' . $this->_sanitizeIdentifier('paste') . '" ( ' .
             "\"dataid\" CHAR(16) NOT NULL$main_key, " .
             "\"data\" $attachmentType, " .
-            '"postdate" INT, ' .
             '"expiredate" INT, ' .
             '"opendiscussion" INT, ' .
             '"burnafterreading" INT, ' .
@@ -926,6 +914,23 @@ class Database extends AbstractData
                     );
                 }
                 // no break, continue with updates for all newer versions
+            case '1.7.2':
+                $supportsDropColumn = true;
+                if ($this->_type === 'sqlite') {
+                    try {
+                        $row                = $this->_select('SELECT sqlite_version() AS "v"', array(), true);
+                        $supportsDropColumn = version_compare($row['v'], '3.35.0', '>=');
+                    } catch (PDOException $e) {
+                        $supportsDropColumn = false;
+                    }
+                }
+                if ($supportsDropColumn) {
+                    $this->_db->exec(
+                        'ALTER TABLE "' . $this->_sanitizeIdentifier('paste') .
+                        '" DROP COLUMN "postdate"'
+                    );
+                }
+                // no break, continue with updates for all newer versions
             default:
                 $this->_exec(
                     'UPDATE "' . $this->_sanitizeIdentifier('config') .

+ 18 - 4
lib/Model/Paste.php

@@ -37,7 +37,7 @@ class Paste extends AbstractModel
             throw new Exception(Controller::GENERIC_ERROR, 64);
         }
 
-        // check if paste has expired and delete it if neccessary.
+        // check if paste has expired and delete it if necessary.
         if (array_key_exists('expire_date', $data['meta'])) {
             if ($data['meta']['expire_date'] < time()) {
                 $this->delete();
@@ -47,6 +47,11 @@ class Paste extends AbstractModel
             $data['meta']['time_to_live'] = $data['meta']['expire_date'] - time();
             unset($data['meta']['expire_date']);
         }
+        foreach (array('created', 'postdate') as $key) {
+            if (array_key_exists($key, $data['meta'])) {
+                unset($data['meta'][$key]);
+            }
+        }
 
         // check if non-expired burn after reading paste needs to be deleted
         if (
@@ -92,8 +97,7 @@ class Paste extends AbstractModel
             throw new Exception('You are unlucky. Try again.', 75);
         }
 
-        $this->_data['meta']['created'] = time();
-        $this->_data['meta']['salt']    = ServerSalt::generate();
+        $this->_data['meta']['salt'] = ServerSalt::generate();
 
         // store paste
         if (
@@ -159,7 +163,17 @@ class Paste extends AbstractModel
      */
     public function getComments()
     {
-        return $this->_store->readComments($this->getId());
+        if ($this->_conf->getKey('discussiondatedisplay')) {
+            return $this->_store->readComments($this->getId());
+        }
+        return array_map(function ($comment) {
+            foreach (array('created', 'postdate') as $key) {
+                if (array_key_exists($key, $comment['meta'])) {
+                    unset($comment['meta'][$key]);
+                }
+            }
+            return $comment;
+        }, $this->_store->readComments($this->getId()));
     }
 
     /**

+ 7 - 7
lib/Vizhash16x16.php

@@ -109,9 +109,9 @@ class Vizhash16x16
         for ($i = 0; $i < 7; ++$i) {
             $action = $this->getInt();
             $color  = imagecolorallocate($image, $r, $g, $b);
-            $r      = $r0      = ((int) $r0 + $this->getInt() / 25) % 256;
-            $g      = $g0      = ((int) $g0 + $this->getInt() / 25) % 256;
-            $b      = $b0      = ((int) $b0 + $this->getInt() / 25) % 256;
+            $r      = $r0      = (int) ($r0 + $this->getInt() / 25) % 256;
+            $g      = $g0      = (int) ($g0 + $this->getInt() / 25) % 256;
+            $b      = $b0      = (int) ($b0 + $this->getInt() / 25) % 256;
             $this->drawshape($image, $action, $color);
         }
 
@@ -148,7 +148,7 @@ class Vizhash16x16
      */
     private function getX()
     {
-        return (int) $this->width * $this->getInt() / 256;
+        return (int) ($this->width * $this->getInt() / 256);
     }
 
     /**
@@ -159,7 +159,7 @@ class Vizhash16x16
      */
     private function getY()
     {
-        return (int) $this->height * $this->getInt() / 256;
+        return (int) ($this->height * $this->getInt() / 256);
     }
 
     /**
@@ -225,8 +225,8 @@ class Vizhash16x16
                 version_compare(PHP_VERSION, '8.1', '<') ? imagefilledpolygon($image, $points, 4, $color) : imagefilledpolygon($image, $points, $color);
                 break;
             default:
-                $start = $this->getInt() * 360 / 256;
-                $end   = $start + $this->getInt() * 180 / 256;
+                $start = (int) ($this->getInt() * 360 / 256);
+                $end   = (int) ($start + $this->getInt() * 180 / 256);
                 imagefilledarc($image, $this->getX(), $this->getY(), $this->getX(), $this->getY(), $start, $end, $color, IMG_ARC_PIE);
         }
     }

+ 1 - 1
tpl/bootstrap.php

@@ -73,7 +73,7 @@ endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.2.js" integrity="sha512-voYCOVXik5/jcT+McTiptsB00iB0NWQrhBmSwSEfj0IH3UDphU8w12JV8w1y+m8FRaozbzW4efHSEWKZpOA+JQ==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-hqatct2X1I7GZZFAvbnaWU+QPz+cIhBQIxhXtR50aq+pTfhvUljqzqoLi4Yli6P+GIV6IFlm5Yf/uvdEvSjMcA==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-UdOSZnkEQtdvgsyYhMSTCw2/TRv7x/jL8AtCKLnT722eudYsGPAd8wvPOU6zvdoNNJ8R43CfSJCJuCaDP2ahzA==" crossorigin="anonymous"></script>
 		<!-- icon -->
 		<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />

+ 1 - 1
tpl/bootstrap5.php

@@ -57,7 +57,7 @@ endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.2.js" integrity="sha512-voYCOVXik5/jcT+McTiptsB00iB0NWQrhBmSwSEfj0IH3UDphU8w12JV8w1y+m8FRaozbzW4efHSEWKZpOA+JQ==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-hqatct2X1I7GZZFAvbnaWU+QPz+cIhBQIxhXtR50aq+pTfhvUljqzqoLi4Yli6P+GIV6IFlm5Yf/uvdEvSjMcA==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-UdOSZnkEQtdvgsyYhMSTCw2/TRv7x/jL8AtCKLnT722eudYsGPAd8wvPOU6zvdoNNJ8R43CfSJCJuCaDP2ahzA==" crossorigin="anonymous"></script>
 		<!-- icon -->
 		<link rel="apple-touch-icon" href="<?php echo I18n::encode($BASEPATH); ?>img/apple-touch-icon.png" sizes="180x180" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png" sizes="32x32" />

+ 1 - 1
tpl/page.php

@@ -51,7 +51,7 @@ endif;
 ?>
 		<script type="text/javascript" data-cfasync="false" src="js/purify-3.1.2.js" integrity="sha512-voYCOVXik5/jcT+McTiptsB00iB0NWQrhBmSwSEfj0IH3UDphU8w12JV8w1y+m8FRaozbzW4efHSEWKZpOA+JQ==" crossorigin="anonymous"></script>
 		<script type="text/javascript" data-cfasync="false" src="js/legacy.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-LYos+qXHIRqFf5ZPNphvtTB0cgzHUizu2wwcOwcwz/VIpRv9lpcBgPYz4uq6jx0INwCAj6Fbnl5HoKiLufS2jg==" crossorigin="anonymous"></script>
-		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-hqatct2X1I7GZZFAvbnaWU+QPz+cIhBQIxhXtR50aq+pTfhvUljqzqoLi4Yli6P+GIV6IFlm5Yf/uvdEvSjMcA==" crossorigin="anonymous"></script>
+		<script type="text/javascript" data-cfasync="false" src="js/privatebin.js?<?php echo rawurlencode($VERSION); ?>" integrity="sha512-UdOSZnkEQtdvgsyYhMSTCw2/TRv7x/jL8AtCKLnT722eudYsGPAd8wvPOU6zvdoNNJ8R43CfSJCJuCaDP2ahzA==" crossorigin="anonymous"></script>
 		<!-- icon -->
 		<link rel="apple-touch-icon" href="img/apple-touch-icon.png?<?php echo rawurlencode($VERSION); ?>" sizes="180x180" />
 		<link rel="icon" type="image/png" href="img/favicon-32x32.png?<?php echo rawurlencode($VERSION); ?>" sizes="32x32" />

+ 0 - 1
tst/Bootstrap.php

@@ -660,7 +660,6 @@ class Helper
         ),
         'meta' => array(
             'expire'  => '5min',
-            'created' => 1344803344,
         ),
         'v'  => 2,
         'ct' => 'ME5JF/YBEijp2uYMzLZozbKtWc5wfy6R59NBb7SmRig=',

+ 4 - 3
tst/ControllerTest.php

@@ -170,6 +170,7 @@ class ControllerTest extends TestCase
         $this->assertEquals(0, $response['status'], 'outputs status');
         $this->assertTrue($this->_data->exists($response['id']), 'paste exists after posting data');
         $paste = $this->_data->read($response['id']);
+        $this->assertFalse(array_key_exists('created', $paste['meta']), 'does not output created');
         $this->assertEquals(
             hash_hmac('sha256', $response['id'], $paste['meta']['salt']),
             $response['deletetoken'],
@@ -712,7 +713,7 @@ class ControllerTest extends TestCase
         $this->assertEquals($paste['adata'][1], $response['adata'][1], 'outputs formatter correctly');
         $this->assertEquals($paste['adata'][2], $response['adata'][2], 'outputs opendiscussion correctly');
         $this->assertEquals($paste['adata'][3], $response['adata'][3], 'outputs burnafterreading correctly');
-        $this->assertEquals($paste['meta']['created'], $response['meta']['created'], 'outputs created correctly');
+        $this->assertFalse(array_key_exists('created', $response['meta']), 'does not output created');
         $this->assertEquals(0, $response['comment_count'], 'outputs comment_count correctly');
         $this->assertEquals(0, $response['comment_offset'], 'outputs comment_offset correctly');
         // by default it will be deleted instantly after it is read
@@ -741,7 +742,7 @@ class ControllerTest extends TestCase
         $this->assertEquals($paste['adata'][1], $response['adata'][1], 'outputs formatter correctly');
         $this->assertEquals($paste['adata'][2], $response['adata'][2], 'outputs opendiscussion correctly');
         $this->assertEquals($paste['adata'][3], $response['adata'][3], 'outputs burnafterreading correctly');
-        $this->assertEquals($paste['meta']['created'], $response['meta']['created'], 'outputs created correctly');
+        $this->assertFalse(array_key_exists('created', $response['meta']), 'does not output created');
         $this->assertEquals(0, $response['comment_count'], 'outputs comment_count correctly');
         $this->assertEquals(0, $response['comment_offset'], 'outputs comment_offset correctly');
     }
@@ -771,7 +772,7 @@ class ControllerTest extends TestCase
         $this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
         $this->assertEquals($paste['data'], $response['data'], 'outputs data correctly');
         $this->assertEquals('syntaxhighlighting', $response['meta']['formatter'], 'outputs format correctly');
-        $this->assertEquals($paste['meta']['postdate'], $response['meta']['postdate'], 'outputs postdate correctly');
+        $this->assertFalse(array_key_exists('postdate', $response['meta']), 'does not output postdate');
         $this->assertEquals($paste['meta']['opendiscussion'], $response['meta']['opendiscussion'], 'outputs opendiscussion correctly');
         $this->assertEquals(0, $response['comment_count'], 'outputs comment_count correctly');
         $this->assertEquals(0, $response['comment_offset'], 'outputs comment_offset correctly');

+ 3 - 5
tst/Data/DatabaseTest.php

@@ -259,12 +259,11 @@ class DatabaseTest extends TestCase
             $this->_options['pwd'],
             $this->_options['opt']
         );
-        $statement = $db->prepare('INSERT INTO bar_paste VALUES(?,?,?,?,?,?,?,?,?)');
+        $statement = $db->prepare('INSERT INTO bar_paste VALUES(?,?,?,?,?,?,?,?)');
         $statement->execute(
             array(
                 Helper::getPasteId(),
                 $paste['data'],
-                $paste['meta']['postdate'],
                 $paste['meta']['expire_date'],
                 0,
                 0,
@@ -292,7 +291,7 @@ class DatabaseTest extends TestCase
         $this->_options['tbl'] = 'baz_';
         $model                 = new Database($this->_options);
         $paste                 = Helper::getPaste(1, array('expire_date' => 1344803344));
-        unset($paste['meta']['formatter'], $paste['meta']['opendiscussion'], $paste['meta']['salt']);
+        unset($paste['meta']['formatter'], $paste['meta']['opendiscussion'], $paste['meta']['postdate'], $paste['meta']['salt']);
         $model->delete(Helper::getPasteId());
 
         $db = new PDO(
@@ -301,12 +300,11 @@ class DatabaseTest extends TestCase
             $this->_options['pwd'],
             $this->_options['opt']
         );
-        $statement = $db->prepare('INSERT INTO baz_paste VALUES(?,?,?,?,?,?,?,?,?)');
+        $statement = $db->prepare('INSERT INTO baz_paste VALUES(?,?,?,?,?,?,?,?)');
         $statement->execute(
             array(
                 Helper::getPasteId(),
                 $paste['data'],
-                $paste['meta']['postdate'],
                 $paste['meta']['expire_date'],
                 0,
                 0,

+ 1 - 1
tst/JsonApiTest.php

@@ -180,7 +180,7 @@ class JsonApiTest extends TestCase
         $this->assertEquals(Helper::getPasteId(), $response['id'], 'outputs data correctly');
         $this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
         $this->assertEquals($paste['ct'], $response['ct'], 'outputs data correctly');
-        $this->assertEquals($paste['meta']['created'], $response['meta']['created'], 'outputs postdate correctly');
+        $this->assertFalse(array_key_exists('created', $paste['meta']), 'does not output created');
         $this->assertEquals(0, $response['comment_count'], 'outputs comment_count correctly');
         $this->assertEquals(0, $response['comment_offset'], 'outputs comment_offset correctly');
     }

+ 10 - 6
tst/ModelTest.php

@@ -134,12 +134,11 @@ class ModelTest extends TestCase
             $options['model_options']['pwd'],
             $options['model_options']['opt']
         );
-        $statement = $db->prepare('INSERT INTO paste VALUES(?,?,?,?,?,?,?,?,?)');
+        $statement = $db->prepare('INSERT INTO paste VALUES(?,?,?,?,?,?,?,?)');
         $statement->execute(
             array(
                 Helper::getPasteId(),
                 $pasteData['data'],
-                $pasteData['meta']['postdate'],
                 0,
                 0,
                 0,
@@ -452,12 +451,13 @@ class ModelTest extends TestCase
 
     public function testCommentWithDisabledVizhash()
     {
-        $options                 = parse_ini_file(CONF, true);
-        $options['main']['icon'] = 'none';
-        $options['model']        = array(
+        $options                                  = parse_ini_file(CONF, true);
+        $options['main']['discussiondatedisplay'] = 'false';
+        $options['main']['icon']                  = 'none';
+        $options['model']                         = array(
             'class' => 'Database',
         );
-        $options['model_options'] = array(
+        $options['model_options']                 = array(
             'dsn' => 'sqlite::memory:',
             'usr' => null,
             'pwd' => null,
@@ -494,6 +494,10 @@ class ModelTest extends TestCase
 
         $comment = current($this->_model->getPaste(Helper::getPasteId())->get()['comments']);
         $this->assertFalse(array_key_exists('icon', $comment['meta']), 'icon was not generated');
+        $this->assertTrue(array_key_exists('created', $comment['meta']), 'creation is set, when using default configuration');
+
+        $comment = current($paste->get()['comments']);
+        $this->assertFalse(array_key_exists('created', $comment['meta']), 'creation is not set, if using disabled configuration');
     }
 
     public function testCommentVizhash()