Просмотр исходного кода

burn after reading messages are only deleted after callback by JS when
successfully decrypted, resolves #11

El RIDO 11 лет назад
Родитель
Сommit
802a0b26b9
3 измененных файлов с 94 добавлено и 22 удалено
  1. 8 5
      js/zerobin.js
  2. 48 17
      lib/zerobin.php
  3. 38 0
      tst/zerobin.php

+ 8 - 5
js/zerobin.js

@@ -238,6 +238,10 @@ function displayMessages(key, comments) {
     // Display paste expiration.
     if (comments[0].meta.expire_date) $('#remainingtime').removeClass('foryoureyesonly').text('This document will expire in '+secondsToHuman(comments[0].meta.remaining_time)+'.').removeClass('hidden');
     if (comments[0].meta.burnafterreading) {
+        $.get(scriptLocation() + "?pasteid=" + pasteID() + '&deletetoken=burnafterreading', 'json')
+        .fail(function() {
+            showError('Could not delete the paste, it was not stored in burn after reading mode.');
+        });
         $('#remainingtime').addClass('foryoureyesonly').text('FOR YOUR EYES ONLY.  Don\'t close this window, this message can\'t be displayed again.').removeClass('hidden');
         $('#clonebutton').addClass('hidden'); // Discourage cloning (as it can't really be prevented).
     }
@@ -382,11 +386,7 @@ function send_data() {
                          burnafterreading: $('#burnafterreading').is(':checked') ? 1 : 0,
                          opendiscussion: $('#opendiscussion').is(':checked') ? 1 : 0
                        };
-    $.post(scriptLocation(), data_to_send, 'json')
-    .error(function() {
-        showError('Data could not be sent (serveur error or not responding).');
-    })
-    .success(function(data) {
+    $.post(scriptLocation(), data_to_send, function(data) {
         if (data.status == 0) {
             stateExistingPaste();
             var url = scriptLocation() + "?" + data.id + '#' + randomkey;
@@ -412,6 +412,9 @@ function send_data() {
         else {
             showError('Could not create paste.');
         }
+    }, 'json')
+    .fail(function() {
+        showError('Data could not be sent (server error or not responding).');
     });
 }
 

+ 48 - 17
lib/zerobin.php

@@ -24,6 +24,13 @@ class zerobin
      */
     const VERSION = 'Alpha 0.19';
 
+    /**
+     * show the same error message if the paste expired or does not exist
+     *
+     * @const string
+     */
+    const GENERIC_ERROR = 'Paste does not exist, has expired or has been deleted.';
+
     /**
      * configuration array
      *
@@ -99,7 +106,11 @@ class zerobin
         // delete an existing paste
         elseif (!empty($_GET['deletetoken']) && !empty($_GET['pasteid']))
         {
-            $this->_delete($_GET['pasteid'], $_GET['deletetoken']);
+            $result = $this->_delete($_GET['pasteid'], $_GET['deletetoken']);
+            if (strlen($result)) {
+                echo $result;
+                return;
+            }
         }
         // display an existing paste
         elseif (!empty($_SERVER['QUERY_STRING']))
@@ -355,7 +366,7 @@ class zerobin
      * @access private
      * @param  string $dataid
      * @param  string $deletetoken
-     * @return void
+     * @return string
      */
     private function _delete($dataid, $deletetoken)
     {
@@ -363,14 +374,42 @@ class zerobin
         if (!filter::is_valid_paste_id($dataid))
         {
             $this->_error = 'Invalid paste ID.';
-            return;
+            return '';
         }
 
         // Check that paste exists.
         if (!$this->_model()->exists($dataid))
         {
-            $this->_error = 'Paste does not exist, has expired or has been deleted.';
-            return;
+            $this->_error = self::GENERIC_ERROR;
+            return '';
+        }
+
+        // Get the paste itself.
+        $paste = $this->_model()->read($dataid);
+
+        // See if paste has expired.
+        if (
+            isset($paste->meta->expire_date) &&
+            $paste->meta->expire_date < time()
+        )
+        {
+            // Delete the paste
+            $this->_model()->delete($dataid);
+            $this->_error = self::GENERIC_ERROR;
+        }
+
+        if ($deletetoken == 'burnafterreading') {
+            header('Content-type: application/json');
+            if (
+                isset($paste->meta->burnafterreading) &&
+                $paste->meta->burnafterreading
+            )
+            {
+                // Delete the paste
+                $this->_model()->delete($dataid);
+                return $this->_return_message(0, 'Paste was properly deleted.');
+            }
+            return $this->_return_message(1, 'Paste is not of burn-after-reading type.');
         }
 
         // Make sure token is valid.
@@ -378,12 +417,13 @@ class zerobin
         if (!filter::slow_equals($deletetoken, hash_hmac('sha1', $dataid, serversalt::get())))
         {
             $this->_error = 'Wrong deletion token. Paste was not deleted.';
-            return;
+            return '';
         }
 
         // Paste exists and deletion token is valid: Delete the paste.
         $this->_model()->delete($dataid);
         $this->_status = 'Paste was properly deleted.';
+        return '';
     }
 
     /**
@@ -402,9 +442,6 @@ class zerobin
             return;
         }
 
-        // show the same error message if the paste expired or does not exist
-        $genericError = 'Paste does not exist, has expired or has been deleted.';
-
         // Check that paste exists.
         if ($this->_model()->exists($dataid))
         {
@@ -419,7 +456,7 @@ class zerobin
             {
                 // Delete the paste
                 $this->_model()->delete($dataid);
-                $this->_error = $genericError;
+                $this->_error = self::GENERIC_ERROR;
             }
             // If no error, return the paste.
             else
@@ -444,17 +481,11 @@ class zerobin
                     );
                 }
                 $this->_data = json_encode($messages);
-
-                // If the paste was meant to be read only once, delete it.
-                if (
-                    property_exists($paste->meta, 'burnafterreading') &&
-                    $paste->meta->burnafterreading
-                ) $this->_model()->delete($dataid);
             }
         }
         else
         {
-            $this->_error = $genericError;
+            $this->_error = self::GENERIC_ERROR;
         }
     }
 

+ 38 - 0
tst/zerobin.php

@@ -527,4 +527,42 @@ class zerobinTest extends PHPUnit_Framework_TestCase
         );
         $this->assertTrue($this->_model->exists(self::$pasteid), 'paste exists after failing to delete data');
     }
+
+    /**
+     * @runInSeparateProcess
+     */
+    public function testDeleteBurnAfterReading()
+    {
+        $this->reset();
+        $burnPaste = self::$paste;
+        $burnPaste['meta']['burnafterreading'] = true;
+        $this->_model->create(self::$pasteid, $burnPaste);
+        $this->assertTrue($this->_model->exists(self::$pasteid), 'paste exists before deleting data');
+        $_GET['pasteid'] = self::$pasteid;
+        $_GET['deletetoken'] = 'burnafterreading';
+        ob_start();
+        new zerobin;
+        $content = ob_get_contents();
+        $response = json_decode($content, true);
+        $this->assertEquals(0, $response['status'], 'outputs status');
+        $this->assertFalse($this->_model->exists(self::$pasteid), 'paste successfully deleted');
+    }
+
+    /**
+     * @runInSeparateProcess
+     */
+    public function testDeleteInvalidBurnAfterReading()
+    {
+        $this->reset();
+        $this->_model->create(self::$pasteid, self::$paste);
+        $this->assertTrue($this->_model->exists(self::$pasteid), 'paste exists before deleting data');
+        $_GET['pasteid'] = self::$pasteid;
+        $_GET['deletetoken'] = 'burnafterreading';
+        ob_start();
+        new zerobin;
+        $content = ob_get_contents();
+        $response = json_decode($content, true);
+        $this->assertEquals(1, $response['status'], 'outputs status');
+        $this->assertTrue($this->_model->exists(self::$pasteid), 'paste successfully deleted');
+    }
 }