zerobin.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979
  1. <?php
  2. class zerobinTest extends PHPUnit_Framework_TestCase
  3. {
  4. protected $_model;
  5. public function setUp()
  6. {
  7. /* Setup Routine */
  8. $this->_model = zerobin_data::getInstance(array('dir' => PATH . 'data'));
  9. serversalt::setPath(PATH . 'data');
  10. $this->reset();
  11. }
  12. public function tearDown()
  13. {
  14. /* Tear Down Routine */
  15. helper::confRestore();
  16. }
  17. public function reset()
  18. {
  19. $_POST = array();
  20. $_GET = array();
  21. $_SERVER = array();
  22. if ($this->_model->exists(helper::getPasteId()))
  23. $this->_model->delete(helper::getPasteId());
  24. helper::confRestore();
  25. }
  26. /**
  27. * @runInSeparateProcess
  28. */
  29. public function testView()
  30. {
  31. $this->reset();
  32. ob_start();
  33. new zerobin;
  34. $content = ob_get_contents();
  35. $this->assertContains(
  36. '<title>ZeroBin</title>',
  37. $content,
  38. 'outputs title correctly'
  39. );
  40. $this->assertNotContains(
  41. 'id="shortenbutton"',
  42. $content,
  43. 'doesn\'t output shortener button'
  44. );
  45. }
  46. /**
  47. * @runInSeparateProcess
  48. */
  49. public function testViewLanguageSelection()
  50. {
  51. $this->reset();
  52. $options = parse_ini_file(CONF, true);
  53. $options['main']['languageselection'] = true;
  54. helper::confBackup();
  55. helper::createIniFile(CONF, $options);
  56. $_COOKIE['lang'] = 'de';
  57. ob_start();
  58. new zerobin;
  59. $content = ob_get_contents();
  60. $this->assertContains(
  61. '<title>ZeroBin</title>',
  62. $content,
  63. 'outputs title correctly'
  64. );
  65. }
  66. /**
  67. * @runInSeparateProcess
  68. */
  69. public function testViewForceLanguageDefault()
  70. {
  71. $this->reset();
  72. $options = parse_ini_file(CONF, true);
  73. $options['main']['languageselection'] = false;
  74. $options['main']['languagedefault'] = 'fr';
  75. helper::confBackup();
  76. helper::createIniFile(CONF, $options);
  77. $_COOKIE['lang'] = 'de';
  78. ob_start();
  79. new zerobin;
  80. $content = ob_get_contents();
  81. $this->assertContains(
  82. '<title>ZeroBin</title>',
  83. $content,
  84. 'outputs title correctly'
  85. );
  86. }
  87. /**
  88. * @runInSeparateProcess
  89. */
  90. public function testViewUrlShortener()
  91. {
  92. $shortener = 'https://shortener.example.com/api?link=';
  93. $this->reset();
  94. $options = parse_ini_file(CONF, true);
  95. $options['main']['urlshortener'] = $shortener;
  96. helper::confBackup();
  97. helper::createIniFile(CONF, $options);
  98. $_COOKIE['lang'] = 'de';
  99. ob_start();
  100. new zerobin;
  101. $content = ob_get_contents();
  102. $this->assertRegExp(
  103. '#id="shortenbutton"[^>]*data-shortener="' . preg_quote($shortener) . '"#',
  104. $content,
  105. 'outputs configured shortener URL correctly'
  106. );
  107. }
  108. /**
  109. * @runInSeparateProcess
  110. */
  111. public function testHtaccess()
  112. {
  113. $this->reset();
  114. $dirs = array('cfg', 'lib');
  115. foreach ($dirs as $dir) {
  116. $file = PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess';
  117. @unlink($file);
  118. }
  119. ob_start();
  120. new zerobin;
  121. ob_end_clean();
  122. foreach ($dirs as $dir) {
  123. $file = PATH . $dir . DIRECTORY_SEPARATOR . '.htaccess';
  124. $this->assertFileExists(
  125. $file,
  126. "$dir htaccess recreated"
  127. );
  128. }
  129. }
  130. /**
  131. * @expectedException Exception
  132. * @expectedExceptionCode 2
  133. */
  134. public function testConf()
  135. {
  136. $this->reset();
  137. helper::confBackup();
  138. file_put_contents(CONF, '');
  139. ob_start();
  140. new zerobin;
  141. ob_end_clean();
  142. }
  143. /**
  144. * @runInSeparateProcess
  145. */
  146. public function testCreate()
  147. {
  148. $this->reset();
  149. $options = parse_ini_file(CONF, true);
  150. $options['traffic']['limit'] = 0;
  151. helper::confBackup();
  152. helper::createIniFile(CONF, $options);
  153. $_POST = helper::getPaste();
  154. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  155. $_SERVER['REQUEST_METHOD'] = 'POST';
  156. $_SERVER['REMOTE_ADDR'] = '::1';
  157. ob_start();
  158. new zerobin;
  159. $content = ob_get_contents();
  160. $response = json_decode($content, true);
  161. $this->assertEquals(0, $response['status'], 'outputs status');
  162. $this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
  163. $paste = $this->_model->read($response['id']);
  164. $this->assertEquals(
  165. hash_hmac('sha256', $response['id'], $paste->meta->salt),
  166. $response['deletetoken'],
  167. 'outputs valid delete token'
  168. );
  169. }
  170. /**
  171. * @runInSeparateProcess
  172. */
  173. public function testCreateInvalidTimelimit()
  174. {
  175. $this->reset();
  176. $_POST = helper::getPaste();
  177. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  178. $_SERVER['REQUEST_METHOD'] = 'POST';
  179. $_SERVER['REMOTE_ADDR'] = '::1';
  180. trafficlimiter::canPass();
  181. ob_start();
  182. new zerobin;
  183. $content = ob_get_contents();
  184. $response = json_decode($content, true);
  185. $this->assertEquals(1, $response['status'], 'outputs error status');
  186. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste exists after posting data');
  187. }
  188. /**
  189. * @runInSeparateProcess
  190. */
  191. public function testCreateInvalidSize()
  192. {
  193. $this->reset();
  194. $options = parse_ini_file(CONF, true);
  195. $options['main']['sizelimit'] = 10;
  196. $options['traffic']['limit'] = 0;
  197. helper::confBackup();
  198. helper::createIniFile(CONF, $options);
  199. $_POST = helper::getPaste();
  200. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  201. $_SERVER['REQUEST_METHOD'] = 'POST';
  202. $_SERVER['REMOTE_ADDR'] = '::1';
  203. ob_start();
  204. new zerobin;
  205. $content = ob_get_contents();
  206. $response = json_decode($content, true);
  207. $this->assertEquals(1, $response['status'], 'outputs error status');
  208. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste exists after posting data');
  209. }
  210. /**
  211. * @runInSeparateProcess
  212. */
  213. public function testCreateProxyHeader()
  214. {
  215. $this->reset();
  216. $options = parse_ini_file(CONF, true);
  217. $options['traffic']['header'] = 'X_FORWARDED_FOR';
  218. $options['traffic']['limit'] = 100;
  219. helper::confBackup();
  220. helper::createIniFile(CONF, $options);
  221. $_POST = helper::getPaste();
  222. $_SERVER['HTTP_X_FORWARDED_FOR'] = '::1';
  223. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  224. $_SERVER['REQUEST_METHOD'] = 'POST';
  225. $_SERVER['REMOTE_ADDR'] = '::1';
  226. ob_start();
  227. new zerobin;
  228. $content = ob_get_contents();
  229. $response = json_decode($content, true);
  230. $this->assertEquals(1, $response['status'], 'outputs error status');
  231. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste exists after posting data');
  232. }
  233. /**
  234. * @runInSeparateProcess
  235. */
  236. public function testCreateDuplicateId()
  237. {
  238. $this->reset();
  239. $options = parse_ini_file(CONF, true);
  240. $options['traffic']['limit'] = 0;
  241. helper::confBackup();
  242. helper::createIniFile(CONF, $options);
  243. $this->_model->create(helper::getPasteId(), helper::getPaste());
  244. $_POST = helper::getPaste();
  245. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  246. $_SERVER['REQUEST_METHOD'] = 'POST';
  247. $_SERVER['REMOTE_ADDR'] = '::1';
  248. ob_start();
  249. new zerobin;
  250. $content = ob_get_contents();
  251. $response = json_decode($content, true);
  252. $this->assertEquals(1, $response['status'], 'outputs error status');
  253. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists after posting data');
  254. }
  255. /**
  256. * @runInSeparateProcess
  257. */
  258. public function testCreateValidExpire()
  259. {
  260. $this->reset();
  261. $options = parse_ini_file(CONF, true);
  262. $options['traffic']['limit'] = 0;
  263. helper::confBackup();
  264. helper::createIniFile(CONF, $options);
  265. $_POST = helper::getPaste();
  266. $_POST['expire'] = '5min';
  267. $_POST['formatter'] = 'foo';
  268. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  269. $_SERVER['REQUEST_METHOD'] = 'POST';
  270. $_SERVER['REMOTE_ADDR'] = '::1';
  271. $time = time();
  272. ob_start();
  273. new zerobin;
  274. $content = ob_get_contents();
  275. $response = json_decode($content, true);
  276. $this->assertEquals(0, $response['status'], 'outputs status');
  277. $this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
  278. $paste = $this->_model->read($response['id']);
  279. $this->assertEquals(
  280. hash_hmac('sha256', $response['id'], $paste->meta->salt),
  281. $response['deletetoken'],
  282. 'outputs valid delete token'
  283. );
  284. $this->assertGreaterThanOrEqual($time + 300, $paste->meta->expire_date, 'time is set correctly');
  285. }
  286. /**
  287. * @runInSeparateProcess
  288. */
  289. public function testCreateValidExpireWithDiscussion()
  290. {
  291. $this->reset();
  292. $options = parse_ini_file(CONF, true);
  293. $options['traffic']['limit'] = 0;
  294. helper::confBackup();
  295. helper::createIniFile(CONF, $options);
  296. $_POST = helper::getPaste();
  297. $_POST['expire'] = '5min';
  298. $_POST['opendiscussion'] = '1';
  299. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  300. $_SERVER['REQUEST_METHOD'] = 'POST';
  301. $_SERVER['REMOTE_ADDR'] = '::1';
  302. $time = time();
  303. ob_start();
  304. new zerobin;
  305. $content = ob_get_contents();
  306. $response = json_decode($content, true);
  307. $this->assertEquals(0, $response['status'], 'outputs status');
  308. $this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
  309. $paste = $this->_model->read($response['id']);
  310. $this->assertEquals(
  311. hash_hmac('sha256', $response['id'], $paste->meta->salt),
  312. $response['deletetoken'],
  313. 'outputs valid delete token'
  314. );
  315. $this->assertGreaterThanOrEqual($time + 300, $paste->meta->expire_date, 'time is set correctly');
  316. $this->assertEquals(1, $paste->meta->opendiscussion, 'discussion is enabled');
  317. }
  318. /**
  319. * @runInSeparateProcess
  320. */
  321. public function testCreateInvalidExpire()
  322. {
  323. $this->reset();
  324. $options = parse_ini_file(CONF, true);
  325. $options['traffic']['limit'] = 0;
  326. helper::confBackup();
  327. helper::createIniFile(CONF, $options);
  328. $_POST = helper::getPaste();
  329. $_POST['expire'] = 'foo';
  330. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  331. $_SERVER['REQUEST_METHOD'] = 'POST';
  332. $_SERVER['REMOTE_ADDR'] = '::1';
  333. ob_start();
  334. new zerobin;
  335. $content = ob_get_contents();
  336. $response = json_decode($content, true);
  337. $this->assertEquals(0, $response['status'], 'outputs status');
  338. $this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
  339. $paste = $this->_model->read($response['id']);
  340. $this->assertEquals(
  341. hash_hmac('sha256', $response['id'], $paste->meta->salt),
  342. $response['deletetoken'],
  343. 'outputs valid delete token'
  344. );
  345. }
  346. /**
  347. * @runInSeparateProcess
  348. */
  349. public function testCreateInvalidBurn()
  350. {
  351. $this->reset();
  352. $options = parse_ini_file(CONF, true);
  353. $options['traffic']['limit'] = 0;
  354. helper::confBackup();
  355. helper::createIniFile(CONF, $options);
  356. $_POST = helper::getPaste();
  357. $_POST['burnafterreading'] = 'neither 1 nor 0';
  358. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  359. $_SERVER['REQUEST_METHOD'] = 'POST';
  360. $_SERVER['REMOTE_ADDR'] = '::1';
  361. ob_start();
  362. new zerobin;
  363. $content = ob_get_contents();
  364. $response = json_decode($content, true);
  365. $this->assertEquals(1, $response['status'], 'outputs error status');
  366. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste exists after posting data');
  367. }
  368. /**
  369. * @runInSeparateProcess
  370. */
  371. public function testCreateInvalidOpenDiscussion()
  372. {
  373. $this->reset();
  374. $options = parse_ini_file(CONF, true);
  375. $options['traffic']['limit'] = 0;
  376. helper::confBackup();
  377. helper::createIniFile(CONF, $options);
  378. $_POST = helper::getPaste();
  379. $_POST['opendiscussion'] = 'neither 1 nor 0';
  380. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  381. $_SERVER['REQUEST_METHOD'] = 'POST';
  382. $_SERVER['REMOTE_ADDR'] = '::1';
  383. ob_start();
  384. new zerobin;
  385. $content = ob_get_contents();
  386. $response = json_decode($content, true);
  387. $this->assertEquals(1, $response['status'], 'outputs error status');
  388. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste exists after posting data');
  389. }
  390. /**
  391. * @runInSeparateProcess
  392. */
  393. public function testCreateAttachment()
  394. {
  395. $this->reset();
  396. $options = parse_ini_file(CONF, true);
  397. $options['traffic']['limit'] = 0;
  398. $options['main']['fileupload'] = true;
  399. helper::confBackup();
  400. helper::createIniFile(CONF, $options);
  401. $_POST = helper::getPasteWithAttachment();
  402. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  403. $_SERVER['REQUEST_METHOD'] = 'POST';
  404. $_SERVER['REMOTE_ADDR'] = '::1';
  405. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste does not exists before posting data');
  406. ob_start();
  407. new zerobin;
  408. $content = ob_get_contents();
  409. $response = json_decode($content, true);
  410. $this->assertEquals(0, $response['status'], 'outputs status');
  411. $this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
  412. $original = json_decode(json_encode($_POST));
  413. $stored = $this->_model->read($response['id']);
  414. foreach (array('data', 'attachment', 'attachmentname') as $key) {
  415. $this->assertEquals($original->$key, $stored->$key);
  416. }
  417. $this->assertEquals(
  418. hash_hmac('sha256', $response['id'], $stored->meta->salt),
  419. $response['deletetoken'],
  420. 'outputs valid delete token'
  421. );
  422. }
  423. /**
  424. * @runInSeparateProcess
  425. */
  426. public function testCreateValidNick()
  427. {
  428. $this->reset();
  429. $options = parse_ini_file(CONF, true);
  430. $options['traffic']['limit'] = 0;
  431. helper::confBackup();
  432. helper::createIniFile(CONF, $options);
  433. $_POST = helper::getPaste();
  434. $_POST['nickname'] = helper::getComment()['meta']['nickname'];
  435. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  436. $_SERVER['REQUEST_METHOD'] = 'POST';
  437. $_SERVER['REMOTE_ADDR'] = '::1';
  438. ob_start();
  439. new zerobin;
  440. $content = ob_get_contents();
  441. $response = json_decode($content, true);
  442. $this->assertEquals(0, $response['status'], 'outputs status');
  443. $this->assertTrue($this->_model->exists($response['id']), 'paste exists after posting data');
  444. $paste = $this->_model->read($response['id']);
  445. $this->assertEquals(
  446. hash_hmac('sha256', $response['id'], $paste->meta->salt),
  447. $response['deletetoken'],
  448. 'outputs valid delete token'
  449. );
  450. }
  451. /**
  452. * @runInSeparateProcess
  453. */
  454. public function testCreateInvalidNick()
  455. {
  456. $this->reset();
  457. $options = parse_ini_file(CONF, true);
  458. $options['traffic']['limit'] = 0;
  459. helper::confBackup();
  460. helper::createIniFile(CONF, $options);
  461. $_POST = helper::getCommentPost();
  462. $_POST['pasteid'] = helper::getPasteId();
  463. $_POST['parentid'] = helper::getPasteId();
  464. $_POST['nickname'] = 'foo';
  465. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  466. $_SERVER['REQUEST_METHOD'] = 'POST';
  467. $_SERVER['REMOTE_ADDR'] = '::1';
  468. $this->_model->create(helper::getPasteId(), helper::getPaste());
  469. ob_start();
  470. new zerobin;
  471. $content = ob_get_contents();
  472. $response = json_decode($content, true);
  473. $this->assertEquals(1, $response['status'], 'outputs error status');
  474. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists after posting data');
  475. }
  476. /**
  477. * @runInSeparateProcess
  478. */
  479. public function testCreateComment()
  480. {
  481. $this->reset();
  482. $options = parse_ini_file(CONF, true);
  483. $options['traffic']['limit'] = 0;
  484. helper::confBackup();
  485. helper::createIniFile(CONF, $options);
  486. $_POST = helper::getCommentPost();
  487. $_POST['pasteid'] = helper::getPasteId();
  488. $_POST['parentid'] = helper::getPasteId();
  489. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  490. $_SERVER['REQUEST_METHOD'] = 'POST';
  491. $_SERVER['REMOTE_ADDR'] = '::1';
  492. $this->_model->create(helper::getPasteId(), helper::getPaste());
  493. ob_start();
  494. new zerobin;
  495. $content = ob_get_contents();
  496. $response = json_decode($content, true);
  497. $this->assertEquals(0, $response['status'], 'outputs status');
  498. $this->assertTrue($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), $response['id']), 'paste exists after posting data');
  499. }
  500. /**
  501. * @runInSeparateProcess
  502. */
  503. public function testCreateInvalidComment()
  504. {
  505. $this->reset();
  506. $options = parse_ini_file(CONF, true);
  507. $options['traffic']['limit'] = 0;
  508. helper::confBackup();
  509. helper::createIniFile(CONF, $options);
  510. $_POST = helper::getCommentPost();
  511. $_POST['pasteid'] = helper::getPasteId();
  512. $_POST['parentid'] = 'foo';
  513. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  514. $_SERVER['REQUEST_METHOD'] = 'POST';
  515. $_SERVER['REMOTE_ADDR'] = '::1';
  516. $this->_model->create(helper::getPasteId(), helper::getPaste());
  517. ob_start();
  518. new zerobin;
  519. $content = ob_get_contents();
  520. $response = json_decode($content, true);
  521. $this->assertEquals(1, $response['status'], 'outputs error status');
  522. $this->assertFalse($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'paste exists after posting data');
  523. }
  524. /**
  525. * @runInSeparateProcess
  526. */
  527. public function testCreateCommentDiscussionDisabled()
  528. {
  529. $this->reset();
  530. $options = parse_ini_file(CONF, true);
  531. $options['traffic']['limit'] = 0;
  532. helper::confBackup();
  533. helper::createIniFile(CONF, $options);
  534. $_POST = helper::getCommentPost();
  535. $_POST['pasteid'] = helper::getPasteId();
  536. $_POST['parentid'] = helper::getPasteId();
  537. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  538. $_SERVER['REQUEST_METHOD'] = 'POST';
  539. $_SERVER['REMOTE_ADDR'] = '::1';
  540. $paste = helper::getPaste(array('opendiscussion' => false));
  541. $this->_model->create(helper::getPasteId(), $paste);
  542. ob_start();
  543. new zerobin;
  544. $content = ob_get_contents();
  545. $response = json_decode($content, true);
  546. $this->assertEquals(1, $response['status'], 'outputs error status');
  547. $this->assertFalse($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'paste exists after posting data');
  548. }
  549. /**
  550. * @runInSeparateProcess
  551. */
  552. public function testCreateCommentInvalidPaste()
  553. {
  554. $this->reset();
  555. $options = parse_ini_file(CONF, true);
  556. $options['traffic']['limit'] = 0;
  557. helper::confBackup();
  558. helper::createIniFile(CONF, $options);
  559. $_POST = helper::getCommentPost();
  560. $_POST['pasteid'] = helper::getPasteId();
  561. $_POST['parentid'] = helper::getPasteId();
  562. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  563. $_SERVER['REQUEST_METHOD'] = 'POST';
  564. $_SERVER['REMOTE_ADDR'] = '::1';
  565. ob_start();
  566. new zerobin;
  567. $content = ob_get_contents();
  568. $response = json_decode($content, true);
  569. $this->assertEquals(1, $response['status'], 'outputs error status');
  570. $this->assertFalse($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'paste exists after posting data');
  571. }
  572. /**
  573. * @runInSeparateProcess
  574. */
  575. public function testCreateDuplicateComment()
  576. {
  577. $this->reset();
  578. $options = parse_ini_file(CONF, true);
  579. $options['traffic']['limit'] = 0;
  580. helper::confBackup();
  581. helper::createIniFile(CONF, $options);
  582. $this->_model->create(helper::getPasteId(), helper::getPaste());
  583. $this->_model->createComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId(), helper::getComment());
  584. $this->assertTrue($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'comment exists before posting data');
  585. $_POST = helper::getCommentPost();
  586. $_POST['pasteid'] = helper::getPasteId();
  587. $_POST['parentid'] = helper::getPasteId();
  588. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  589. $_SERVER['REQUEST_METHOD'] = 'POST';
  590. $_SERVER['REMOTE_ADDR'] = '::1';
  591. ob_start();
  592. new zerobin;
  593. $content = ob_get_contents();
  594. $response = json_decode($content, true);
  595. $this->assertEquals(1, $response['status'], 'outputs error status');
  596. $this->assertTrue($this->_model->existsComment(helper::getPasteId(), helper::getPasteId(), helper::getCommentId()), 'paste exists after posting data');
  597. }
  598. /**
  599. * @runInSeparateProcess
  600. */
  601. public function testRead()
  602. {
  603. $this->reset();
  604. $this->_model->create(helper::getPasteId(), helper::getPaste());
  605. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  606. ob_start();
  607. new zerobin;
  608. $content = ob_get_contents();
  609. $this->assertContains(
  610. '<div id="cipherdata" class="hidden">' .
  611. htmlspecialchars(helper::getPasteAsJson(), ENT_NOQUOTES) .
  612. '</div>',
  613. $content,
  614. 'outputs data correctly'
  615. );
  616. }
  617. /**
  618. * @runInSeparateProcess
  619. */
  620. public function testReadInvalidId()
  621. {
  622. $this->reset();
  623. $_SERVER['QUERY_STRING'] = 'foo';
  624. ob_start();
  625. new zerobin;
  626. $content = ob_get_contents();
  627. $this->assertRegExp(
  628. '#<div[^>]*id="errormessage"[^>]*>.*Invalid paste ID\.</div>#',
  629. $content,
  630. 'outputs error correctly'
  631. );
  632. }
  633. /**
  634. * @runInSeparateProcess
  635. */
  636. public function testReadNonexisting()
  637. {
  638. $this->reset();
  639. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  640. ob_start();
  641. new zerobin;
  642. $content = ob_get_contents();
  643. $this->assertRegExp(
  644. '#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist[^<]*</div>#',
  645. $content,
  646. 'outputs error correctly'
  647. );
  648. }
  649. /**
  650. * @runInSeparateProcess
  651. */
  652. public function testReadExpired()
  653. {
  654. $this->reset();
  655. $expiredPaste = helper::getPaste(array('expire_date' => 1344803344));
  656. $this->_model->create(helper::getPasteId(), $expiredPaste);
  657. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  658. ob_start();
  659. new zerobin;
  660. $content = ob_get_contents();
  661. $this->assertRegExp(
  662. '#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist[^<]*</div>#',
  663. $content,
  664. 'outputs error correctly'
  665. );
  666. }
  667. /**
  668. * @runInSeparateProcess
  669. */
  670. public function testReadBurn()
  671. {
  672. $this->reset();
  673. $burnPaste = helper::getPaste(array('burnafterreading' => true));
  674. $this->_model->create(helper::getPasteId(), $burnPaste);
  675. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  676. ob_start();
  677. new zerobin;
  678. $content = ob_get_contents();
  679. unset($burnPaste['meta']['salt']);
  680. $this->assertContains(
  681. '<div id="cipherdata" class="hidden">' .
  682. htmlspecialchars(helper::getPasteAsJson($burnPaste['meta']), ENT_NOQUOTES) .
  683. '</div>',
  684. $content,
  685. 'outputs data correctly'
  686. );
  687. }
  688. /**
  689. * @runInSeparateProcess
  690. */
  691. public function testReadJson()
  692. {
  693. $this->reset();
  694. $paste = helper::getPaste();
  695. $this->_model->create(helper::getPasteId(), $paste);
  696. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  697. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  698. ob_start();
  699. new zerobin;
  700. $content = ob_get_contents();
  701. $response = json_decode($content, true);
  702. $this->assertEquals(0, $response['status'], 'outputs success status');
  703. $this->assertEquals(helper::getPasteId(), $response['id'], 'outputs data correctly');
  704. $this->assertStringEndsWith('?' . $response['id'], $response['url'], 'returned URL points to new paste');
  705. $this->assertEquals($paste['data'], $response['data'], 'outputs data correctly');
  706. $this->assertEquals($paste['meta']['formatter'], $response['meta']['formatter'], 'outputs format correctly');
  707. $this->assertEquals($paste['meta']['postdate'], $response['meta']['postdate'], 'outputs postdate correctly');
  708. $this->assertEquals($paste['meta']['opendiscussion'], $response['meta']['opendiscussion'], 'outputs opendiscussion correctly');
  709. $this->assertEquals(0, $response['comment_count'], 'outputs comment_count correctly');
  710. $this->assertEquals(0, $response['comment_offset'], 'outputs comment_offset correctly');
  711. }
  712. /**
  713. * @runInSeparateProcess
  714. */
  715. public function testReadInvalidJson()
  716. {
  717. $this->reset();
  718. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  719. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  720. ob_start();
  721. new zerobin;
  722. $content = ob_get_contents();
  723. $response = json_decode($content, true);
  724. $this->assertEquals(1, $response['status'], 'outputs error status');
  725. }
  726. /**
  727. * @runInSeparateProcess
  728. */
  729. public function testReadOldSyntax()
  730. {
  731. $this->reset();
  732. $oldPaste = helper::getPaste();
  733. $meta = array(
  734. 'syntaxcoloring' => true,
  735. 'postdate' => $oldPaste['meta']['postdate'],
  736. 'opendiscussion' => $oldPaste['meta']['opendiscussion'],
  737. );
  738. $oldPaste['meta'] = $meta;
  739. $this->_model->create(helper::getPasteId(), $oldPaste);
  740. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  741. ob_start();
  742. new zerobin;
  743. $content = ob_get_contents();
  744. $meta['formatter'] = 'syntaxhighlighting';
  745. $this->assertContains(
  746. '<div id="cipherdata" class="hidden">' .
  747. htmlspecialchars(helper::getPasteAsJson($meta), ENT_NOQUOTES) .
  748. '</div>',
  749. $content,
  750. 'outputs data correctly'
  751. );
  752. }
  753. /**
  754. * @runInSeparateProcess
  755. */
  756. public function testReadOldFormat()
  757. {
  758. $this->reset();
  759. $oldPaste = helper::getPaste();
  760. unset($oldPaste['meta']['formatter']);
  761. $this->_model->create(helper::getPasteId(), $oldPaste);
  762. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  763. ob_start();
  764. new zerobin;
  765. $content = ob_get_contents();
  766. $oldPaste['meta']['formatter'] = 'plaintext';
  767. unset($oldPaste['meta']['salt']);
  768. $this->assertContains(
  769. '<div id="cipherdata" class="hidden">' .
  770. htmlspecialchars(helper::getPasteAsJson($oldPaste['meta']), ENT_NOQUOTES) .
  771. '</div>',
  772. $content,
  773. 'outputs data correctly'
  774. );
  775. }
  776. /**
  777. * @runInSeparateProcess
  778. */
  779. public function testDelete()
  780. {
  781. $this->reset();
  782. $this->_model->create(helper::getPasteId(), helper::getPaste());
  783. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
  784. $paste = $this->_model->read(helper::getPasteId());
  785. $_GET['pasteid'] = helper::getPasteId();
  786. $_GET['deletetoken'] = hash_hmac('sha256', helper::getPasteId(), $paste->meta->salt);
  787. ob_start();
  788. new zerobin;
  789. $content = ob_get_contents();
  790. $this->assertRegExp(
  791. '#<div[^>]*id="status"[^>]*>.*Paste was properly deleted[^<]*</div>#s',
  792. $content,
  793. 'outputs deleted status correctly'
  794. );
  795. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
  796. }
  797. /**
  798. * @runInSeparateProcess
  799. */
  800. public function testDeleteInvalidId()
  801. {
  802. $this->reset();
  803. $this->_model->create(helper::getPasteId(), helper::getPaste());
  804. $_GET['pasteid'] = 'foo';
  805. $_GET['deletetoken'] = 'bar';
  806. ob_start();
  807. new zerobin;
  808. $content = ob_get_contents();
  809. $this->assertRegExp(
  810. '#<div[^>]*id="errormessage"[^>]*>.*Invalid paste ID\.</div>#',
  811. $content,
  812. 'outputs delete error correctly'
  813. );
  814. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists after failing to delete data');
  815. }
  816. /**
  817. * @runInSeparateProcess
  818. */
  819. public function testDeleteInexistantId()
  820. {
  821. $this->reset();
  822. $_GET['pasteid'] = helper::getPasteId();
  823. $_GET['deletetoken'] = 'bar';
  824. ob_start();
  825. new zerobin;
  826. $content = ob_get_contents();
  827. $this->assertRegExp(
  828. '#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist[^<]*</div>#',
  829. $content,
  830. 'outputs delete error correctly'
  831. );
  832. }
  833. /**
  834. * @runInSeparateProcess
  835. */
  836. public function testDeleteInvalidToken()
  837. {
  838. $this->reset();
  839. $this->_model->create(helper::getPasteId(), helper::getPaste());
  840. $_GET['pasteid'] = helper::getPasteId();
  841. $_GET['deletetoken'] = 'bar';
  842. ob_start();
  843. new zerobin;
  844. $content = ob_get_contents();
  845. $this->assertRegExp(
  846. '#<div[^>]*id="errormessage"[^>]*>.*Wrong deletion token[^<]*</div>#',
  847. $content,
  848. 'outputs delete error correctly'
  849. );
  850. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists after failing to delete data');
  851. }
  852. /**
  853. * @runInSeparateProcess
  854. */
  855. public function testDeleteBurnAfterReading()
  856. {
  857. $this->reset();
  858. $burnPaste = helper::getPaste(array('burnafterreading' => true));
  859. $this->_model->create(helper::getPasteId(), $burnPaste);
  860. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
  861. $_POST['deletetoken'] = 'burnafterreading';
  862. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  863. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  864. $_SERVER['REQUEST_METHOD'] = 'POST';
  865. ob_start();
  866. new zerobin;
  867. $content = ob_get_contents();
  868. $response = json_decode($content, true);
  869. $this->assertEquals(0, $response['status'], 'outputs status');
  870. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
  871. }
  872. /**
  873. * @runInSeparateProcess
  874. */
  875. public function testDeleteInvalidBurnAfterReading()
  876. {
  877. $this->reset();
  878. $this->_model->create(helper::getPasteId(), helper::getPaste());
  879. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
  880. $_POST['deletetoken'] = 'burnafterreading';
  881. $_SERVER['QUERY_STRING'] = helper::getPasteId();
  882. $_SERVER['HTTP_X_REQUESTED_WITH'] = 'JSONHttpRequest';
  883. $_SERVER['REQUEST_METHOD'] = 'POST';
  884. ob_start();
  885. new zerobin;
  886. $content = ob_get_contents();
  887. $response = json_decode($content, true);
  888. $this->assertEquals(1, $response['status'], 'outputs status');
  889. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
  890. }
  891. /**
  892. * @runInSeparateProcess
  893. */
  894. public function testDeleteExpired()
  895. {
  896. $this->reset();
  897. $expiredPaste = helper::getPaste(array('expire_date' => 1000));
  898. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste does not exist before being created');
  899. $this->_model->create(helper::getPasteId(), $expiredPaste);
  900. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
  901. $_GET['pasteid'] = helper::getPasteId();
  902. $_GET['deletetoken'] = 'does not matter in this context, but has to be set';
  903. ob_start();
  904. new zerobin;
  905. $content = ob_get_contents();
  906. $this->assertRegExp(
  907. '#<div[^>]*id="errormessage"[^>]*>.*Paste does not exist[^<]*</div>#',
  908. $content,
  909. 'outputs error correctly'
  910. );
  911. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
  912. }
  913. /**
  914. * @runInSeparateProcess
  915. */
  916. public function testDeleteMissingPerPasteSalt()
  917. {
  918. $this->reset();
  919. $paste = helper::getPaste();
  920. unset($paste['meta']['salt']);
  921. $this->_model->create(helper::getPasteId(), $paste);
  922. $this->assertTrue($this->_model->exists(helper::getPasteId()), 'paste exists before deleting data');
  923. $_GET['pasteid'] = helper::getPasteId();
  924. $_GET['deletetoken'] = hash_hmac('sha256', helper::getPasteId(), serversalt::get());
  925. ob_start();
  926. new zerobin;
  927. $content = ob_get_contents();
  928. $this->assertRegExp(
  929. '#<div[^>]*id="status"[^>]*>.*Paste was properly deleted[^<]*</div>#s',
  930. $content,
  931. 'outputs deleted status correctly'
  932. );
  933. $this->assertFalse($this->_model->exists(helper::getPasteId()), 'paste successfully deleted');
  934. }
  935. }