Comment.php 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  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.0
  11. */
  12. namespace PrivateBin\Model;
  13. use Exception;
  14. use Identicon\Identicon;
  15. use PrivateBin\Persistence\TrafficLimiter;
  16. use PrivateBin\Sjcl;
  17. use PrivateBin\Vizhash16x16;
  18. /**
  19. * Comment
  20. *
  21. * Model of a PrivateBin comment.
  22. */
  23. class Comment extends AbstractModel
  24. {
  25. /**
  26. * Instance's parent.
  27. *
  28. * @access private
  29. * @var Paste
  30. */
  31. private $_paste;
  32. /**
  33. * Get comment data.
  34. *
  35. * @access public
  36. * @throws Exception
  37. * @return stdClass
  38. */
  39. public function get()
  40. {
  41. // @todo add support to read specific comment
  42. $comments = $this->_store->readComments($this->getPaste()->getId());
  43. foreach ($comments as $comment) {
  44. if (
  45. $comment->parentid == $this->getParentId() &&
  46. $comment->id == $this->getId()
  47. ) {
  48. $this->_data = $comment;
  49. break;
  50. }
  51. }
  52. return $this->_data;
  53. }
  54. /**
  55. * Store the comment's data.
  56. *
  57. * @access public
  58. * @throws Exception
  59. * @return void
  60. */
  61. public function store()
  62. {
  63. // Make sure paste exists.
  64. $pasteid = $this->getPaste()->getId();
  65. if (!$this->getPaste()->exists()) {
  66. throw new Exception('Invalid data.', 67);
  67. }
  68. // Make sure the discussion is opened in this paste and in configuration.
  69. if (!$this->getPaste()->isOpendiscussion() || !$this->_conf->getKey('discussion')) {
  70. throw new Exception('Invalid data.', 68);
  71. }
  72. // Check for improbable collision.
  73. if ($this->exists()) {
  74. throw new Exception('You are unlucky. Try again.', 69);
  75. }
  76. $this->_data->meta->postdate = time();
  77. // store comment
  78. if (
  79. $this->_store->createComment(
  80. $pasteid,
  81. $this->getParentId(),
  82. $this->getId(),
  83. json_decode(json_encode($this->_data), true)
  84. ) === false
  85. ) {
  86. throw new Exception('Error saving comment. Sorry.', 70);
  87. }
  88. }
  89. /**
  90. * Delete the comment.
  91. *
  92. * @access public
  93. * @throws Exception
  94. * @return void
  95. */
  96. public function delete()
  97. {
  98. throw new Exception('To delete a comment, delete its parent paste', 64);
  99. }
  100. /**
  101. * Test if comment exists in store.
  102. *
  103. * @access public
  104. * @return bool
  105. */
  106. public function exists()
  107. {
  108. return $this->_store->existsComment(
  109. $this->getPaste()->getId(),
  110. $this->getParentId(),
  111. $this->getId()
  112. );
  113. }
  114. /**
  115. * Set paste.
  116. *
  117. * @access public
  118. * @param Paste $paste
  119. * @throws Exception
  120. * @return void
  121. */
  122. public function setPaste(Paste $paste)
  123. {
  124. $this->_paste = $paste;
  125. $this->_data->meta->pasteid = $paste->getId();
  126. }
  127. /**
  128. * Get paste.
  129. *
  130. * @access public
  131. * @return Paste
  132. */
  133. public function getPaste()
  134. {
  135. return $this->_paste;
  136. }
  137. /**
  138. * Set parent ID.
  139. *
  140. * @access public
  141. * @param string $id
  142. * @throws Exception
  143. * @return void
  144. */
  145. public function setParentId($id)
  146. {
  147. if (!self::isValidId($id)) {
  148. throw new Exception('Invalid paste ID.', 65);
  149. }
  150. $this->_data->meta->parentid = $id;
  151. }
  152. /**
  153. * Get parent ID.
  154. *
  155. * @access public
  156. * @return string
  157. */
  158. public function getParentId()
  159. {
  160. if (!property_exists($this->_data->meta, 'parentid')) {
  161. $this->_data->meta->parentid = '';
  162. }
  163. return $this->_data->meta->parentid;
  164. }
  165. /**
  166. * Set nickname.
  167. *
  168. * @access public
  169. * @param string $nickname
  170. * @throws Exception
  171. * @return void
  172. */
  173. public function setNickname($nickname)
  174. {
  175. if (!Sjcl::isValid($nickname)) {
  176. throw new Exception('Invalid data.', 66);
  177. }
  178. $this->_data->meta->nickname = $nickname;
  179. // If a nickname is provided, we generate an icon based on a SHA512 HMAC
  180. // of the users IP. (We assume that if the user did not enter a nickname,
  181. // the user wants to be anonymous and we will not generate an icon.)
  182. $icon = $this->_conf->getKey('icon');
  183. if ($icon != 'none') {
  184. $pngdata = '';
  185. $hmac = TrafficLimiter::getHash();
  186. if ($icon == 'identicon') {
  187. $identicon = new Identicon();
  188. $pngdata = $identicon->getImageDataUri($hmac, 16);
  189. } elseif ($icon == 'vizhash') {
  190. $vh = new Vizhash16x16();
  191. $pngdata = 'data:image/png;base64,' . base64_encode(
  192. $vh->generate($hmac)
  193. );
  194. }
  195. if ($pngdata != '') {
  196. $this->_data->meta->vizhash = $pngdata;
  197. }
  198. }
  199. // Once the icon is generated, we do not keep the IP address hash.
  200. }
  201. }