/** * Delete the post and eventually the entire thread if it's OP * Also deletes the images when it's the only post with that image * * @param null $password * @param bool $force * @param bool $thread * @throws CommentSendingDatabaseException * @throws CommentDeleteWrongPassException * @return array|bool */ protected function p_delete($password = null, $force = false, $thread = false) { if (!$this->getAuth()->hasAccess('comment.passwordless_deletion') && $force !== true) { if (!password_verify($password, $this->comment->getDelpass())) { throw new CommentDeleteWrongPassException(_i('You did not provide the correct deletion password.')); } } try { $this->dc->getConnection()->beginTransaction(); // check that the post isn't already in deleted $has_deleted = $this->dc->qb()->select('COUNT(*) as found')->from($this->radix->getTable('_deleted'), 'd')->where('doc_id = :doc_id')->setParameter(':doc_id', $this->comment->doc_id)->execute()->fetch(); if (!$has_deleted['found']) { // throw into _deleted table $this->dc->getConnection()->executeUpdate('INSERT INTO ' . $this->radix->getTable('_deleted') . ' ' . $this->dc->qb()->select('*')->from($this->radix->getTable(), 't')->where('doc_id = ' . $this->dc->getConnection()->quote($this->comment->doc_id))->getSQL()); } // delete post $this->dc->qb()->delete($this->radix->getTable())->where('doc_id = :doc_id')->setParameter(':doc_id', $this->comment->doc_id)->execute(); // purge reports $this->dc->qb()->delete($this->dc->p('reports'))->where('board_id = :board_id')->andWhere('doc_id = :doc_id')->setParameter(':board_id', $this->radix->id)->setParameter(':doc_id', $this->comment->doc_id)->execute(); // clear cache $this->radix_coll->clearCache(); // remove image file if (isset($this->media)) { $media_sql = $this->dc->qb()->select('COUNT(*)')->from($this->radix->getTable(), 't')->where('media_id = :media_id')->setParameter(':media_id', $this->media->media_id)->getSQL(); $this->dc->qb()->update($this->radix->getTable('_images'))->set('total', '(' . $media_sql . ')')->where('media_id = :media_id')->setParameter(':media_id', $this->media->media_id)->execute(); $has_image = $this->dc->qb()->select('total')->from($this->radix->getTable('_images'), 'ti')->where('media_id = :media_id')->setParameter(':media_id', $this->media->media_id)->execute()->fetch(); if (!$has_image || !$has_image['total']) { $media = new Media($this->getContext(), $this->bulk); $media->delete(); } } // if this is OP, delete replies too if ($this->comment->op) { // delete thread data $this->dc->qb()->delete($this->radix->getTable('_threads'))->where('thread_num = :thread_num')->setParameter(':thread_num', $this->comment->thread_num)->execute(); // process each comment $comments = $this->dc->qb()->select('doc_id')->from($this->radix->getTable(), 'b')->where('thread_num = :thread_num')->setParameter(':thread_num', $this->comment->thread_num)->execute()->fetchAll(); foreach ($comments as $comment) { $post = Board::forge($this->getContext())->getPost()->setOptions('doc_id', $comment['doc_id'])->setRadix($this->radix)->getComments(); $post = current($post); $post = new Comment($this->getContext(), $post); $post->delete(null, true, true); } } else { // if this is not triggered by a thread deletion, update the thread table if ($thread === false && !$this->radix->archive) { $time_last = ' ( COALESCE(GREATEST( time_op, ( SELECT MAX(timestamp) FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' AND subnum = 0 ) ), time_op) )'; $time_bump = ' ( COALESCE(GREATEST( time_op, ( SELECT MAX(timestamp) FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' AND subnum = 0 AND (email <> \'sage\' OR email IS NULL) ) ), time_op) )'; $time_ghost = ' ( SELECT MAX(timestamp) FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' AND subnum <> 0 )'; $time_ghost_bump = ' ( SELECT MAX(timestamp) FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' AND subnum <> 0 AND (email <> \'sage\' OR email IS NULL) )'; // update thread information $this->dc->qb()->update($this->radix->getTable('_threads'))->set('time_last', $time_last)->set('time_bump', $time_bump)->set('time_ghost', $time_ghost)->set('time_ghost_bump', $time_ghost_bump)->set('time_last_modified', ':time')->set('nreplies', 'nreplies - 1')->set('nimages', $this->media === null ? 'nimages' : 'nimages - 1')->where('thread_num = :thread_num')->setParameter(':time', $this->getRadixTime())->setParameter(':thread_num', $this->comment->thread_num)->execute(); } } $this->dc->getConnection()->commit(); $this->clearCache(); if ($thread === false) { $this->audit->log(Audit::AUDIT_DEL_POST, ['radix' => $this->radix->id, 'doc_id' => $this->comment->doc_id, 'thread_num' => $this->comment->thread_num, 'num' => $this->comment->num, 'subnum' => $this->comment->subnum]); } } catch (\Doctrine\DBAL\DBALException $e) { $this->logger->error('\\Foolz\\FoolFuuka\\Model\\CommentInsert: ' . $e->getMessage()); $this->dc->getConnection()->rollBack(); throw new CommentSendingDatabaseException(_i('Something went wrong when deleting the post in the database. Try again.')); } return $this; }
/** * @return bool */ public function radix_submit() { // adapter if (!$this->getPost()) { return $this->error(_i('You aren\'t sending the required fields for creating a new message.')); } if (!$this->checkCsrfToken()) { return $this->error(_i('The security token wasn\'t found. Try resubmitting.')); } if ($this->getPost('reply_delete')) { foreach ($this->getPost('delete') as $idx => $doc_id) { try { $comments = Board::forge($this->getContext())->getPost()->setOptions('doc_id', $doc_id)->setRadix($this->radix)->getComments(); $comment = current($comments); $comment = new Comment($this->getContext(), $comment); $comment->delete($this->getPost('delpass')); } catch (\Foolz\Foolfuuka\Model\BoardException $e) { return $this->error($e->getMessage(), 404); } catch (\Foolz\Foolfuuka\Model\CommentDeleteWrongPassException $e) { return $this->error($e->getMessage(), 404); } } $this->builder->createLayout('redirect')->getParamManager()->setParam('url', $this->uri->create([$this->radix->shortname, 'thread', $comment->comment->thread_num])); $this->builder->getProps()->addTitle(_i('Redirecting')); return new Response($this->builder->build()); } if ($this->getPost('reply_report')) { foreach ($this->getPost('delete') as $idx => $doc_id) { try { $this->getContext()->getService('foolfuuka.report_collection')->add($this->radix, $doc_id, $this->getPost('KOMENTO'), Inet::ptod($this->getRequest()->getClientIp())); } catch (\Foolz\Foolfuuka\Model\ReportException $e) { return $this->error($e->getMessage(), 404); } } $this->builder->createLayout('redirect')->getParamManager()->setParam('url', $this->uri->create($this->radix->shortname . '/thread/' . $this->getPost('parent'))); $this->builder->getProps()->addTitle(_i('Redirecting')); return new Response($this->builder->build()); } // Determine if the invalid post fields are populated by bots. if (isset($post['name']) && mb_strlen($post['name'], 'utf-8') > 0) { return $this->error(); } if (isset($post['reply']) && mb_strlen($post['reply'], 'utf-8') > 0) { return $this->error(); } if (isset($post['email']) && mb_strlen($post['email'], 'utf-8') > 0) { return $this->error(); } $data = []; $post = $this->getPost(); if (isset($post['parent'])) { $data['thread_num'] = $post['parent']; } if (isset($post['NAMAE'])) { $data['name'] = $post['NAMAE']; $this->response->headers->setCookie(new Cookie($this->getContext(), 'reply_name', $data['name'], 60 * 60 * 24 * 30)); } if (isset($post['MERU'])) { $data['email'] = $post['MERU']; $this->response->headers->setCookie(new Cookie($this->getContext(), 'reply_email', $data['email'], 60 * 60 * 24 * 30)); } if (isset($post['subject'])) { $data['title'] = $post['subject']; } if (isset($post['KOMENTO'])) { $data['comment'] = $post['KOMENTO']; } if (isset($post['delpass'])) { // get the password needed for the reply field if it's not set yet if (!$post['delpass'] || strlen($post['delpass']) < 3) { $post['delpass'] = Util::randomString(7); } $data['delpass'] = $post['delpass']; } if (isset($post['reply_spoiler'])) { $data['spoiler'] = true; } if (isset($post['reply_postas'])) { $data['capcode'] = $post['reply_postas']; } if (isset($post['recaptcha_challenge_field']) && isset($post['recaptcha_response_field'])) { $data['recaptcha_challenge'] = $post['recaptcha_challenge_field']; $data['recaptcha_response'] = $post['recaptcha_response_field']; } $media = null; if ($this->getRequest()->files->count()) { try { $media = $this->media_factory->forgeFromUpload($this->getRequest(), $this->radix); $media->spoiler = isset($data['spoiler']) && $data['spoiler']; } catch (\Foolz\Foolfuuka\Model\MediaUploadNoFileException $e) { $media = null; } catch (\Foolz\Foolfuuka\Model\MediaUploadException $e) { return $this->error($e->getMessage()); } } return $this->submit($data, $media); }
public function post_mod_actions() { if (!$this->checkCsrfToken()) { return $this->response->setData(['error' => _i('The security token was not found. Please try again.')]); } if (!$this->getAuth()->hasAccess('comment.mod_capcode')) { return $this->response->setData(['error' => _i('Access Denied.')])->setStatusCode(403); } if (!$this->check_board()) { return $this->response->setData(['error' => _i('No board was selected.')])->setStatusCode(422); } if ($this->getPost('action') === 'delete_report') { try { $this->report_coll->delete($this->getPost('id')); } catch (\Foolz\Foolfuuka\Model\ReportException $e) { return $this->response->setData(['error' => $e->getMessage()])->setStatusCode(404); } return $this->response->setData(['success' => _i('The report was deleted.')]); } if ($this->getPost('action') === 'delete_post') { try { $comments = Board::forge($this->getContext())->getPost()->setOptions('doc_id', $this->getPost('id'))->setRadix($this->radix)->getComments(); $comment = current($comments); $comment = new Comment($this->getContext(), $comment); $comment->delete(); } catch (\Foolz\Foolfuuka\Model\BoardException $e) { return $this->response->setData(['error' => $e->getMessage()])->setStatusCode(404); } return $this->response->setData(['success' => _i('This post was deleted.')]); } if ($this->getPost('action') === 'delete_image') { try { $media = $this->media_factory->getByMediaId($this->radix, $this->getPost('id')); $media = new Media($this->getContext(), CommentBulk::forge($this->radix, null, $media)); $media->delete(true, true, true); } catch (\Foolz\Foolfuuka\Model\MediaNotFoundException $e) { return $this->response->setData(['error' => $e->getMessage()])->setStatusCode(404); } return $this->response->setData(['success' => _i('This image was deleted.')]); } if ($this->getPost('action') === 'ban_image_local' || $this->getPost('action') === 'ban_image_global') { $global = false; if ($this->getPost('action') === 'ban_image_global') { $global = true; } try { $media = $this->media_factory->getByMediaId($this->radix, $this->getPost('id')); $media = new Media($this->getContext(), CommentBulk::forge($this->radix, null, $media)); $media->ban($global); } catch (\Foolz\Foolfuuka\Model\MediaNotFoundException $e) { return $this->response->setData(['error' => $e->getMessage()])->setStatusCode(404); } return $this->response->setData(['success' => _i('This image was banned.')]); } if ($this->getPost('action') === 'ban_user') { try { $this->ban_factory->add(Inet::ptod($this->getPost('ip')), $this->getPost('reason'), $this->getPost('length'), $this->getPost('board_ban') === 'global' ? array() : array($this->radix->id)); } catch (\Foolz\Foolfuuka\Model\BanException $e) { return $this->response->setData(['error' => $e->getMessage()])->setStatusCode(404); } return $this->response->setData(['success' => _i('This user was banned.')]); } }