ModelTest.php 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. <?php
  2. use PrivateBin\Configuration;
  3. use PrivateBin\Data\Database;
  4. use PrivateBin\Model;
  5. use PrivateBin\Model\Paste;
  6. use PrivateBin\Persistence\ServerSalt;
  7. use PrivateBin\Vizhash16x16;
  8. class ModelTest extends PHPUnit_Framework_TestCase
  9. {
  10. private $_conf;
  11. private $_model;
  12. protected $_path;
  13. public function setUp()
  14. {
  15. /* Setup Routine */
  16. Helper::confRestore();
  17. $this->_path = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'privatebin_data';
  18. if (!is_dir($this->_path)) mkdir($this->_path);
  19. ServerSalt::setPath($this->_path);
  20. $options = parse_ini_file(CONF, true);
  21. $options['purge']['limit'] = 0;
  22. $options['model'] = array(
  23. 'class' => 'Database',
  24. );
  25. $options['model_options'] = array(
  26. 'dsn' => 'sqlite::memory:',
  27. 'usr' => null,
  28. 'pwd' => null,
  29. 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
  30. );
  31. Helper::confBackup();
  32. Helper::createIniFile(CONF, $options);
  33. $this->_conf = new Configuration;
  34. $this->_model = new Model($this->_conf);
  35. $_SERVER['REMOTE_ADDR'] = '::1';
  36. }
  37. public function tearDown()
  38. {
  39. /* Tear Down Routine */
  40. Helper::confRestore();
  41. Helper::rmDir($this->_path);
  42. }
  43. public function testBasicWorkflow()
  44. {
  45. // storing pastes
  46. $pasteData = Helper::getPaste();
  47. $this->_model->getPaste(Helper::getPasteId())->delete();
  48. $paste = $this->_model->getPaste(Helper::getPasteId());
  49. $this->assertFalse($paste->exists(), 'paste does not yet exist');
  50. $paste = $this->_model->getPaste();
  51. $paste->setData($pasteData['data']);
  52. $paste->setOpendiscussion();
  53. $paste->setFormatter($pasteData['meta']['formatter']);
  54. $paste->store();
  55. $paste = $this->_model->getPaste(Helper::getPasteId());
  56. $this->assertTrue($paste->exists(), 'paste exists after storing it');
  57. $paste = $paste->get();
  58. $this->assertEquals($pasteData['data'], $paste->data);
  59. foreach (array('opendiscussion', 'formatter') as $key) {
  60. $this->assertEquals($pasteData['meta'][$key], $paste->meta->$key);
  61. }
  62. // storing comments
  63. $commentData = Helper::getComment();
  64. $paste = $this->_model->getPaste(Helper::getPasteId());
  65. $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
  66. $this->assertFalse($comment->exists(), 'comment does not yet exist');
  67. $comment = $paste->getComment(Helper::getPasteId());
  68. $comment->setData($commentData['data']);
  69. $comment->setNickname($commentData['meta']['nickname']);
  70. $comment->store();
  71. $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
  72. $this->assertTrue($comment->exists(), 'comment exists after storing it');
  73. $comment = $comment->get();
  74. $this->assertEquals($commentData['data'], $comment->data);
  75. $this->assertEquals($commentData['meta']['nickname'], $comment->meta->nickname);
  76. // deleting pastes
  77. $this->_model->getPaste(Helper::getPasteId())->delete();
  78. $paste = $this->_model->getPaste(Helper::getPasteId());
  79. $this->assertFalse($paste->exists(), 'paste successfully deleted');
  80. $this->assertEquals(array(), $paste->getComments(), 'comment was deleted with paste');
  81. }
  82. /**
  83. * @expectedException Exception
  84. * @expectedExceptionCode 75
  85. */
  86. public function testPasteDuplicate()
  87. {
  88. $pasteData = Helper::getPaste();
  89. $this->_model->getPaste(Helper::getPasteId())->delete();
  90. $paste = $this->_model->getPaste();
  91. $paste->setData($pasteData['data']);
  92. $paste->setOpendiscussion();
  93. $paste->setFormatter($pasteData['meta']['formatter']);
  94. $paste->store();
  95. $paste = $this->_model->getPaste();
  96. $paste->setData($pasteData['data']);
  97. $paste->setOpendiscussion();
  98. $paste->setFormatter($pasteData['meta']['formatter']);
  99. $paste->store();
  100. }
  101. /**
  102. * @expectedException Exception
  103. * @expectedExceptionCode 69
  104. */
  105. public function testCommentDuplicate()
  106. {
  107. $pasteData = Helper::getPaste();
  108. $commentData = Helper::getComment();
  109. $this->_model->getPaste(Helper::getPasteId())->delete();
  110. $paste = $this->_model->getPaste();
  111. $paste->setData($pasteData['data']);
  112. $paste->setOpendiscussion();
  113. $paste->setFormatter($pasteData['meta']['formatter']);
  114. $paste->store();
  115. $comment = $paste->getComment(Helper::getPasteId());
  116. $comment->setData($commentData['data']);
  117. $comment->setNickname($commentData['meta']['nickname']);
  118. $comment->store();
  119. $comment = $paste->getComment(Helper::getPasteId());
  120. $comment->setData($commentData['data']);
  121. $comment->setNickname($commentData['meta']['nickname']);
  122. $comment->store();
  123. }
  124. public function testImplicitDefaults()
  125. {
  126. $pasteData = Helper::getPaste();
  127. $commentData = Helper::getComment();
  128. $this->_model->getPaste(Helper::getPasteId())->delete();
  129. $paste = $this->_model->getPaste();
  130. $paste->setData($pasteData['data']);
  131. $paste->setBurnafterreading();
  132. $paste->setOpendiscussion();
  133. // not setting a formatter, should use default one
  134. $paste->store();
  135. $paste = $this->_model->getPaste(Helper::getPasteId())->get(); // ID was set based on data
  136. $this->assertEquals(true, property_exists($paste->meta, 'burnafterreading') && $paste->meta->burnafterreading, 'burn after reading takes precendence');
  137. $this->assertEquals(false, property_exists($paste->meta, 'opendiscussion') && $paste->meta->opendiscussion, 'opendiscussion is disabled');
  138. $this->assertEquals($this->_conf->getKey('defaultformatter'), $paste->meta->formatter, 'default formatter is set');
  139. $this->_model->getPaste(Helper::getPasteId())->delete();
  140. $paste = $this->_model->getPaste();
  141. $paste->setData($pasteData['data']);
  142. $paste->setBurnafterreading('0');
  143. $paste->setOpendiscussion();
  144. $paste->store();
  145. $vz = new Vizhash16x16();
  146. $pngdata = 'data:image/png;base64,' . base64_encode($vz->generate($_SERVER['REMOTE_ADDR']));
  147. $comment = $paste->getComment(Helper::getPasteId());
  148. $comment->setData($commentData['data']);
  149. $comment->setNickname($commentData['meta']['nickname']);
  150. $comment->store();
  151. $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId())->get();
  152. $this->assertEquals($pngdata, $comment->meta->vizhash, 'nickname triggers vizhash to be set');
  153. }
  154. public function testPasteIdValidation()
  155. {
  156. $this->assertTrue(Paste::isValidId('a242ab7bdfb2581a'), 'valid paste id');
  157. $this->assertFalse(Paste::isValidId('foo'), 'invalid hex values');
  158. $this->assertFalse(Paste::isValidId('../bar/baz'), 'path attack');
  159. }
  160. /**
  161. * @expectedException Exception
  162. * @expectedExceptionCode 62
  163. */
  164. public function testInvalidComment()
  165. {
  166. $paste = $this->_model->getPaste();
  167. $paste->getComment(Helper::getPasteId());
  168. }
  169. public function testExpiration()
  170. {
  171. $pasteData = Helper::getPaste();
  172. $this->_model->getPaste(Helper::getPasteId())->delete();
  173. $paste = $this->_model->getPaste(Helper::getPasteId());
  174. $this->assertFalse($paste->exists(), 'paste does not yet exist');
  175. $paste = $this->_model->getPaste();
  176. $paste->setData($pasteData['data']);
  177. $paste->setExpiration('5min'); // = 300 seconds
  178. $paste->store();
  179. $paste = $paste->get();
  180. $this->assertEquals(300, $paste->meta->remaining_time, 'remaining time is set correctly');
  181. }
  182. /**
  183. * @expectedException Exception
  184. * @expectedExceptionCode 64
  185. */
  186. public function testCommentDeletion()
  187. {
  188. $pasteData = Helper::getPaste();
  189. $this->_model->getPaste(Helper::getPasteId())->delete();
  190. $paste = $this->_model->getPaste();
  191. $paste->setData($pasteData['data']);
  192. $paste->store();
  193. $paste->getComment(Helper::getPasteId())->delete();
  194. }
  195. public function testPurge()
  196. {
  197. $conf = new Configuration;
  198. $store = Database::getInstance($conf->getSection('model_options'));
  199. $store->delete(Helper::getPasteId());
  200. $expired = Helper::getPaste(array('expire_date' => 1344803344));
  201. $paste = Helper::getPaste(array('expire_date' => time() + 3600));
  202. $keys = array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'x', 'y', 'z');
  203. $ids = array();
  204. foreach ($keys as $key) {
  205. $ids[$key] = substr(md5($key), 0, 16);
  206. $store->delete($ids[$key]);
  207. $this->assertFalse($store->exists($ids[$key]), "paste $key does not yet exist");
  208. if (in_array($key, array('x', 'y', 'z'))) {
  209. $this->assertTrue($store->create($ids[$key], $paste), "store $key paste");
  210. } else {
  211. $this->assertTrue($store->create($ids[$key], $expired), "store $key paste");
  212. }
  213. $this->assertTrue($store->exists($ids[$key]), "paste $key exists after storing it");
  214. }
  215. $this->_model->purge(10);
  216. foreach ($ids as $key => $id) {
  217. if (in_array($key, array('x', 'y', 'z'))) {
  218. $this->assertTrue($this->_model->getPaste($id)->exists(), "paste $key exists after purge");
  219. $this->_model->getPaste($id)->delete();
  220. } else {
  221. $this->assertFalse($this->_model->getPaste($id)->exists(), "paste $key was purged");
  222. }
  223. }
  224. }
  225. public function testCommentWithDisabledVizhash()
  226. {
  227. $options = parse_ini_file(CONF, true);
  228. $options['main']['vizhash'] = false;
  229. $options['model'] = array(
  230. 'class' => 'privatebin_db',
  231. );
  232. $options['model_options'] = array(
  233. 'dsn' => 'sqlite::memory:',
  234. 'usr' => null,
  235. 'pwd' => null,
  236. 'opt' => array(PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION),
  237. );
  238. Helper::confBackup();
  239. Helper::createIniFile(CONF, $options);
  240. $model = new Model(new Configuration);
  241. $pasteData = Helper::getPaste();
  242. $this->_model->getPaste(Helper::getPasteId())->delete();
  243. $paste = $model->getPaste(Helper::getPasteId());
  244. $this->assertFalse($paste->exists(), 'paste does not yet exist');
  245. $paste = $model->getPaste();
  246. $paste->setData($pasteData['data']);
  247. $paste->setOpendiscussion();
  248. $paste->setFormatter($pasteData['meta']['formatter']);
  249. $paste->store();
  250. $paste = $model->getPaste(Helper::getPasteId());
  251. $this->assertTrue($paste->exists(), 'paste exists after storing it');
  252. $paste = $paste->get();
  253. $this->assertEquals($pasteData['data'], $paste->data);
  254. foreach (array('opendiscussion', 'formatter') as $key) {
  255. $this->assertEquals($pasteData['meta'][$key], $paste->meta->$key);
  256. }
  257. // storing comments
  258. $commentData = Helper::getComment();
  259. $paste = $model->getPaste(Helper::getPasteId());
  260. $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
  261. $this->assertFalse($comment->exists(), 'comment does not yet exist');
  262. $comment = $paste->getComment(Helper::getPasteId());
  263. $comment->setData($commentData['data']);
  264. $comment->setNickname($commentData['meta']['nickname']);
  265. $comment->store();
  266. $comment = $paste->getComment(Helper::getPasteId(), Helper::getCommentId());
  267. $this->assertTrue($comment->exists(), 'comment exists after storing it');
  268. $comment = $comment->get();
  269. $this->assertEquals($commentData['data'], $comment->data);
  270. $this->assertEquals($commentData['meta']['nickname'], $comment->meta->nickname);
  271. $this->assertFalse(property_exists($comment->meta, 'vizhash'), 'vizhash was not generated');
  272. }
  273. }