"Fossies" - the Fresh Open Source Software Archive

Member "PrivateBin-1.3.1/lib/Model/Paste.php" (22 Sep 2019, 7546 Bytes) of package /linux/www/PrivateBin-1.3.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "Paste.php" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 1.3_vs_1.3.1.

    1 <?php
    2 /**
    3  * PrivateBin
    4  *
    5  * a zero-knowledge paste bin
    6  *
    7  * @link      https://github.com/PrivateBin/PrivateBin
    8  * @copyright 2012 S├ębastien SAUVAGE (sebsauvage.net)
    9  * @license   https://www.opensource.org/licenses/zlib-license.php The zlib/libpng License
   10  * @version   1.3.1
   11  */
   12 
   13 namespace PrivateBin\Model;
   14 
   15 use Exception;
   16 use PrivateBin\Controller;
   17 use PrivateBin\Persistence\ServerSalt;
   18 
   19 /**
   20  * Paste
   21  *
   22  * Model of a PrivateBin paste.
   23  */
   24 class Paste extends AbstractModel
   25 {
   26     /**
   27      * Get paste data.
   28      *
   29      * @access public
   30      * @throws Exception
   31      * @return array
   32      */
   33     public function get()
   34     {
   35         $data = $this->_store->read($this->getId());
   36         if ($data === false) {
   37             throw new Exception(Controller::GENERIC_ERROR, 64);
   38         }
   39 
   40         // check if paste has expired and delete it if neccessary.
   41         if (array_key_exists('expire_date', $data['meta'])) {
   42             if ($data['meta']['expire_date'] < time()) {
   43                 $this->delete();
   44                 throw new Exception(Controller::GENERIC_ERROR, 63);
   45             }
   46             // We kindly provide the remaining time before expiration (in seconds)
   47             $data['meta']['time_to_live'] = $data['meta']['expire_date'] - time();
   48             unset($data['meta']['expire_date']);
   49         }
   50 
   51         // check if non-expired burn after reading paste needs to be deleted
   52         if (
   53             (array_key_exists('adata', $data) && $data['adata'][3] === 1) ||
   54             (array_key_exists('burnafterreading', $data['meta']) && $data['meta']['burnafterreading'])
   55         ) {
   56             $this->delete();
   57         }
   58 
   59         // set formatter for the view in version 1 pastes.
   60         if (array_key_exists('data', $data) && !array_key_exists('formatter', $data['meta'])) {
   61             // support < 0.21 syntax highlighting
   62             if (array_key_exists('syntaxcoloring', $data['meta']) && $data['meta']['syntaxcoloring'] === true) {
   63                 $data['meta']['formatter'] = 'syntaxhighlighting';
   64             } else {
   65                 $data['meta']['formatter'] = $this->_conf->getKey('defaultformatter');
   66             }
   67         }
   68 
   69         // support old paste format with server wide salt
   70         if (!array_key_exists('salt', $data['meta'])) {
   71             $data['meta']['salt'] = ServerSalt::get();
   72         }
   73         $data['comments']       = array_values($this->getComments());
   74         $data['comment_count']  = count($data['comments']);
   75         $data['comment_offset'] = 0;
   76         $data['@context']       = '?jsonld=paste';
   77         $this->_data            = $data;
   78 
   79         return $this->_data;
   80     }
   81 
   82     /**
   83      * Store the paste's data.
   84      *
   85      * @access public
   86      * @throws Exception
   87      */
   88     public function store()
   89     {
   90         // Check for improbable collision.
   91         if ($this->exists()) {
   92             throw new Exception('You are unlucky. Try again.', 75);
   93         }
   94 
   95         $this->_data['meta']['created'] = time();
   96         $this->_data['meta']['salt']    = serversalt::generate();
   97 
   98         // store paste
   99         if (
  100             $this->_store->create(
  101                 $this->getId(),
  102                 $this->_data
  103             ) === false
  104         ) {
  105             throw new Exception('Error saving paste. Sorry.', 76);
  106         }
  107     }
  108 
  109     /**
  110      * Delete the paste.
  111      *
  112      * @access public
  113      * @throws Exception
  114      */
  115     public function delete()
  116     {
  117         $this->_store->delete($this->getId());
  118     }
  119 
  120     /**
  121      * Test if paste exists in store.
  122      *
  123      * @access public
  124      * @return bool
  125      */
  126     public function exists()
  127     {
  128         return $this->_store->exists($this->getId());
  129     }
  130 
  131     /**
  132      * Get a comment, optionally a specific instance.
  133      *
  134      * @access public
  135      * @param string $parentId
  136      * @param string $commentId
  137      * @throws Exception
  138      * @return Comment
  139      */
  140     public function getComment($parentId, $commentId = '')
  141     {
  142         if (!$this->exists()) {
  143             throw new Exception('Invalid data.', 62);
  144         }
  145         $comment = new Comment($this->_conf, $this->_store);
  146         $comment->setPaste($this);
  147         $comment->setParentId($parentId);
  148         if ($commentId !== '') {
  149             $comment->setId($commentId);
  150         }
  151         return $comment;
  152     }
  153 
  154     /**
  155      * Get all comments, if any.
  156      *
  157      * @access public
  158      * @return array
  159      */
  160     public function getComments()
  161     {
  162         return $this->_store->readComments($this->getId());
  163     }
  164 
  165     /**
  166      * Generate the "delete" token.
  167      *
  168      * The token is the hmac of the pastes ID signed with the server salt.
  169      * The paste can be deleted by calling:
  170      * https://example.com/privatebin/?pasteid=<pasteid>&deletetoken=<deletetoken>
  171      *
  172      * @access public
  173      * @return string
  174      */
  175     public function getDeleteToken()
  176     {
  177         if (!array_key_exists('salt', $this->_data['meta'])) {
  178             $this->get();
  179         }
  180         return hash_hmac(
  181             $this->_conf->getKey('zerobincompatibility') ? 'sha1' : 'sha256',
  182             $this->getId(),
  183             $this->_data['meta']['salt']
  184         );
  185     }
  186 
  187     /**
  188      * Check if paste has discussions enabled.
  189      *
  190      * @access public
  191      * @throws Exception
  192      * @return bool
  193      */
  194     public function isOpendiscussion()
  195     {
  196         if (!array_key_exists('adata', $this->_data) && !array_key_exists('data', $this->_data)) {
  197             $this->get();
  198         }
  199         return
  200             (array_key_exists('adata', $this->_data) && $this->_data['adata'][2] === 1) ||
  201             (array_key_exists('opendiscussion', $this->_data['meta']) && $this->_data['meta']['opendiscussion']);
  202     }
  203 
  204     /**
  205      * Sanitizes data to conform with current configuration.
  206      *
  207      * @access protected
  208      * @param  array $data
  209      * @return array
  210      */
  211     protected function _sanitize(array $data)
  212     {
  213         $expiration = $data['meta']['expire'];
  214         unset($data['meta']['expire']);
  215         $expire_options = $this->_conf->getSection('expire_options');
  216         if (array_key_exists($expiration, $expire_options)) {
  217             $expire = $expire_options[$expiration];
  218         } else {
  219             // using getKey() to ensure a default value is present
  220             $expire = $this->_conf->getKey($this->_conf->getKey('default', 'expire'), 'expire_options');
  221         }
  222         if ($expire > 0) {
  223             $data['meta']['expire_date'] = time() + $expire;
  224         }
  225         return $data;
  226     }
  227 
  228     /**
  229      * Validate data.
  230      *
  231      * @access protected
  232      * @param  array $data
  233      * @throws Exception
  234      */
  235     protected function _validate(array $data)
  236     {
  237         // reject invalid or disabled formatters
  238         if (!array_key_exists($data['adata'][1], $this->_conf->getSection('formatter_options'))) {
  239             throw new Exception('Invalid data.', 75);
  240         }
  241 
  242         // discussion requested, but disabled in config or burn after reading requested as well, or invalid integer
  243         if (
  244             ($data['adata'][2] === 1 && ( // open discussion flag
  245                 !$this->_conf->getKey('discussion') ||
  246                 $data['adata'][3] === 1  // burn after reading flag
  247             )) ||
  248             ($data['adata'][2] !== 0 && $data['adata'][2] !== 1)
  249         ) {
  250             throw new Exception('Invalid data.', 74);
  251         }
  252 
  253         // reject invalid burn after reading
  254         if ($data['adata'][3] !== 0 && $data['adata'][3] !== 1) {
  255             throw new Exception('Invalid data.', 73);
  256         }
  257     }
  258 }