public function action_login() { // redirect user to admin panel if ($this->getAuth()->hasAccess('maccess.user')) { return $this->redirectToAdmin(); } // the login button has been submitted - authenticate username and password if ($this->getPost() && !$this->security->checkCsrfToken($this->getRequest())) { $this->notices->set('error', _i('The security token was not found. Please try again.')); } elseif ($this->getPost()) { // load authentication instance // verify credentials try { $this->getAuth()->authenticateWithUsernameAndPassword($this->getPost('username', ''), $this->getPost('password', '')); $rememberme_token = $this->getAuth()->createAutologinHash(Inet::ptod($this->getRequest()->getClientIp()), $this->getRequest()->headers->get('User-Agent')); $response = new RedirectResponse($this->uri->create('admin')); //$this->getRequest()->getSession()->set('rememberme', $rememberme_token); if ($this->getPost('remember')) { $response->headers->setCookie(new Cookie($this->getContext(), 'rememberme', $rememberme_token, 365 * 24 * 60 * 60)); } return $response; } catch (WrongUsernameOrPasswordException $e) { $this->notices->set('error', _i('You have entered an invalid username and/or password. Please try again.')); } } // generate login form $this->param_manager->setParam('method_title', _i('Login')); $this->builder->createLayout('account'); $this->builder->createPartial('body', 'account/login'); return new Response($this->builder->build()); }
public function blockCountryComment(Result $result) { /** @var Comment $obj */ $obj = $result->getObject(); // globally allowed and disallowed $allow = $this->preferences->get('foolfuuka.plugins.geoip_region_lock.allow_comment'); $disallow = $this->preferences->get('foolfuuka.plugins.geoip_region_lock.disallow_comment'); $board_allow = trim($obj->radix->getValue('plugin_geo_ip_region_lock_allow_comment'), " ,"); $board_disallow = trim($obj->radix->getValue('plugin_geo_ip_region_lock_disallow_comment'), " ,"); // allow board settings to override global if ($board_allow || $board_disallow) { $allow = $board_allow; $disallow = $board_disallow; } if ($allow || $disallow) { $ip = Inet::dtop($obj->comment->poster_ip); $reader = new Reader($this->preferences->get('foolframe.maxmind.geoip2_db_path')); $country = null; try { $record = $reader->country($ip); $country = strtolower($record->country->isoCode); } catch (AddressNotFoundException $e) { $country = 'xx'; } if ($allow) { $allow = array_filter(explode(',', $allow)); foreach ($allow as $al) { if (strtolower(trim($al)) === $country) { return; } } throw new CommentSendingException(_i('Your nation has been blocked from posting.') . '<br/><br/>This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com/'); } if ($disallow) { $disallow = array_filter(explode(',', $disallow)); foreach ($disallow as $disal) { if (strtolower(trim($disal)) == $country) { throw new CommentSendingException(_i('Your nation has been blocked from posting.') . '<br/><br/>This product includes GeoLite2 data created by MaxMind, available from http://www.maxmind.com/'); } } } } }
public function toString() { $controller_method = $this->getBuilderParamManager()->getParam('controller_method', 'thread'); $p = $this->getParamManager()->getParam('p'); $p_media = $this->getParamManager()->getParam('p_media'); if ($this->getParamManager()->getParam('modifiers', false)) { $modifiers = $this->getParamManager()->getParam('modifiers'); } $num = $p->num . ($p->subnum ? '_' . $p->subnum : ''); ?> <div class="post stub stub_doc_id_<?php echo $p->doc_id; ?> "> <button class="btn-toggle-post" data-function="showPost" data-board="<?php echo $p->radix->shortname; ?> " data-doc-id="<?php echo $p->doc_id; ?> " data-thread-num="<?php echo $p->thread_num; ?> "><i class="icon-plus"></i></button> <?php if ($p->email && $p->email !== 'noko') { ?> <a href="mailto:<?php echo rawurlencode($p->email); ?> "><?php } ?> <span class="post_author"><?php echo $p->getNameProcessed(); ?> </span><?php echo $p->getNameProcessed() && $p->getTripProcessed() ? ' ' : ''; ?> <span class="post_tripcode"><?php echo $p->getTripProcessed(); ?> </span><?php if ($p->email && $p->email !== 'noko') { ?> </a><?php } ?> </div> <article class="post doc_id_<?php echo $p->doc_id; if ($p->subnum > 0) { ?> post_ghost<?php } if ($p->thread_num === $p->num) { ?> post_is_op<?php } if (!is_null($p_media)) { ?> has_image<?php } ?> " id="<?php echo $num; ?> "> <div class="stub pull-left"> <button class="btn-toggle-post" data-function="hidePost" data-board="<?php echo $p->radix->shortname; ?> " data-doc-id="<?php echo $p->doc_id; ?> "><i class="icon-minus"></i></button> </div> <div class="<?php if ($p->capcode === 'A') { ?> adminpost<?php } ?> post_wrapper"> <?php if ($p_media !== null) { ?> <div class="post_file" style="overflow:visible;"> <span class="post_file_controls"> <?php if ($p_media->getMediaStatus($this->getRequest()) !== 'banned' || $this->getAuth()->hasAccess('media.see_hidden')) { ?> <?php if (!$p->radix->hide_thumbnails || $this->getAuth()->hasAccess('media.see_hidden')) { ?> <?php $dropdowntest = 0; if ($dropdowntest === 1) { ?> <a href="<?php echo $this->getUri()->create((isset($modifiers['post_show_board_name']) && $modifiers['post_show_board_name'] ? '_' : $p->radix->shortname) . '/search/image/' . $p_media->getSafeMediaHash()); ?> " class="btnr parent"><?php echo _i('View Same'); ?> </a> <a href="http://google.com/searchbyimage?image_url=<?php echo $p_media->getThumbLink($this->getRequest()); ?> " target="_blank" class="btnr parent">Google</a> <a href="http://iqdb.org/?url=<?php echo $p_media->getThumbLink($this->getRequest()); ?> " target="_blank" class="btnr parent">iqdb</a> <a href="http://saucenao.com/search.php?url=<?php echo $p_media->getThumbLink($this->getRequest()); ?> " target="_blank" class="btnr parent">SauceNAO</a> <?php } else { ?> <div class="saucenav"> <ul> <li class="btnr parent"><a href="#" onclick="return false;">Image Search</a> <ul class="saucenav-reply"> <li><a href="<?php echo $this->getUri()->create((isset($modifiers['post_show_board_name']) && $modifiers['post_show_board_name'] ? '_' : $p->radix->shortname) . '/search/image/' . $p_media->getSafeMediaHash()); ?> "><?php echo _i('View Same'); ?> </a></li> <li><a href="http://google.com/searchbyimage?image_url=<?php echo $p_media->getThumbLink($this->getRequest()); ?> " target="_blank">Google</a></li> <li><a href="http://iqdb.org/?url=<?php echo $p_media->getThumbLink($this->getRequest()); ?> " target="_blank">Iqdb</a></li> <li><a href="http://saucenao.com/search.php?url=<?php echo $p_media->getThumbLink($this->getRequest()); ?> " target="_blank">SauceNAO</a></li> </ul> </li> </ul> </div> <?php } ?> <?php if (!$p->radix->archive || $p->radix->getValue('archive_full_images')) { ?> <a href="<?php echo $p_media->getMediaDownloadLink($this->getRequest()); ?> " download="<?php echo $p_media->getMediaFilenameProcessed(); ?> " style="border-color: #9E9E9E!important;" class="btnr parent"><i class="icon-download-alt"></i></a> <?php } ?> <?php } ?> <?php } ?> </span> <?php if ($p_media->getMediaStatus($this->getRequest()) !== 'banned' || $this->getAuth()->hasAccess('media.see_banned')) { ?> <?php if (mb_strlen($p_media->getMediaFilenameProcessed()) > 35) { ?> <a href="<?php echo $p_media->getMediaLink($this->getRequest()) ? $p_media->getMediaLink($this->getRequest()) : $p_media->getRemoteMediaLink($this->getRequest()); ?> " class="post_file_filename" rel="tooltip" title="<?php echo htmlspecialchars($p_media->media_filename); ?> " target="_blank"><?php echo mb_substr($p_media->getMediaFilenameProcessed(), 0, 30, 'utf-8') . ' (...)' . mb_substr($p_media->getMediaFilenameProcessed(), mb_strrpos($p_media->getMediaFilenameProcessed(), '.', 'utf-8'), null, 'utf-8'); ?> </a>, <?php } else { ?> <a href="<?php echo $p_media->getMediaLink($this->getRequest()) ? $p_media->getMediaLink($this->getRequest()) : $p_media->getRemoteMediaLink($this->getRequest()); ?> " class="post_file_filename" rel="tooltip" title="<?php echo htmlspecialchars($p_media->media_filename); ?> " target="_blank"><?php echo $p_media->getMediaFilenameProcessed(); ?> </a>, <?php } ?> <span class="post_file_metadata"> <?php echo \Rych\ByteSize\ByteSize::formatBinary($p_media->media_size, 0) . ', ' . $p_media->media_w . 'x' . $p_media->media_h; ?> </span> <?php } ?> </div> <div class="thread_image_box"> <?php if ($p_media->getMediaStatus($this->getRequest()) === 'banned') { ?> <img src="<?php echo $this->getAssetManager()->getAssetLink('images/banned-image.png'); ?> " width="150" height="150" /> <?php } elseif ($p_media->getMediaStatus($this->getRequest()) !== 'normal') { ?> <a href="<?php echo $p_media->getMediaLink($this->getRequest()) ? $p_media->getMediaLink($this->getRequest()) : $p_media->getRemoteMediaLink($this->getRequest()); ?> " target="_blank" rel="noreferrer" class="thread_image_link"> <img src="<?php echo $this->getAssetManager()->getAssetLink('images/missing-image.jpg'); ?> " width="150" height="150" /> </a> <?php } else { ?> <a href="<?php echo $p_media->getMediaLink($this->getRequest()) ? $p_media->getMediaLink($this->getRequest()) : $p_media->getRemoteMediaLink($this->getRequest()); ?> " target="_blank" rel="noreferrer" class="thread_image_link"> <?php if (!$this->getAuth()->hasAccess('maccess.mod') && !$p->radix->getValue('transparent_spoiler') && $p_media->spoiler) { ?> <div class="spoiler_box"><span class="spoiler_box_text"><?php echo _i('Spoiler'); ?> <span class="spoiler_box_text_help"><?php echo _i('Click to view'); ?> </span></div> <?php } elseif (isset($modifiers['lazyload']) && $modifiers['lazyload'] == true) { ?> <img src="<?php echo $this->getUri()->base() . $this->getAssetManager()->getAssetLink('images/transparent_pixel.png'); ?> " data-original="<?php echo $p_media->getThumbLink($this->getRequest()); ?> " width="<?php echo $p_media->preview_w; ?> " height="<?php echo $p_media->preview_h; ?> " class="lazyload post_image<?php echo $p_media->spoiler ? ' is_spoiler_image' : ''; ?> " data-md5="<?php echo $p_media->media_hash; ?> " /> <noscript> <a href="<?php echo $p_media->getMediaLink($this->getRequest()) ? $p_media->getMediaLink($this->getRequest()) : $p_media->getRemoteMediaLink($this->getRequest()); ?> " target="_blank" rel="noreferrer" class="thread_image_link"> <img src="<?php echo $p_media->getThumbLink($this->getRequest()); ?> " style="margin-left: -<?php echo $p_media->preview_w; ?> px" width="<?php echo $p_media->preview_w; ?> " height="<?php echo $p_media->preview_h; ?> " class="lazyload post_image<?php echo $p_media->spoiler ? ' is_spoiler_image' : ''; ?> " data-md5="<?php echo $p_media->media_hash; ?> " /> </a> </noscript> <?php } else { ?> <img src="<?php echo $p_media->getThumbLink($this->getRequest()); ?> " width="<?php echo $p_media->preview_w; ?> " height="<?php echo $p_media->preview_h; ?> " class="lazyload post_image<?php echo $p_media->spoiler ? ' is_spoiler_image' : ''; ?> " imgstate="normal" smsize="<?php echo $p->media->preview_w . "x" . $p->media->preview_h; ?> " data-md5="<?php echo $p_media->media_hash; ?> " /> <?php } ?> </a> <?php } ?> </div> <?php } ?> <header> <div class="post_data"> <?php if (isset($modifiers['post_show_board_name']) && $modifiers['post_show_board_name']) { ?> <span class="post_show_board">/<?php echo $p->radix->shortname; ?> /</span> <?php } ?> <?php if ($p->getTitleProcessed() !== '') { ?> <h2 class="post_title"><?php echo $p->getTitleProcessed(); ?> </h2><?php } ?> <span class="post_poster_data"> <?php if ($p->email && $p->email !== 'noko') { ?> <a href="mailto:<?php echo rawurlencode($p->email); ?> "><?php } ?> <span class="post_author"><?php echo $p->getNameProcessed(); ?> </span><?php echo $p->getNameProcessed() && $p->getTripProcessed() ? ' ' : ''; ?> <span class="post_tripcode"><?php echo $p->getTripProcessed(); ?> </span><?php if ($p->email && $p->email !== 'noko') { ?> </a><?php } ?> <?php if ($p->getPosterHashProcessed()) { ?> <span class="poster_hash">ID:<?php echo $p->getPosterHashProcessed(); ?> </span><?php } ?> <?php if ($p->capcode !== 'N') { ?> <?php if ($p->capcode === 'M') { ?> <span class="post_level post_level_moderator">## <?php echo _i('Mod'); ?> </span><?php } ?> <?php if ($p->capcode === 'A') { ?> <span class="post_level post_level_administrator">## <?php echo _i('Admin'); ?> </span><?php } ?> <?php if ($p->capcode === 'D') { ?> <span class="post_level post_level_developer">## <?php echo _i('Developer'); ?> </span><?php } ?> <?php } ?> </span> <span class="time_wrap"> <time datetime="<?php echo gmdate(DATE_W3C, $p->timestamp); ?> " <?php if ($p->radix->archive) { ?> title="<?php echo _i('4chan Time') . ': ' . $p->getFourchanDate(); ?> "<?php } ?> ><?php echo gmdate('D d M Y H:i:s', $p->timestamp); ?> </time> </span> <a href="<?php echo $this->getUri()->create([$p->radix->shortname, $controller_method, $p->thread_num]) . '#' . $num; ?> " data-post="<?php echo $num; ?> " data-function="highlight">No.</a><a href="<?php echo $this->getUri()->create([$p->radix->shortname, $controller_method, $p->thread_num]) . '#q' . $num; ?> " data-post="<?php echo str_replace('_', ',', $num); ?> " data-function="quote"><?php if ($p->capcode === 'L') { echo str_replace('_', ',', 1999999999); } else { echo str_replace('_', ',', $num); } ?> </a> <span class="post_type"> <?php if ($p->poster_country !== null) { ?> <span title="<?php echo e($p->poster_country_name); ?> " class="flag flag-<?php echo strtolower($p->poster_country); ?> "></span><?php } ?> <?php if ($p->subnum) { ?> <i class="icon-comment-alt" title="<?php echo htmlspecialchars(_i('This post was submitted as a "ghost" reply.')); ?> "></i><?php } ?> <?php if (isset($p_media) && $p_media->spoiler) { ?> <i class="icon-eye-close" title="<?php echo htmlspecialchars(_i('The image in this post has been marked spoiler.')); ?> "></i><?php } ?> <?php if ($p->deleted && !$p->timestamp_expired) { ?> <i class="icon-trash" title="<?php echo htmlspecialchars(_i('This post was prematurely deleted.')); ?> "></i><?php } ?> <?php if ($p->deleted && $p->timestamp_expired) { ?> <i class="icon-trash" title="<?php echo htmlspecialchars(_i('This post was deleted on %s.', gmdate('M d, Y \\a\\t H:i:s e', $p->timestamp_expired))); ?> "></i><?php } ?> <?php if ($p->sticky) { ?> <i class="icon-pushpin" title="<?php echo _i('This thread has been stickied.'); ?> "></i><?php } ?> <?php if ($p->locked) { ?> <i class="icon-lock" title="<?php echo _i('This thread has been locked.'); ?> "></i><?php } ?> </span> <span class="post_controls"> <?php if (isset($modifiers['post_show_view_button'])) { ?> <a href="<?php echo $this->getUri()->create($p->radix->shortname . '/thread/' . $p->thread_num) . '#' . $num; ?> " class="btnr parent"><?php echo _i('View'); ?> </a><?php } ?> <a href="#" class="btnr parent" data-post="<?php echo $p->doc_id; ?> " data-post-id="<?php echo $num; ?> " data-board="<?php echo htmlspecialchars($p->radix->shortname); ?> " data-controls-modal="post_tools_modal" data-backdrop="true" data-keyboard="true" data-function="report"><?php echo _i('Report'); ?> </a><?php if ($p->subnum > 0 || $this->getAuth()->hasAccess('comment.passwordless_deletion') || !$p->radix->archive) { ?> <a href="#" class="btnr parent" data-post="<?php echo $p->doc_id; ?> " data-post-id="<?php echo $num; ?> " data-board="<?php echo htmlspecialchars($p->radix->shortname); ?> " data-controls-modal="post_tools_modal" data-backdrop="true" data-keyboard="true" data-function="delete"><?php echo _i('Delete'); ?> </a><?php } ?> </span> </div> </header> <div class="backlink_list"<?php echo $p->getBacklinks() ? ' style="display:block"' : ''; ?> > <?php echo _i('Quoted By:'); ?> <span class="post_backlink" data-post="<?php echo $p->num; ?> "><?php echo $p->getBacklinks() ? implode(' ', $p->getBacklinks()) : ''; ?> </span> </div> <div class="text<?php if (preg_match('/[\\x{4E00}-\\x{9FBF}\\x{3040}-\\x{309F}\\x{30A0}-\\x{30FF}]/u', $p->getCommentProcessed())) { echo ' shift-jis'; } ?> "> <?php echo $p->getCommentProcessed(); ?> </div> <?php if ($this->getAuth()->hasAccess('maccess.mod')) { ?> <div class="btn-group" style="clear:both; padding:5px 0 0 0;"> <button class="btn btn-mini" data-function="activateModeration"><?php echo _i('Mod'); if ($p->poster_ip) { echo ' ' . Inet::dtop($p->poster_ip); } ?> </button> </div> <div class="btn-group post_mod_controls" style="clear:both; padding:5px 0 0 5px;"> <?php if ($p->op) { ?> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $p->radix->shortname; ?> " data-id="<?php echo $p->doc_id; ?> " data-action="toggle_sticky"><?php echo _i('Toggle Sticky'); ?> </button> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $p->radix->shortname; ?> " data-id="<?php echo $p->doc_id; ?> " data-action="toggle_locked"><?php echo _i('Toggle Locked'); ?> </button> <?php } ?> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $p->radix->shortname; ?> " data-board-url="<?php echo $this->getUri()->create([$p->radix->shortname]); ?> " data-id="<?php echo $p->doc_id; ?> " data-action="delete_post"><?php echo _i('Delete Post'); ?> </button> <?php if (!is_null($p_media)) { ?> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $p->radix->shortname; ?> " data-id="<?php echo $p_media->media_id; ?> " data-doc-id="<?php echo $p->doc_id; ?> " data-action="delete_image"><?php echo _i('Delete Image'); ?> </button> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $p->radix->shortname; ?> " data-id="<?php echo $p_media->media_id; ?> " data-doc-id="<?php echo $p->doc_id; ?> " data-action="ban_image_local"><?php echo _i('Ban Image'); ?> </button> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $p->radix->shortname; ?> " data-id="<?php echo $p_media->media_id; ?> " data-doc-id="<?php echo $p->doc_id; ?> " data-action="ban_image_global"><?php echo _i('Ban Image Globally'); ?> </button> <?php } ?> <?php if ($p->poster_ip) { ?> <button class="btn btn-mini" data-function="ban" data-controls-modal="post_tools_modal" data-backdrop="true" data-keyboard="true" data-board="<?php echo $p->radix->shortname; ?> " data-ip="<?php echo Inet::dtop($p->poster_ip); ?> " data-action="ban_user"><?php echo _i('Ban IP:') . ' ' . Inet::dtop($p->poster_ip); ?> </button> <button class="btn btn-mini" data-function="searchUser" data-board="<?php echo $p->radix->shortname; ?> " data-id="<?php echo $p->doc_id; ?> " data-poster-ip="<?php echo Inet::dtop($p->poster_ip); ?> "><?php echo _i('Search IP'); ?> </button> <?php if ($this->getPreferences()->get('foolfuuka.sphinx.global')) { ?> <button class="btn btn-mini" data-function="searchUserGlobal" data-board="<?php echo $p->radix->shortname; ?> " data-id="<?php echo $p->doc_id; ?> " data-poster-ip="<?php echo Inet::dtop($p->poster_ip); ?> "><?php echo _i('Search IP Globally'); ?> </button> <?php } ?> <?php } ?> </div> <?php if ($p->getReports()) { ?> <?php foreach ($p->getReports() as $report) { ?> <div class="report_reason"><?php echo '<strong>' . _i('Reported Reason:') . '</strong> ' . $report->getReasonProcessed(); ?> <br/> <div class="ip_reporter"> <strong><?php echo _i('Info:'); ?> </strong> <?php echo Inet::dtop($report->ip_reporter); ?> , <?php echo _i('Type:'); ?> <?php echo $report->media_id !== null ? _i('media') : _i('post'); ?> , <?php echo _i('Time:'); ?> <?php echo gmdate('D M d H:i:s Y', $report->created); ?> <button class="btn btn-mini" data-function="mod" data-id="<?php echo $report->id; ?> " data-board="<?php echo htmlspecialchars($p->radix->shortname); ?> " data-action="delete_report"><?php echo _i('Delete Report'); ?> </button> </div> </div> <?php } ?> <?php } ?> <?php } ?> </div> </article> <?php }
/** * @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); }
/** * Send the comment and attached media to database * * @param Media $media * @param array $data extra data * @throws CommentSendingDatabaseException * @throws CommentSendingBannedException * @throws CommentSendingThreadWithoutMediaException * @throws CommentSendingSpamException * @throws CommentSendingImageInGhostException * @throws CommentSendingNoDelPassException * @throws CommentSendingThreadClosedException * @throws CommentSendingRequestCaptchaException * @throws CommentSendingTimeLimitException * @throws CommentSendingException * @throws CommentSendingTooManyCharactersException * @throws \RuntimeException * @throws CommentSendingDisplaysEmptyException * @throws CommentSendingTooManyLinesException * @throws CommentSendingSameCommentException * @throws CommentSendingWrongCaptchaException * @throws CommentSendingUnallowedCapcodeException * @return array error key with explanation to show to user, or success and post row */ public function p_insert(Media $media = null, $data = []) { if (isset($data['recaptcha_challenge'])) { $this->recaptcha_challenge = $data['recaptcha_challenge']; $this->recaptcha_response = $data['recaptcha_response']; } $this->ghost = false; $this->ghost_exist = false; $this->allow_media = true; // some users don't need to be limited, in here go all the ban and posting limitators if (!$this->getAuth()->hasAccess('comment.limitless_comment')) { // check if the user is banned if ($ban = $this->ban_factory->isBanned($this->comment->poster_ip, $this->radix)) { if ($ban->board_id == 0) { $banned_string = _i('It looks like you were banned on all boards.'); } else { $banned_string = _i('It looks like you were banned on /' . $this->radix->shortname . '/.'); } if ($ban->length) { $banned_string .= ' ' . _i('This ban will last until:') . ' ' . date(DATE_COOKIE, $ban->start + $ban->length) . '.'; } else { $banned_string .= ' ' . _i('This ban will last forever.'); } if ($ban->reason) { $banned_string .= ' ' . _i('The reason for this ban is:') . ' «' . $ban->reason . '».'; } if ($ban->appeal_status == Ban::APPEAL_NONE) { $banned_string .= ' ' . _i('If you\'d like to appeal to your ban, go to the %s page.', '<a href="' . $this->uri->create($this->radix->shortname . '/appeal') . '">' . _i('Appeal') . '</a>'); } elseif ($ban->appeal_status == Ban::APPEAL_PENDING) { $banned_string .= ' ' . _i('Your appeal is pending.'); } throw new CommentSendingBannedException($banned_string); } } // check if it's a thread and its status if ($this->comment->thread_num > 0) { try { $thread = Board::forge($this->getContext())->getThread($this->comment->thread_num)->setRadix($this->radix); $status = $thread->getThreadStatus(); } catch (BoardException $e) { throw new CommentSendingException($e->getMessage()); } if ($status['closed']) { throw new CommentSendingThreadClosedException(_i('The thread is closed.')); } $this->ghost = $status['dead']; $this->ghost_exist = $status['ghost_exist']; $this->allow_media = !$status['disable_image_upload']; } foreach (['name', 'email', 'title', 'comment', 'capcode'] as $key) { $this->comment->{$key} = trim((string) $this->comment->{$key}); } $this->comment->setDelpass(trim((string) $this->comment->getDelPass())); // some users don't need to be limited, in here go all the ban and posting limitators if (!$this->getAuth()->hasAccess('comment.limitless_comment')) { if ($this->comment->thread_num < 1) { // one can create a new thread only once every 5 minutes $check_op = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'r')->where('r.poster_ip = :poster_ip')->andWhere('r.timestamp > :timestamp')->andWhere('r.op = :op')->setParameters([':poster_ip' => $this->comment->poster_ip, ':timestamp' => time() - $this->radix->getValue('cooldown_new_thread'), ':op' => true])->setMaxResults(1)->execute()->fetch(); if ($check_op) { throw new CommentSendingTimeLimitException(_i('You must wait up to %d minutes to make another new thread.', ceil($this->radix->getValue('cooldown_new_thread') / 60))); } } // check the latest posts by the user to see if he's posting the same message or if he's posting too fast $check = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'r')->where('poster_ip = :poster_ip')->orderBy('timestamp', 'DESC')->setMaxResults(1)->setParameter(':poster_ip', $this->comment->poster_ip)->execute()->fetch(); if ($check) { if ($this->comment->comment !== null && $check['comment'] === $this->comment->comment) { throw new CommentSendingSameCommentException(_i('You\'re sending the same comment as the last time')); } $check_time = $this->getRadixTime(); if ($check_time - $check['timestamp'] < $this->radix->getValue('cooldown_new_comment') && $check_time - $check['timestamp'] > 0) { throw new CommentSendingTimeLimitException(_i('You must wait up to %d seconds to post again.', $this->radix->getValue('cooldown_new_comment'))); } } // we want to know if the comment will display empty, and in case we won't let it pass $comment_parsed = $this->processComment(); if ($this->comment->comment !== '' && $comment_parsed === '') { throw new CommentSendingDisplaysEmptyException(_i('This comment would display empty.')); } // clean up to reset eventual auto-built entries $this->comment->clean(); if ($this->recaptcha_challenge && $this->recaptcha_response && $this->preferences->get('foolframe.auth.recaptcha_public', false)) { $recaptcha = ReCaptcha::create($this->preferences->get('foolframe.auth.recaptcha_public'), $this->preferences->get('foolframe.auth.recaptcha_private')); $recaptcha_result = $recaptcha->checkAnswer(Inet::dtop($this->comment->poster_ip), $this->recaptcha_challenge, $this->recaptcha_response); if (!$recaptcha_result->isValid()) { throw new CommentSendingWrongCaptchaException(_i('Incorrect CAPTCHA solution.')); } } elseif ($this->preferences->get('foolframe.auth.recaptcha_public')) { // if there wasn't a recaptcha input, let's go with heavier checks if (substr_count($this->comment->comment, 'http') >= $this->radix->getValue('captcha_comment_link_limit')) { throw new CommentSendingRequestCaptchaException(); } // bots usually fill all the fields if ($this->comment->comment && $this->comment->title && $this->comment->email) { throw new CommentSendingRequestCaptchaException(); } // bots usually try various BBC, this checks if there's unparsed BBC after parsing it if ($comment_parsed !== '' && substr_count($comment_parsed, '[') + substr_count($comment_parsed, ']') > 4) { throw new CommentSendingRequestCaptchaException(); } } // load the spam list and check comment, name, title and email $spam = array_filter(preg_split('/\\r\\n|\\r|\\n/', file_get_contents(ASSETSPATH . 'packages/anti-spam/databases/urls.dat'))); foreach ($spam as $s) { if (strpos($this->comment->comment, $s) !== false || strpos($this->comment->name, $s) !== false || strpos($this->comment->title, $s) !== false || strpos($this->comment->email, $s) !== false) { throw new CommentSendingSpamException(_i('Your post has undesidered content.')); } } // check entire length of comment if (mb_strlen($this->comment->comment, 'utf-8') > $this->radix->getValue('max_comment_characters_allowed')) { throw new CommentSendingTooManyCharactersException(_i('Your comment has too many characters')); } // check total numbers of lines in comment if (count(explode("\n", $this->comment->comment)) > $this->radix->getValue('max_comment_lines_allowed')) { throw new CommentSendingTooManyLinesException(_i('Your comment has too many lines.')); } } \Foolz\Plugin\Hook::forge('Foolz\\Foolslide\\Model\\CommentInsert::insert.call.after.input_checks')->setObject($this)->execute(); // process comment name+trip if ($this->comment->name === '') { $this->comment->name = $this->radix->getValue('anonymous_default_name'); $this->comment->trip = null; } else { $this->processName(); if ($this->comment->trip === '') { $this->comment->trip = null; } } foreach (['email', 'title', 'comment'] as $key) { if ($this->comment->{$key} === '') { $this->comment->{$key} = null; } } // process comment password if ($this->comment->getDelpass() === '') { throw new CommentSendingNoDelPassException(_i('You must submit a deletion password.')); } $pass = password_hash($this->comment->getDelpass(), PASSWORD_BCRYPT, ['cost' => 10]); if ($this->comment->getDelpass() === false) { throw new \RuntimeException('Password hashing failed'); } $this->comment->setDelpass($pass); if ($this->comment->capcode != '') { $allowed_capcodes = ['N']; if ($this->getAuth()->hasAccess('comment.mod_capcode')) { $allowed_capcodes[] = 'M'; } if ($this->getAuth()->hasAccess('comment.admin_capcode')) { $allowed_capcodes[] = 'A'; } if ($this->getAuth()->hasAccess('comment.dev_capcode')) { $allowed_capcodes[] = 'D'; } if (!in_array($this->comment->capcode, $allowed_capcodes)) { throw new CommentSendingUnallowedCapcodeException(_i('You\'re not allowed to use this capcode.')); } } else { $this->comment->capcode = 'N'; } $microtime = str_replace('.', '', (string) microtime(true)); $this->comment->timestamp = substr($microtime, 0, 10); $this->comment->op = (bool) (!$this->comment->thread_num); if ($this->radix->getValue('enable_flags')) { $reader = new Reader($this->preferences->get('foolframe.maxmind.geoip2_db_path')); try { $record = $reader->country(Inet::dtop($this->comment->poster_ip)); $this->comment->poster_country = strtolower($record->country->isoCode); } catch (AddressNotFoundException $e) { $this->comment->poster_country = 'xx'; } } // process comment media if ($media !== null) { // if uploading an image with OP is prohibited if (!$this->comment->thread_num && $this->radix->getValue('op_image_upload_necessity') === 'never') { throw new CommentSendingException(_i('You can\'t start a new thread with an image.')); } if (!$this->allow_media) { if ($this->ghost) { throw new CommentSendingImageInGhostException(_i('You can\'t post images when the thread is in ghost mode.')); } else { throw new CommentSendingException(_i('This thread has reached its image limit.')); } } try { $media->insert($microtime, $this->comment->op); $this->media = $media->media; } catch (MediaInsertException $e) { throw new CommentSendingException($e->getMessage()); } } else { // if the user is forced to upload an image when making a new thread if (!$this->comment->thread_num && $this->radix->getValue('op_image_upload_necessity') === 'always') { throw new CommentSendingThreadWithoutMediaException(_i('You can\'t start a new thread without an image.')); } // in case of no media, check comment field again for null if ($this->comment->comment === null) { throw new CommentSendingDisplaysEmptyException(_i('This comment would display empty.')); } $this->media = $this->bulk->media = new MediaData(); } // 2ch-style codes, only if enabled if ($this->comment->thread_num && $this->radix->getValue('enable_poster_hash')) { $this->comment->poster_hash = substr(substr(crypt(md5($this->comment->poster_ip . 'id' . $this->comment->thread_num), 'id'), +3), 0, 8); } $this->comment->timestamp = $this->getRadixTime($this->comment->timestamp); \Foolz\Plugin\Hook::forge('Foolz\\Foolslide\\Model\\CommentInsert::insert.call.before.sql')->setObject($this)->execute(); // being processing insert... if ($this->ghost) { $num = ' ( SELECT MAX(num) AS num FROM ( ( SELECT num FROM ' . $this->radix->getTable() . ' xr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' ) UNION ( SELECT num FROM ' . $this->radix->getTable('_deleted') . ' xrd WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' ) ) x )'; $subnum = ' ( SELECT MAX(subnum) + 1 AS subnum FROM ( ( SELECT subnum FROM ' . $this->radix->getTable() . ' xxr WHERE num = ( SELECT MAX(num) FROM ( ( SELECT num FROM ' . $this->radix->getTable() . ' xxxr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' ) UNION ( SELECT num FROM ' . $this->radix->getTable('_deleted') . ' xxxrd WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' ) ) xxx ) ) UNION ( SELECT subnum FROM ' . $this->radix->getTable('_deleted') . ' xxdr WHERE num = ( SELECT MAX(num) FROM ( ( SELECT num FROM ' . $this->radix->getTable() . ' xxxr WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' ) UNION ( SELECT num FROM ' . $this->radix->getTable('_deleted') . ' xxxdrd WHERE thread_num = ' . $this->dc->getConnection()->quote($this->comment->thread_num) . ' ) ) xxxd ) ) ) xx )'; $thread_num = $this->comment->thread_num; } else { $num = ' ( SELECT MAX(num) + 1 AS num FROM ( ( SELECT COALESCE(MAX(num), 0) AS num FROM ' . $this->radix->getTable() . ' xr ) UNION ( SELECT COALESCE(MAX(num), 0) AS num FROM ' . $this->radix->getTable('_deleted') . ' xdr ) ) x )'; $subnum = 0; if ($this->comment->thread_num > 0) { $thread_num = $this->dc->getConnection()->quote($this->comment->thread_num); } else { $thread_num = ' ( SELECT MAX(thread_num) + 1 AS thread_num FROM ( ( SELECT COALESCE(MAX(num), 0) as thread_num FROM ' . $this->radix->getTable() . ' xxr ) UNION ( SELECT COALESCE(MAX(num), 0) as thread_num FROM ' . $this->radix->getTable('_deleted') . ' xxdr ) ) xx )'; } } try { $query_fields = ['num' => $num, 'subnum' => $subnum, 'thread_num' => $thread_num]; $fields = ['media_id' => $this->media->media_id ? $this->media->media_id : 0, 'op' => (int) $this->op, 'timestamp' => $this->comment->timestamp, 'capcode' => $this->comment->capcode, 'email' => $this->comment->email, 'name' => $this->comment->name, 'trip' => $this->comment->trip, 'title' => $this->comment->title, 'comment' => $this->comment->comment, 'delpass' => $this->comment->getDelpass(), 'spoiler' => (int) $this->media->spoiler, 'poster_ip' => $this->comment->poster_ip, 'poster_hash' => $this->comment->poster_hash, 'poster_country' => $this->comment->poster_country, 'preview_orig' => $this->media->preview_orig, 'preview_w' => $this->media->preview_w, 'preview_h' => $this->media->preview_h, 'media_filename' => $this->media->media_filename, 'media_w' => $this->media->media_w, 'media_h' => $this->media->media_h, 'media_size' => $this->media->media_size, 'media_hash' => $this->media->media_hash, 'media_orig' => $this->media->media_orig, 'exif' => $this->media->exif !== null ? @json_encode($this->media->exif) : null, 'timestamp_expired' => 0]; foreach ($fields as $key => $item) { if ($item === null) { $fields[$key] = 'null'; } else { $fields[$key] = $this->dc->getConnection()->quote($item); } } $fields = $query_fields + $fields; $this->dc->getConnection()->beginTransaction(); $this->dc->getConnection()->executeUpdate('INSERT INTO ' . $this->radix->getTable() . ' (' . implode(', ', array_keys($fields)) . ') VALUES (' . implode(', ', array_values($fields)) . ')'); $last_id = $this->dc->getConnection()->lastInsertId($this->radix->getTable('_doc_id_seq')); $comment = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'r')->where('doc_id = :doc_id')->setParameter(':doc_id', $last_id)->execute()->fetchAll(); $this->bulk->import($comment[0], $this->radix); if (!$this->radix->archive) { $this->insertTriggerThreads(); $this->insertTriggerDaily(); $this->insertTriggerUsers(); } // update poster_hash for op posts if ($this->comment->op && $this->radix->getValue('enable_poster_hash')) { $this->comment->poster_hash = substr(substr(crypt(md5($this->comment->poster_ip . 'id' . $this->comment->thread_num), 'id'), 3), 0, 8); $this->dc->qb()->update($this->radix->getTable(), 'ph')->set('poster_hash', $this->dc->getConnection()->quote($this->comment->poster_hash))->where('doc_id = :doc_id')->setParameter(':doc_id', $this->comment->doc_id)->execute(); } $this->dc->getConnection()->commit(); // clean up some caches Cache::item('foolslide.model.board.getThreadComments.thread.' . md5(serialize([$this->radix->shortname, $this->comment->thread_num])))->delete(); // clean up the 10 first pages of index and gallery that are cached for ($i = 1; $i <= 10; $i++) { Cache::item('foolslide.model.board.getLatestComments.query.' . $this->radix->shortname . '.by_post.' . $i)->delete(); Cache::item('foolslide.model.board.getLatestComments.query.' . $this->radix->shortname . '.by_thread.' . $i)->delete(); Cache::item('foolslide.model.board.getThreadsComments.query.' . $this->radix->shortname . '.' . $i)->delete(); } } catch (\Doctrine\DBAL\DBALException $e) { $this->logger->error('\\Foolz\\Foolslide\\Model\\CommentInsert: ' . $e->getMessage()); $this->dc->getConnection()->rollBack(); throw new CommentSendingDatabaseException(_i('Something went wrong when inserting the post in the database. Try again.')); } return $this; }
public function toString() { $users = $this->getContext()->getService('users'); $radix_coll = $this->getContext()->getService('foolfuuka.radix_collection'); $form = $this->getForm(); ?> <div class="admin-container"> <div class="admin-container-header"> <?php echo _i('Bans'); ?> </div> <div class="pull-right"> <?php echo $form->open(['action' => 'admin/moderation/find_ban']); ?> <div class="input-prepend"> <label class="add-on" for="form_ip">Search by IP</label><?php echo $form->input('ip'); ?> </div> <?php echo $form->close(); ?> </div> <table class="table table-hover table-condensed"> <thead> <tr> <th><?php echo _i('IP'); ?> </th> <th><?php echo _i('Board'); ?> </th> <th><?php echo _i('Reason'); ?> </th> <th><?php echo _i('Appeal'); ?> </th> <th><?php echo _i('Issued - Length'); ?> </th> <th><?php echo _i('Actions'); ?> </th> </tr> </thead> <tbody> <?php foreach ($this->getParamManager()->getParam('bans') as $b) { ?> <tr> <td><?php echo Inet::dtop($b->ip); echo $this->getPreferences()->get('foolfuuka.sphinx.global') ? '<br><small><a href="' . $this->getUri()->create('_/search/poster_ip/' . Inet::dtop($b->ip)) . '" target="_blank">' . _i('Search posts') . '</a></small>' : ''; ?> </td> <td><?php echo $b->board_id ? '/' . $radix_coll->getById($b->board_id)->shortname . '/' : _i('Global'); ?> </td> <td><?php echo htmlentities($b->reason); ?> <br><small><?php echo _i('By:') . ' ' . htmlentities($users->getUserBy('id', $b->creator_id)->username); ?> </small></td> <td><?php echo htmlentities($b->appeal); ?> <br><small><?php echo _i('Status:') . ' ' . ($b->appeal_status == Ban::APPEAL_PENDING ? _i('pending') : '') . ($b->appeal_status == Ban::APPEAL_REJECTED ? _i('rejected') : '') . ($b->appeal_status == Ban::APPEAL_NONE ? _i('none') : ''); ?> </small></td> <td><?php echo date('d-M-y H:i:s T', $b->start); ?> , <?php echo $b->length ? $b->length / 24 / 60 / 60 . ' ' . _i('Day(s)') : _i('Forever'); ?> <br><small><?php echo _i('Status:') . ' ' . (!$b->length || time() < $b->start + $b->length ? _i('ongoing') : _i('expired')); ?> </small></td> <td> <div class="btn-group"> <a class="btn btn-small dropdown-toggle" data-toggle="dropdown" href="#"> <?php echo _i('Action'); ?> <span class="caret"></span> </a> <ul class="dropdown-menu"> <li><a href="<?php echo $this->getUri()->create('admin/moderation/ban_manage/unban/' . $b->id); ?> "><?php echo _i('Unban'); ?> </a></li> <?php if ($b->appeal_status == Ban::APPEAL_PENDING) { ?> <li><a href="<?php echo $this->getUri()->create('admin/moderation/ban_manage/reject_appeal/' . $b->id); ?> "><?php echo _i('Reject appeal'); ?> </a></li> <?php } ?> </ul> </div> </td> </tr> <?php } ?> </tbody> </table> <?php $page = $this->getParamManager()->getParam('page'); ?> <?php if ($page) { ?> <div class="pagination"> <ul> <?php if ($page > 1) { ?> <li class=""><a href="<?php echo $this->getParamManager()->getParam('page_url') . ($page - 1); ?> "><?php echo _i('Prev'); ?> </a></li> <?php } ?> <li class=""><a href="<?php echo $this->getParamManager()->getParam('page_url') . ($page + 1); ?> "><?php echo _i('Next'); ?> </a></li> </ul> </div> <?php } ?> </div> <?php }
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\Foolslide\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\Foolslide\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\Foolslide\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\Foolslide\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\Foolslide\Model\BanException $e) { return $this->response->setData(['error' => $e->getMessage()])->setStatusCode(404); } return $this->response->setData(['success' => _i('This user was banned.')]); } }
public function submit($data, $media) { // some beginners' validation, while through validation will happen in the Comment model $validator = new Validator(); $validator->add('thread_num', _i('Thread Number'), [new Assert\NotBlank()])->add('name', _i('Name'), [new Assert\Length(['max' => 64])])->add('email', _i('Email'), [new Assert\Length(['max' => 64])])->add('title', _i('Title'), [new Assert\Length(['max' => 64])])->add('delpass', _i('Deletion pass'), [new Assert\Length(['min' => 3, 'max' => 32])]); // no empty posts without images if ($media === null) { $validator->add('comment', _i('Comment'), [new Assert\NotBlank(), new Assert\Length(['min' => 3])]); } // this is for redirecting, not for the database $limit = false; if (isset($data['last_limit'])) { $limit = intval($data['last_limit']); unset($data['last_limit']); } $validator->validate($data); if (!$validator->getViolations()->count()) { try { $data['poster_ip'] = Inet::ptod($this->getRequest()->getClientIp()); $bulk = new CommentBulk(); $bulk->import($data, $this->radix); $comment = new CommentInsert($this->getContext(), $bulk); $comment->insert($media, $data); } catch (\Foolz\Foolfuuka\Model\CommentSendingRequestCaptchaException $e) { if ($this->getRequest()->isXmlHttpRequest()) { return $this->response->setData(['captcha' => true]); } else { return $this->error(_i('Your message looked like spam. Make sure you have JavaScript enabled to display the reCAPTCHA to submit the comment.')); } } catch (\Foolz\Foolfuuka\Model\CommentSendingException $e) { if ($this->getRequest()->isXmlHttpRequest()) { return $this->response->setData(['error' => $e->getMessage()]); } else { return $this->error($e->getMessage()); } } } else { if ($this->getRequest()->isXmlHttpRequest()) { return $this->response->setData(['error' => $validator->getViolations()->getText()]); } else { return $this->error($validator->getViolations()->getHtml()); } } if ($this->request->isXmlHttpRequest()) { $latest_doc_id = $this->getPost('latest_doc_id'); if ($latest_doc_id && ctype_digit((string) $latest_doc_id)) { try { $board = Board::forge($this->getContext())->getThread($comment->comment->thread_num)->setRadix($this->radix)->setOptions(['type' => 'from_doc_id', 'latest_doc_id' => $latest_doc_id]); $comments = $board->getComments(); } catch (\Foolz\Foolfuuka\Model\BoardThreadNotFoundException $e) { return $this->error(_i('Thread not found.')); } catch (\Foolz\Foolfuuka\Model\BoardException $e) { return $this->error(_i('Unknown error.')); } $comment_obj = new Comment($this->getContext()); $comment_obj->setControllerMethod($limit ? 'last/' . $limit : 'thread'); $media_obj = new Media($this->getContext()); $m = null; foreach ($board->getCommentsUnsorted() as $bulk) { $comment_obj->setBulk($bulk, $this->radix); if ($bulk->media) { $media_obj->setBulk($bulk, $this->radix); $m = $media_obj; } else { $m = null; } if ($this->builder) { $this->param_manager->setParam('controller_method', $limit ? 'last/' . $limit : 'thread'); $partial = $this->builder->createPartial('board_comment', 'board_comment'); $partial->getParamManager()->setParam('p', $comment_obj)->setParam('p_media', $m); $bulk->comment->formatted = $partial->build(); $partial->clearBuilt(); } } $this->response->setData(['success' => _i('Message sent.')] + $comments); } else { if ($this->builder) { $this->param_manager->setParam('controller_method', $limit ? 'last/' . $limit : 'thread'); $partial = $this->builder->createPartial('board_comment', 'board_comment'); $partial->getParamManager()->setParam('p', new Comment($this->getContext(), $comment->bulk))->setParam('p_media', new Media($this->getContext(), $comment->bulk)); $bulk->comment->formatted = $partial->build(); $partial->clearBuilt(); } $this->response->setData(['success' => _i('Message sent.'), 'thread_num' => $comment->comment->thread_num, $comment->comment->thread_num => ['posts' => [$comment->bulk]]]); } } else { $this->builder->createLayout('redirect')->getParamManager()->setParam('url', $this->uri->create([$this->radix->shortname, !$limit ? 'thread' : 'last/' . $limit, $comment->comment->thread_num]) . '#' . $comment->comment->num); $this->builder->getProps()->addTitle(_i('Redirecting')); $this->response->setContent($this->builder->build()); } return $this->response; }
public function action_ban_manage($action, $id) { try { $ban = $this->ban_factory->getById($id); } catch (\Foolz\Foolfuuka\Model\BanException $e) { throw new NotFoundHttpException(); } if ($this->getPost() && !$this->checkCsrfToken()) { $this->notices->set('warning', _i('The security token wasn\'t found. Try resubmitting.')); } elseif ($this->getPost()) { switch ($action) { case 'unban': $ban->delete(); $this->notices->setFlash('success', _i('The poster with IP %s has been unbanned.', Inet::dtop($ban->ip))); return $this->redirect('admin/moderation/bans'); break; case 'reject_appeal': $ban->appealReject(); $this->notices->setFlash('success', _i('The appeal of the poster with IP %s has been rejected.', Inet::dtop($ban->ip))); return $this->redirect('admin/moderation/bans'); break; default: throw new NotFoundHttpException(); } } switch ($action) { case 'unban': $this->_views['method_title'] = _i('Unbanning') . ' ' . Inet::dtop($ban->ip); $data['alert_level'] = 'warning'; $data['message'] = _i('Do you want to unban this user?'); break; case 'reject_appeal': $this->_views['method_title'] = _i('Rejecting appeal for') . ' ' . Inet::dtop($ban->ip); $data['alert_level'] = 'warning'; $data['message'] = _i('Do you want to reject the appeal of this user? He won\'t be able to appeal again.'); break; default: throw new NotFoundHttpException(); } $this->builder->createPartial('body', 'confirm')->getParamManager()->setParams($data); return new Response($this->builder->build()); }
/** * Gets the search results * * @return \Foolz\Foolfuuka\Model\Search The current object * @throws SearchEmptyResultException If there's no results to display * @throws SearchRequiresSphinxException If the search submitted requires Sphinx to run * @throws SearchSphinxOfflineException If the Sphinx server is unreachable * @throws SearchInvalidException If the values of the search weren't compatible with the domain */ protected function p_getSearchComments() { $this->profiler->log('Board::getSearchComments Start'); extract($this->options); // set all empty fields to null $search_fields = ['boards', 'subject', 'text', 'username', 'tripcode', 'email', 'capcode', 'uid', 'poster_ip', 'filename', 'image', 'deleted', 'ghost', 'filter', 'type', 'start', 'end', 'results', 'order']; foreach ($search_fields as $field) { if (!isset($args[$field])) { $args[$field] = null; } } // populate an array containing all boards that would be searched $boards = []; if ($args['boards'] !== null) { foreach ($args['boards'] as $board) { $b = $this->radix_coll->getByShortname($board); if ($b) { $boards[] = $b; } } } // search all boards if none selected if (count($boards) == 0) { $boards = $this->radix_coll->getAll(); } // if image is set, get either the media_hash or media_id if ($args['image'] !== null) { if (substr($args['image'], -2) !== '==') { $args['image'] .= '=='; } // if board is set, retrieve media_id if ($this->radix !== null) { try { $media = $this->media_factory->getByMediaHash($this->radix, $args['image']); } catch (MediaNotFoundException $e) { $this->comments_unsorted = []; $this->comments = []; $this->profiler->log('Board::getSearchComments Ended Prematurely'); throw new SearchEmptyResultException(_i('No results found.')); } $args['image'] = $media->media_id; } } if ($this->radix === null && !$this->preferences->get('foolfuuka.sphinx.global')) { // global search requires sphinx throw new SearchRequiresSphinxException(_i('Sorry, this action requires the Sphinx to be installed and running.')); } elseif ($this->radix === null && $this->preferences->get('foolfuuka.sphinx.global') || $this->radix !== null && $this->radix->sphinx) { // configure sphinx connection params $sphinx = explode(':', $this->preferences->get('foolfuuka.sphinx.listen')); $conn = new SphinxConnnection(); $conn->setParams(['host' => $sphinx[0], 'port' => $sphinx[1], 'options' => [MYSQLI_OPT_CONNECT_TIMEOUT => 5]]); $conn->silenceConnectionWarning(true); // establish connection try { SphinxQL::forge($conn); } catch (\Foolz\SphinxQL\ConnectionException $e) { throw new SearchSphinxOfflineException(_i('The search backend is currently unavailable.')); } // determine if all boards will be used for search or not if ($this->radix == null) { $indexes = []; foreach ($boards as $radix) { if (!$radix->sphinx) { continue; } $indexes[] = $radix->shortname . '_ancient'; $indexes[] = $radix->shortname . '_main'; $indexes[] = $radix->shortname . '_delta'; } } else { $indexes = [$this->radix->shortname . '_ancient', $this->radix->shortname . '_main', $this->radix->shortname . '_delta']; } // start search query $query = SphinxQL::forge()->select('id', 'board')->from($indexes); // parse search params if ($args['subject'] !== null) { $query->match('title', $args['subject']); } if ($args['text'] !== null) { if (mb_strlen($args['text'], 'utf-8') < 1) { return []; } $query->match('comment', $args['text'], true); } if ($args['username'] !== null) { $query->match('name', $args['username']); } if ($args['tripcode'] !== null) { $query->match('trip', '"' . $args['tripcode'] . '"'); } if ($args['email'] !== null) { $query->match('email', $args['email']); } if ($args['capcode'] !== null) { if ($args['capcode'] === 'user') { $query->where('cap', ord('N')); } elseif ($args['capcode'] === 'mod') { $query->where('cap', ord('M')); } elseif ($args['capcode'] === 'admin') { $query->where('cap', ord('A')); } elseif ($args['capcode'] === 'dev') { $query->where('cap', ord('D')); } } if ($args['uid'] !== null) { $query->match('pid', $args['uid']); } if ($this->getAuth()->hasAccess('comment.see_ip') && $args['poster_ip'] !== null) { $query->where('pip', (int) Inet::ptod($args['poster_ip'])); } if ($args['filename'] !== null) { $query->match('media_filename', $args['filename']); } if ($args['image'] !== null) { if ($this->radix !== null) { $query->where('mid', (int) $args['image']); } else { $query->match('media_hash', '"' . $args['image'] . '"'); } } if ($args['deleted'] !== null) { if ($args['deleted'] == 'deleted') { $query->where('is_deleted', 1); } if ($args['deleted'] == 'not-deleted') { $query->where('is_deleted', 0); } } if ($args['ghost'] !== null) { if ($args['ghost'] == 'only') { $query->where('is_internal', 1); } if ($args['ghost'] == 'none') { $query->where('is_internal', 0); } } if ($args['filter'] !== null) { if ($args['filter'] == 'image') { $query->where('has_image', 0); } if ($args['filter'] == 'text') { $query->where('has_image', 1); } } if ($args['type'] !== null) { if ($args['type'] == 'sticky') { $query->where('is_sticky', 1); } if ($args['type'] == 'op') { $query->where('is_op', 1); } if ($args['type'] == 'posts') { $query->where('is_op', 0); } } if ($args['start'] !== null) { $query->where('timestamp', '>=', intval(strtotime($args['start']))); } if ($args['end'] !== null) { $query->where('timestamp', '<=', intval(strtotime($args['end']))); } if ($args['results'] !== null) { if ($args['results'] == 'op') { $query->groupBy('thread_num'); $query->withinGroupOrderBy('is_op', 'desc'); } if ($args['results'] == 'posts') { $query->where('is_op', 0); } } if ($args['order'] !== null && $args['order'] == 'asc') { $query->orderBy('timestamp', 'ASC'); } else { $query->orderBy('timestamp', 'DESC'); } $max_matches = $this->preferences->get('foolfuuka.sphinx.max_matches', 5000); // set sphinx options $query->limit($limit)->offset($page * $limit - $limit >= $max_matches ? $max_matches - 1 : $page * $limit - $limit)->option('max_matches', (int) $max_matches)->option('reverse_scan', $args['order'] === 'asc' ? 0 : 1); // submit query try { $search = $query->execute(); } catch (\Foolz\SphinxQL\DatabaseException $e) { $this->logger->error('Search Error: ' . $e->getMessage()); throw new SearchInvalidException(_i('The search backend returned an error.')); } // no results found if (!count($search)) { $this->comments_unsorted = []; $this->comments = []; throw new SearchEmptyResultException(_i('No results found.')); } $sphinx_meta = Helper::pairsToAssoc(Helper::create($conn)->showMeta()->execute()); $this->total_count = $sphinx_meta['total']; $this->total_found = $sphinx_meta['total_found']; // populate sql array for full records $sql = []; foreach ($search as $doc => $result) { $board = $this->radix_coll->getById($result['board']); $sql[] = $this->dc->qb()->select('*, ' . $result['board'] . ' AS board_id')->from($board->getTable(), 'r')->leftJoin('r', $board->getTable('_images'), 'mg', 'mg.media_id = r.media_id')->where('doc_id = ' . $this->dc->getConnection()->quote($result['id']))->getSQL(); } $result = $this->dc->getConnection()->executeQuery(implode(' UNION ', $sql))->fetchAll(); } else { // this is not implemented yet, would require some sort of MySQL search throw new SearchRequiresSphinxException(_i('Sorry, this board does not have search enabled.')); } // no results found IN DATABASE, but we might still get a search count from Sphinx if (!count($result)) { $this->comments_unsorted = []; $this->comments = []; } else { // process results foreach ($result as $key => $row) { $board = $this->radix !== null ? $this->radix : $this->radix_coll->getById($row['board_id']); $bulk = new CommentBulk(); $bulk->import($row, $board); $this->comments_unsorted[] = $bulk; unset($result[$key]); } } $this->comments[0]['posts'] = $this->comments_unsorted; return $this; }
public function toString() { $board = $this->getParamManager()->getParam('board'); $controller_method = $this->getBuilderParamManager()->getParam('controller_method', 'thread'); $thread_id = $this->getBuilderParamManager()->getParam('thread_id', 0); foreach ($board as $key => $post) { if (isset($post['op'])) { $op_bulk = $post['op']; $op = new Comment($this->getContext(), $op_bulk); $op->setControllerMethod($controller_method); if ($op_bulk->media !== null) { $op_media = new Media($this->getContext(), $op_bulk); } else { $op_media = null; } $num = $op->num . ($op->subnum ? '_' . $op->subnum : ''); ?> <?php if ($thread_id === 0) { ?> <div class="thread stub stub_doc_id_<?php echo $op->doc_id; ?> "> <button class="btn-toggle-post" data-function="showThread" data-board="<?php echo $op->radix->shortname; ?> " data-doc-id="<?php echo $op->doc_id; ?> " data-thread-num="<?php echo $op->thread_num; ?> "><i class="icon-plus"></i></button> <?php if ($op->email && $op->email !== 'noko') { ?> <a href="mailto:<?php echo rawurlencode($op->email); ?> "><?php } ?> <span class="post_author"><?php echo $op->getNameProcessed(); ?> </span><?php echo $op->getNameProcessed() && $op->getTripProcessed() ? ' ' : ''; ?> <span class="post_tripcode"><?php echo $op->getTripProcessed(); ?> </span><?php if ($op->email && $op->email !== 'noko') { ?> </a><?php } ?> (<?php echo $post['omitted'] + 5 . ' ' . _i('replies'); ?> ) </div> <?php } ?> <article id="<?php echo $num; ?> " class="clearfix thread doc_id_<?php echo $op->doc_id; ?> board_<?php echo $op->radix->shortname; ?> " data-doc-id="<?php echo $op->doc_id; ?> " data-thread-num="<?php echo $op->thread_num; ?> "> <?php if ($thread_id === 0) { ?> <div class="stub pull-left"> <button class="btn-toggle-post" data-function="hideThread" data-board="<?php echo $op->radix->shortname; ?> " data-doc-id="<?php echo $op->doc_id; ?> "><i class="icon-minus"></i></button> </div> <?php } ?> <?php \Foolz\Plugin\Hook::forge('foolfuuka.themes.default_after_op_open')->setObject($this)->setParam('board', $op->radix)->execute(); ?> <?php if ($op_media !== null) { ?> <div class="thread_image_box"> <?php if ($op_media->getMediaStatus($this->getRequest()) === 'banned') { ?> <img src="<?php echo $this->getAssetManager()->getAssetLink('images/banned-image.png'); ?> " width="150" height="150" /> <?php } elseif ($op_media->getMediaStatus($this->getRequest()) !== 'normal') { ?> <a href="<?php echo $op_media->getMediaLink($this->getRequest()) ? $op_media->getMediaLink($this->getRequest()) : $op_media->getRemoteMediaLink($this->getRequest()); ?> " target="_blank" rel="noreferrer" class="thread_image_link"> <img src="<?php echo $this->getAssetManager()->getAssetLink('images/missing-image.jpg'); ?> " width="150" height="150" /> </a> <?php } else { ?> <a href="<?php echo $op_media->getMediaLink($this->getRequest()) ? $op_media->getMediaLink($this->getRequest()) : $op_media->getRemoteMediaLink($this->getRequest()); ?> " target="_blank" rel="noreferrer" class="thread_image_link"> <?php if (!$this->getAuth()->hasAccess('maccess.mod') && !$op->radix->getValue('transparent_spoiler') && $op_media->spoiler) { ?> <div class="spoiler_box"><span class="spoiler_box_text"><?php echo _i('Spoiler'); ?> <span class="spoiler_box_text_help"><?php echo _i('Click to view'); ?> </span></div> <?php } else { ?> <img src="<?php echo $op_media->getThumbLink($this->getRequest()); ?> " width="<?php echo $op_media->preview_w; ?> " height="<?php echo $op_media->preview_h; ?> " class="thread_image<?php echo $op_media->spoiler ? ' is_spoiler_image' : ''; ?> " data-md5="<?php echo $op_media->media_hash; ?> " /> <?php } ?> </a> <?php } ?> <?php if ($op_media->getMediaStatus($this->getRequest()) !== 'banned') { ?> <div class="post_file" style="padding-left: 2px;<?php if ($op_media->preview_w > 149) { echo 'max-width:' . $op_media->preview_w . 'px;'; } ?> "> <?php echo ByteSize::formatBinary($op_media->media_size, 0) . ', ' . $op_media->media_w . 'x' . $op_media->media_h . ', '; ?> <a class="post_file_filename" href="<?php echo $op_media->getMediaLink($this->getRequest()) ? $op_media->getMediaLink($this->getRequest()) : $op_media->getRemoteMediaLink($this->getRequest()); ?> " target="_blank"><?php echo $op_media->getMediaFilenameProcessed(); ?> </a> </div> <?php } ?> <div class="post_file_controls"> <?php if ($op_media->getMediaStatus($this->getRequest()) !== 'banned' || $this->getAuth()->hasAccess('media.see_banned')) { ?> <?php if (!$op->radix->hide_thumbnails || $this->getAuth()->hasAccess('maccess.mod')) { ?> <a href="<?php echo $this->getUri()->create($op->radix->shortname . '/search/image/' . $op_media->getSafeMediaHash()); ?> " class="btnr parent"><?php echo _i('View Same'); ?> </a><a href="http://google.com/searchbyimage?image_url=<?php echo $op_media->getThumbLink($this->getRequest()); ?> " target="_blank" class="btnr parent">Google</a><a href="http://iqdb.org/?url=<?php echo $op_media->getThumbLink($this->getRequest()); ?> " target="_blank" class="btnr parent">iqdb</a><a href="http://saucenao.com/search.php?url=<?php echo $op_media->getThumbLink($this->getRequest()); ?> " target="_blank" class="btnr parent">SauceNAO</a><?php if (!$op->radix->archive || $op->radix->getValue('archive_full_images')) { ?> <a href="<?php echo $op_media->getMediaDownloadLink($this->getRequest()); ?> " download="<?php echo $op_media->getMediaFilenameProcessed(); ?> " class="btnr parent"><i class="icon-download-alt"></i></a><?php } ?> <?php } ?> <?php } ?> </div> </div> <?php } ?> <header> <div class="post_data"> <?php if ($op->getTitleProcessed() !== '') { ?> <h2 class="post_title"><?php echo $op->getTitleProcessed(); ?> </h2><?php } ?> <span class="post_poster_data"> <?php if ($op->email && $op->email !== 'noko') { ?> <a href="mailto:<?php echo rawurlencode($op->email); ?> "><?php } ?> <span class="post_author"><?php echo $op->getNameProcessed(); ?> </span><?php echo $op->getNameProcessed() && $op->getTripProcessed() ? ' ' : ''; ?> <span class="post_tripcode"><?php echo $op->getTripProcessed(); ?> </span><?php if ($op->email && $op->email !== 'noko') { ?> </a><?php } ?> <?php if ($op->getPosterHashProcessed()) { ?> <span class="poster_hash">ID:<?php echo $op->getPosterHashProcessed(); ?> </span><?php } ?> <?php if ($op->capcode !== 'N') { ?> <?php if ($op->capcode === 'M') { ?> <span class="post_level post_level_moderator">## <?php echo _i('Mod'); ?> </span><?php } ?> <?php if ($op->capcode === 'A') { ?> <span class="post_level post_level_administrator">## <?php echo _i('Admin'); ?> </span><?php } ?> <?php if ($op->capcode === 'D') { ?> <span class="post_level post_level_developer">## <?php echo _i('Developer'); ?> </span><?php } ?> <?php } ?> </span> <span class="time_wrap"> <time datetime="<?php echo gmdate(DATE_W3C, $op->timestamp); ?> " class="show_time" <?php if ($op->radix->archive) { ?> title="<?php echo _i('4chan Time') . ': ' . $op->getFourchanDate(); ?> "<?php } ?> ><?php echo gmdate('D d M H:i:s Y', $op->timestamp); ?> </time> </span> <a href="<?php echo $this->getUri()->create(array($op->radix->shortname, $controller_method, $op->thread_num)) . '#' . $num; ?> " data-post="<?php echo $num; ?> " data-function="highlight">No.</a><a href="<?php echo $this->getUri()->create(array($op->radix->shortname, $controller_method, $op->thread_num)) . '#q' . $num; ?> " data-post="<?php echo $num; ?> " data-function="quote"><?php echo $num; ?> </a> <span class="post_type"> <?php if ($op->poster_country !== null) { ?> <span title="<?php echo e($op->poster_country_name); ?> " class="flag flag-<?php echo strtolower($op->poster_country); ?> "></span><?php } ?> <?php if (isset($op_media) && $op_media->spoiler) { ?> <i class="icon-eye-close" title="<?php echo htmlspecialchars(_i('The image in this post has been marked spoiler.')); ?> "></i><?php } ?> <?php if ($op->deleted && !$op->timestamp_expired) { ?> <i class="icon-trash" title="<?php echo htmlspecialchars(_i('This thread was prematurely deleted.')); ?> "></i><?php } ?> <?php if ($op->deleted && $op->timestamp_expired) { ?> <i class="icon-trash" title="<?php echo htmlspecialchars(_i('This thread was deleted on %s.', gmdate('M d, Y \\a\\t H:i:s e', $op->timestamp_expired))); ?> "></i><?php } ?> <?php if ($op->sticky) { ?> <i class="icon-pushpin" title="<?php echo _i('This thread has been stickied.'); ?> "></i><?php } ?> <?php if ($op->locked) { ?> <i class="icon-lock" title="<?php echo _i('This thread has been locked.'); ?> "></i><?php } ?> </span> <span class="post_controls"> <a href="<?php echo $this->getUri()->create(array($op->radix->shortname, 'thread', $num)); ?> " class="btnr parent"><?php echo _i('View'); ?> </a><a href="<?php echo $this->getUri()->create(array($op->radix->shortname, $controller_method, $num)) . '#reply'; ?> " class="btnr parent"><?php echo _i('Reply'); ?> </a><?php echo isset($post['omitted']) && $post['omitted'] > 50 ? '<a href="' . $this->getUri()->create($op->radix->shortname . '/last/50/' . $num) . '" class="btnr parent">' . _i('Last 50') . '</a>' : ''; echo $op->radix->archive ? '<a href="//boards.4chan.org/' . $op->radix->shortname . '/thread/' . $num . '" class="btnr parent">' . _i('Original') . '</a>' : ''; ?> <a href="#" class="btnr parent" data-post="<?php echo $op->doc_id; ?> " data-post-id="<?php echo $num; ?> " data-board="<?php echo htmlspecialchars($op->radix->shortname); ?> " data-controls-modal="post_tools_modal" data-backdrop="true" data-keyboard="true" data-function="report"><?php echo _i('Report'); ?> </a><?php if ($this->getAuth()->hasAccess('maccess.mod') || !$op->radix->archive) { ?> <a href="#" class="btnr parent" data-post="<?php echo $op->doc_id; ?> " data-post-id="<?php echo $num; ?> " data-board="<?php echo htmlspecialchars($op->radix->shortname); ?> " data-controls-modal="post_tools_modal" data-backdrop="true" data-keyboard="true" data-function="delete"><?php echo _i('Delete'); ?> </a><?php } ?> </span> <div class="backlink_list"<?php echo $op->getBacklinks() ? ' style="display:block"' : ''; ?> > <?php echo _i('Quoted By:'); ?> <span class="post_backlink" data-post="<?php echo $num; ?> "><?php echo $op->getBacklinks() ? implode(' ', $op->getBacklinks()) : ''; ?> </span> </div> <?php if ($this->getAuth()->hasAccess('maccess.mod')) { ?> <div class="btn-group" style="clear:both; padding:5px 0 0 0;"> <button class="btn btn-mini" data-function="activateModeration"><?php echo _i('Mod'); if ($op->poster_ip) { echo ' ' . Inet::dtop($op->poster_ip); } ?> </button> </div> <div class="btn-group post_mod_controls" style="clear:both; padding:5px 0 0 0;"> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $op->radix->shortname; ?> " data-id="<?php echo $op->doc_id; ?> " data-action="delete_post"><?php echo _i('Delete Thread'); ?> </button> <?php if (!is_null($op_media)) { ?> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $op->radix->shortname; ?> " data-id="<?php echo $op_media->media_id; ?> " data-doc-id="<?php echo $op->doc_id; ?> " data-action="delete_image"><?php echo _i('Delete Image'); ?> </button> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $op->radix->shortname; ?> " data-id="<?php echo $op_media->media_id; ?> " data-doc-id="<?php echo $op->doc_id; ?> " data-action="ban_image_local"><?php echo _i('Ban Image'); ?> </button> <button class="btn btn-mini" data-function="mod" data-board="<?php echo $op->radix->shortname; ?> " data-id="<?php echo $op_media->media_id; ?> " data-doc-id="<?php echo $op->doc_id; ?> " data-action="ban_image_global"><?php echo _i('Ban Image Globally'); ?> </button> <?php } ?> <?php if ($op->poster_ip) { ?> <button class="btn btn-mini" data-function="ban" data-controls-modal="post_tools_modal" data-backdrop="true" data-keyboard="true" data-board="<?php echo $op->radix->shortname; ?> " data-ip="<?php echo Inet::dtop($op->poster_ip); ?> " data-action="ban_user"><?php echo _i('Ban IP:') . ' ' . Inet::dtop($op->poster_ip); ?> </button> <button class="btn btn-mini" data-function="searchUser" data-board="<?php echo $op->radix->shortname; ?> " data-board-url="<?php echo $this->getUri()->create(array($op->radix->shortname)); ?> " data-id="<?php echo $op->doc_id; ?> " data-poster-ip="<?php echo Inet::dtop($op->poster_ip); ?> "><?php echo _i('Search IP'); ?> </button> <?php if ($this->getPreferences()->get('foolfuuka.sphinx.global')) { ?> <button class="btn btn-mini" data-function="searchUserGlobal" data-board="<?php echo $op->radix->shortname; ?> " data-board-url="<?php echo $this->getUri()->create(array($op->radix->shortname)); ?> " data-id="<?php echo $op->doc_id; ?> " data-poster-ip="<?php echo Inet::dtop($op->poster_ip); ?> "><?php echo _i('Search IP Globally'); ?> </button> <?php } ?> <?php } ?> </div> <?php } ?> </div> </header> <div class="text<?php if (preg_match('/[\\x{4E00}-\\x{9FBF}\\x{3040}-\\x{309F}\\x{30A0}-\\x{30FF}]/u', $op->getCommentProcessed())) { echo ' shift-jis'; } ?> "> <?php echo $op->getCommentProcessed(); ?> </div> <div class="thread_tools_bottom"> <?php if (isset($post['omitted']) && $post['omitted'] > 0) { ?> <span class="omitted"> <a style="display:inline-block" href="<?php echo $this->getUri()->create(array($op->radix->shortname, $controller_method, $op->thread_num)); ?> " data-function="expandThread" data-thread-num="<?php echo $op->thread_num; ?> "><i class="icon icon-resize-full"></i></a> <span class="omitted_text"> <span class="omitted_posts"><?php echo $post['omitted']; ?> </span> <?php echo _n('post', 'posts', $post['omitted']); ?> <?php if (isset($post['images_omitted']) && $post['images_omitted'] > 0) { ?> <?php echo _i('and'); ?> <span class="omitted_images"><?php echo $post['images_omitted']; ?> </span> <?php echo _n('image', 'images', $post['images_omitted']); ?> <?php } ?> <?php echo _n('omitted', 'omitted', $post['omitted'] + $post['images_omitted']); ?> </span> <?php } ?> </div> <?php if ($op->getReports()) { ?> <?php foreach ($op->getReports() as $report) { ?> <div class="report_reason"><?php echo '<strong>' . _i('Reported Reason:') . '</strong> ' . $report->getReasonProcessed(); ?> <br/> <div class="ip_reporter"> <strong><?php echo _i('Info:'); ?> </strong> <?php echo Inet::dtop($report->ip_reporter); ?> , <?php echo _i('Type:'); ?> <?php echo $report->media_id !== null ? _i('media') : _i('post'); ?> , <?php echo _i('Time:'); ?> <?php echo gmdate('D M d H:i:s Y', $report->created); ?> <button class="btn btn-mini" data-function="mod" data-id="<?php echo $report->id; ?> " data-board="<?php echo htmlspecialchars($op->radix->shortname); ?> " data-action="delete_report"><?php echo _i('Delete Report'); ?> </button> </div> </div> <?php } ?> <?php } ?> <?php } elseif (isset($post['posts'])) { ?> <article class="clearfix thread"> <?php \Foolz\Plugin\Hook::forge('foolfuuka.themes.default_after_headless_open')->setObject($this)->setParam('board', array(isset($radix) ? $radix : null))->execute(); ?> <?php } ?> <aside class="posts"> <?php if (isset($post['posts'])) { $post_counter = 0; $image_counter = 0; $board_comment_view = $this->getBuilder()->createPartial('post', 'board_comment'); // reusable Comment object not to create one every loop $comment = new Comment($this->getContext()); $comment->setControllerMethod($controller_method); $media_obj = new Media($this->getContext()); $search = array('/\\>[^\\S ]+/s', '/[^\\S ]+\\</s', '/(\\s)+/s'); $replace = array('>', '<', '\\1'); foreach ($post['posts'] as $p) { /** @var CommentBulk $p */ $post_counter++; if ($p->media !== null) { $image_counter++; } if ($image_counter == 150) { $modifiers['lazyload'] = true; } $comment->setBulk($p); // set the $media to null and leave the Media object in existence if ($p->media !== null) { $media_obj->setBulk($p); $media = $media_obj; } else { $media = null; } $board_comment_view->getParamManager()->setParams(['p' => $comment, 'p_media' => $media, 'modifiers' => $this->getBuilderParamManager()->getParam('modifiers', false), 'post_counter' => $post_counter, 'image_counter' => $image_counter]); // refreshes the string $board_comment_view->doBuild(); echo preg_replace($search, $replace, $board_comment_view->build()); // remove extra strings from the objects $board_comment_view->clearBuilt(); $p->comment->clean(); if ($p->media !== null) { $p->media->clean(); } $this->flush(); } } ?> </aside> <?php if ($thread_id !== 0) { ?> <div class="js_hook_realtimethread"></div> <?php echo $this->getBuilder()->isPartial('tools_reply_box') ? $this->getBuilder()->getPartial('tools_reply_box')->build() : ''; ?> <?php } ?> <?php if (isset($post['op']) || isset($post['posts'])) { ?> </article> <?php } ?> <?php } ?> <article class="clearfix thread backlink_container"> <div id="backlink" style="position: absolute; top: 0; left: 0; z-index: 5;"></div> </article> <?php }
/** * Gets the search results * * @return \Foolz\FoolFuuka\Model\Search The current object * @throws SearchEmptyResultException If there's no results to display * @throws SearchRequiresSphinxException If the search submitted requires Sphinx to run * @throws SearchSphinxOfflineException If the Sphinx server is unreachable * @throws SearchInvalidException If the values of the search weren't compatible with the domain */ protected function p_getResults() { $this->profiler->log('Search::getResults Start'); extract($this->options); $boards = []; $input = $this->getUserInput(); if ($this->radix !== null) { $boards[] = $this->radix; } elseif ($input['boards'] !== null) { foreach ($input['boards'] as $board) { $b = $this->radix_coll->getByShortname($board); if ($b) { $boards[] = $b; } } } // search all boards if none selected if (count($boards) == 0) { $boards = $this->radix_coll->getAll(); } // if image is set, get either the media_hash or media_id if ($input['image'] !== null && substr($input['image'], -2) !== '==') { $input['image'] .= '=='; } if ($this->radix === null && !$this->preferences->get('foolfuuka.sphinx.global')) { throw new SearchRequiresSphinxException(_i('Sorry, the global search function has not been enabled.')); } if ($this->radix !== null && !$this->radix->sphinx) { throw new SearchRequiresSphinxException(_i('Sorry, this board does not have search enabled.')); } $sphinx = explode(':', $this->preferences->get('foolfuuka.sphinx.listen')); $conn = new SphinxConnnection(); $conn->setParams(['host' => $sphinx[0], 'port' => $sphinx[1], 'options' => [MYSQLI_OPT_CONNECT_TIMEOUT => 5]]); $indices = []; foreach ($boards as $radix) { if (!$radix->sphinx) { continue; } $indices[] = $radix->shortname . '_ancient'; $indices[] = $radix->shortname . '_main'; $indices[] = $radix->shortname . '_delta'; } // establish connection try { $query = SphinxQL::create($conn)->select('id', 'board', 'tnum')->from($indices)->setFullEscapeChars(['\\', '(', ')', '|', '-', '!', '@', '%', '~', '"', '&', '/', '^', '$', '='])->setHalfEscapeChars(['\\', '(', ')', '!', '@', '%', '~', '&', '/', '^', '$', '=']); } catch (\Foolz\SphinxQL\Exception\ConnectionException $e) { throw new SearchSphinxOfflineException($this->preferences->get('foolfuuka.sphinx.custom_message', _i('The search backend is currently unavailable.'))); } // process user input if ($input['subject'] !== null) { $query->match('title', $input['subject']); } if ($input['text'] !== null) { if (mb_strlen($input['text'], 'utf-8') < 1) { return []; } $query->match('comment', $input['text'], true); } if ($input['username'] !== null) { $query->match('name', $input['username']); } if ($input['tripcode'] !== null) { $query->match('trip', '"' . $input['tripcode'] . '"'); } if ($input['email'] !== null) { $query->match('email', $input['email']); } if ($input['capcode'] !== null) { switch ($input['capcode']) { case 'user': $query->where('cap', ord('N')); break; case 'mod': $query->where('cap', ord('M')); break; case 'dev': $query->where('cap', ord('D')); break; case 'admin': $query->where('cap', ord('A')); break; } } if ($input['uid'] !== null) { $query->match('pid', $input['uid']); } if ($input['country'] !== null) { $query->match('country', $input['country'], true); } if ($this->getAuth()->hasAccess('comment.see_ip') && $input['poster_ip'] !== null) { $query->where('pip', (int) Inet::ptod($input['poster_ip'])); } if ($input['filename'] !== null) { $query->match('media_filename', $input['filename']); } if ($input['image'] !== null) { $query->match('media_hash', '"' . $input['image'] . '"'); } if ($input['deleted'] !== null) { switch ($input['deleted']) { case 'deleted': $query->where('is_deleted', 1); break; case 'not-deleted': $query->where('is_deleted', 0); break; } } if ($input['ghost'] !== null) { switch ($input['ghost']) { case 'only': $query->where('is_internal', 1); break; case 'none': $query->where('is_internal', 0); break; } } if ($input['filter'] !== null) { switch ($input['filter']) { case 'image': $query->where('has_image', 0); break; case 'text': $query->where('has_image', 1); break; } } if ($input['type'] !== null) { switch ($input['type']) { case 'sticky': $query->where('is_sticky', 1); break; case 'op': $query->where('is_op', 1); break; case 'posts': $query->where('is_op', 0); break; } } if ($input['start'] !== null) { $query->where('timestamp', '>=', intval(strtotime($input['start']))); } if ($input['end'] !== null) { $query->where('timestamp', '<=', intval(strtotime($input['end']))); } if ($input['results'] !== null && $input['results'] == 'thread') { $query->groupBy('tnum'); $query->withinGroupOrderBy('is_op', 'desc'); } if ($input['order'] !== null && $input['order'] == 'asc') { $query->orderBy('timestamp', 'ASC'); } else { $query->orderBy('timestamp', 'DESC'); } $max_matches = $this->preferences->get('foolfuuka.sphinx.max_matches', 5000); // set sphinx options $query->limit($limit)->offset($page * $limit - $limit >= $max_matches ? $max_matches - 1 : $page * $limit - $limit)->option('max_matches', (int) $max_matches)->option('reverse_scan', $input['order'] === 'asc' ? 0 : 1); // submit query try { $this->profiler->log('Start: SphinxQL: ' . $query->compile()->getCompiled()); $search = $query->execute(); $this->profiler->log('Stop: SphinxQL'); } catch (\Foolz\SphinxQL\Exception\DatabaseException $e) { $this->logger->error('Search Error: ' . $e->getMessage()); throw new SearchInvalidException(_i('The search backend returned an error.')); } // no results found if (!count($search)) { $this->comments_unsorted = []; $this->comments = []; throw new SearchEmptyResultException(_i('No results found.')); } $sphinx_meta = Helper::pairsToAssoc(Helper::create($conn)->showMeta()->execute()); $this->total_count = $sphinx_meta['total']; $this->total_found = $sphinx_meta['total_found']; // populate sql array for full records $sql = []; foreach ($search as $doc => $result) { $board = $this->radix_coll->getById($result['board']); if ($input['results'] !== null && $input['results'] == 'thread') { $post = 'num = ' . $this->dc->getConnection()->quote($result['tnum']) . ' AND subnum = 0'; } else { $post = 'doc_id = ' . $this->dc->getConnection()->quote($result['id']); } $sql[] = $this->dc->qb()->select('*, ' . $result['board'] . ' AS board_id')->from($board->getTable(), 'r')->leftJoin('r', $board->getTable('_images'), 'mg', 'mg.media_id = r.media_id')->where($post)->getSQL(); } $result = $this->dc->getConnection()->executeQuery(implode(' UNION ', $sql))->fetchAll(); // no results found IN DATABASE, but we might still get a search count from Sphinx if (!count($result)) { $this->comments_unsorted = []; $this->comments = []; } else { // process results foreach ($result as $key => $row) { $board = $this->radix !== null ? $this->radix : $this->radix_coll->getById($row['board_id']); $bulk = new CommentBulk(); $bulk->import($row, $board); $this->comments_unsorted[] = $bulk; unset($result[$key]); } } $this->comments[0]['posts'] = $this->comments_unsorted; return $this; }