Beispiel #1
0
 /**
  * @param bool $reload
  * @return array|mixed
  */
 public function load($reload = false)
 {
     $this->profiler->log('Preferences::load Start');
     if ($reload === true) {
         Cache::item('foolframe.model.preferences.settings')->delete();
     }
     $this->modules = $this->config->get('foolz/foolframe', 'config', 'modules.installed');
     try {
         $this->preferences = Cache::item('foolframe.model.preferences.settings')->get();
     } catch (\OutOfBoundsException $e) {
         $preferences = $this->dc->qb()->select('*')->from($this->dc->p('preferences'), 'p')->execute()->fetchAll();
         foreach ($preferences as $pref) {
             // fix the PHP issue where . is changed to _ in the $_POST array
             $this->preferences[$pref['name']] = $pref['value'];
         }
         Cache::item('foolframe.model.preferences.settings')->set($this->preferences, 3600);
     }
     $this->preferences = Hook::forge('Foolz\\FoolFrame\\Model\\Preferences::load#var.preferences')->setObject($this)->setParam('preferences', $this->preferences)->execute()->get($this->preferences);
     $this->profiler->logMem('Preferences $preferences', $this->preferences);
     $this->profiler->log('Preferences::load End');
     $this->loaded = true;
     return $this->preferences;
 }
Beispiel #2
0
 /**
  * Gets a thread
  *
  * @return  \Foolz\Foolslide\Model\Board  The current object
  * @throws  BoardThreadNotFoundException  If the thread wasn't found
  */
 protected function p_getThreadComments()
 {
     $this->profiler->log('Board::getThreadComments Start');
     extract($this->options);
     // determine type
     switch ($type) {
         case 'from_doc_id':
             $query_result = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'r')->leftJoin('r', $this->radix->getTable('_images'), 'mg', 'mg.media_id = r.media_id')->where('thread_num = :thread_num')->andWhere('doc_id > :latest_doc_id')->orderBy('num', 'ASC')->addOrderBy('subnum', 'ASC')->setParameter(':thread_num', $num)->setParameter(':latest_doc_id', $latest_doc_id)->execute()->fetchAll();
             break;
         case 'ghosts':
             $query_result = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'r')->leftJoin('r', $this->radix->getTable('_images'), 'mg', 'mg.media_id = r.media_id')->where('thread_num = :thread_num')->where('subnum <> 0')->orderBy('num', 'ASC')->addOrderBy('subnum', 'ASC')->setParameter(':thread_num', $num)->execute()->fetchAll();
             break;
         case 'last_x':
             try {
                 // we save some cache memory by only saving last_50, so it must always fail otherwise
                 if ($last_limit != 50) {
                     throw new \OutOfBoundsException();
                 }
                 $query_result = Cache::item('foolslide.model.board.getThreadComments.last_50.' . md5(serialize([$this->radix->shortname, $num])))->get();
             } catch (\OutOfBoundsException $e) {
                 $subquery_first = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'xr')->where('num = ' . $this->dc->getConnection()->quote($num))->setMaxResults(1)->getSQL();
                 $subquery_last = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'xrr')->where('thread_num = ' . $this->dc->getConnection()->quote($num))->orderBy('num', 'DESC')->addOrderBy('subnum', 'DESC')->setMaxResults($last_limit)->getSQL();
                 $query_result = $this->dc->qb()->select('*')->from('((' . $subquery_first . ') UNION (' . $subquery_last . '))', 'r')->leftJoin('r', $this->radix->getTable('_images'), 'mg', 'mg.media_id = r.media_id')->orderBy('num', 'ASC')->addOrderBy('subnum', 'ASC')->execute()->fetchAll();
                 // cache only if it's last_50
                 if ($last_limit == 50) {
                     $cache_time = 300;
                     if ($this->radix->archive) {
                         $cache_time = 30;
                         // over 7 days is old
                         $old = time() - 604800;
                         // set a very long cache time for archive threads older than a week, in case a ghost post will bump it
                         foreach ($query_result as $k => $r) {
                             if ($r['timestamp'] < $old) {
                                 $cache_time = 300;
                                 break;
                             }
                         }
                     }
                     Cache::item('foolslide.model.board.getThreadComments.last_50.' . md5(serialize([$this->radix->shortname, $num])))->set($query_result, $cache_time);
                 }
             }
             break;
         case 'thread':
             try {
                 $query_result = Cache::item('foolslide.model.board.getThreadComments.thread.' . md5(serialize([$this->radix->shortname, $num])))->get();
             } catch (\OutOfBoundsException $e) {
                 $query_result = $this->dc->qb()->select('*')->from($this->radix->getTable(), 'r')->leftJoin('r', $this->radix->getTable('_images'), 'mg', 'mg.media_id = r.media_id')->where('thread_num = :thread_num')->orderBy('num', 'ASC')->addOrderBy('subnum', 'ASC')->setParameter(':thread_num', $num)->execute()->fetchAll();
                 $cache_time = 300;
                 if ($this->radix->archive) {
                     $cache_time = 30;
                     // over 7 days is old
                     $old = time() - 604800;
                     // set a very long cache time for archive threads older than a week, in case a ghost post will bump it
                     foreach ($query_result as $k => $r) {
                         if ($r['timestamp'] < $old) {
                             $cache_time = 300;
                             break;
                         }
                     }
                 }
                 Cache::item('foolslide.model.board.getThreadComments.thread.' . md5(serialize([$this->radix->shortname, $num])))->set($query_result, $cache_time);
             }
             break;
     }
     if (!count($query_result) && isset($latest_doc_id)) {
         return $this->comments = $this->comments_unsorted = [];
     }
     if (!count($query_result)) {
         throw new BoardThreadNotFoundException(_i('There\'s no such a thread.'));
     }
     foreach ($query_result as $key => $row) {
         $data = new CommentBulk();
         $data->import($row, $this->radix);
         unset($query_result[$key]);
         $this->comments_unsorted[] = $data;
     }
     unset($query_result);
     foreach ($this->comments_unsorted as $key => $bulk) {
         if ($bulk->comment->op == 0) {
             $this->comments[$bulk->comment->thread_num]['posts'][$bulk->comment->num . ($bulk->comment->subnum == 0 ? '' : '_' . $bulk->comment->subnum)] =& $this->comments_unsorted[$key];
         } else {
             $this->comments[$bulk->comment->num]['op'] =& $this->comments_unsorted[$key];
         }
     }
     $this->profiler->logMem('Board $this->comments', $this->comments);
     $this->profiler->logMem('Board $this', $this);
     $this->profiler->log('Board::getThreadComments End');
     return $this;
 }
Beispiel #3
0
 /**
  * Puts the table in readily available variables
  */
 public function preload()
 {
     $this->profiler->log('Radix::preload Start');
     try {
         $result = Cache::item('foolfuuka.model.radix.preload')->get();
     } catch (\OutOfBoundsException $e) {
         $result = $this->dc->qb()->select('*')->from($this->dc->p('boards'), 'b')->orderBy('shortname', 'ASC')->execute()->fetchAll();
         Cache::item('foolfuuka.model.radix.preload')->set($result, 900);
     }
     if (!is_array($result) || empty($result)) {
         $this->preloaded_radixes = [];
         return false;
     }
     $result_object = [];
     foreach ($result as $item) {
         // don't process hidden boards
         if (!$this->getAuth()->hasAccess('boards.see_hidden') && $item['hidden'] == 1) {
             continue;
         }
         $structure = $this->structure($item);
         $result_object[$item['id']] = new Radix($this->getContext(), $this);
         // set the plain database data as keys
         foreach ($item as $k => $i) {
             $result_object[$item['id']]->{$k} = $i;
             // we set it also in the values so we can just use it from there as commodity
             $result_object[$item['id']]->setValue($k, $i);
         }
         // url values for commodity
         $result_object[$item['id']]->setValue('formatted_title', $item['name'] ? '/' . $item['shortname'] . '/ - ' . $item['name'] : '/' . $item['shortname'] . '/');
         // load the basic value of the preferences
         foreach ($structure as $key => $arr) {
             if (!isset($result_object[$item['id']]->{$key}) && isset($arr['boards_preferences'])) {
                 $result_object[$item['id']]->setValue($key, $this->config->get('foolz/foolfuuka', 'package', 'preferences.radix.' . $key, false));
             }
             foreach (['sub', 'sub_inverse'] as $sub) {
                 if (isset($arr[$sub])) {
                     foreach ($arr[$sub] as $k => $a) {
                         if (!isset($result_object[$item['id']]->{$k}) && isset($a['boards_preferences'])) {
                             $result_object[$item['id']]->setValue($k, $this->config->get('foolz/foolfuuka', 'package', 'preferences.radix.' . $k, false));
                         }
                     }
                 }
             }
         }
     }
     // load the preferences from the board_preferences table
     $this->profiler->log('Radix::load_preferences Start');
     try {
         $preferences = Cache::item('foolfuuka.model.radix.load_preferences')->get();
     } catch (\OutOfBoundsException $e) {
         $preferences = $this->dc->qb()->select('*')->from($this->dc->p('boards_preferences'), 'p')->execute()->fetchAll();
         Cache::item('foolfuuka.model.radix.load_preferences')->set($preferences, 900);
     }
     foreach ($preferences as $value) {
         // in case of leftover values, it would try instantiating a new stdClass and that would trigger error
         if (isset($result_object[$value['board_id']])) {
             $result_object[$value['board_id']]->setValue($value['name'], $value['value']);
         }
     }
     $this->preloaded_radixes = $result_object;
     $this->profiler->logMem('Radix $this->preloaded_radixes', $this->preloaded_radixes);
     $this->profiler->log('Radix::load_preferences End');
     // take them all and then filter/do whatever (we use this to split the boards through various subdomains)
     // only public is affected! admins and mods will see all boards at all the time
     $this->preloaded_radixes = \Foolz\Plugin\Hook::forge('Foolz\\Foolfuuka\\Model\\Radix::preload.result.public')->setObject($this)->setParam('preloaded_radixes', $this->preloaded_radixes)->execute()->get($this->preloaded_radixes);
     $this->profiler->log('Radix::preload End');
     $this->profiler->logMem('Radix $this->preloaded_radixes w/ preferences', $this->preloaded_radixes);
 }
Beispiel #4
0
 public function radix_search()
 {
     if ($this->getPost('submit_search_global')) {
         $this->radix = null;
     }
     $text = $this->getPost('text');
     if ($this->radix !== null && $this->getPost('submit_post')) {
         return $this->radix_post(str_replace(',', '_', $text));
     }
     $this->response = new StreamedResponse();
     // Check all allowed search modifiers and apply only these
     $modifiers = ['boards', 'subject', 'text', 'username', 'tripcode', 'email', 'filename', 'capcode', 'uid', 'image', 'deleted', 'ghost', 'type', 'filter', 'start', 'end', 'order', 'page'];
     if ($this->getAuth()->hasAccess('comment.see_ip')) {
         $modifiers[] = 'poster_ip';
         $modifiers[] = 'deletion_mode';
     }
     // GET -> URL Redirection to provide URL presentable for sharing links.
     if ($this->getPost()) {
         if ($this->radix !== null) {
             $redirect_url = [$this->radix->shortname, 'search'];
         } else {
             $redirect_url = ['_', 'search'];
         }
         foreach ($modifiers as $modifier) {
             if ($this->getPost($modifier)) {
                 if ($modifier === 'image') {
                     array_push($redirect_url, $modifier);
                     array_push($redirect_url, rawurlencode(Media::urlsafe_b64encode(Media::urlsafe_b64decode($this->getPost($modifier)))));
                 } elseif ($modifier === 'boards') {
                     if ($this->getPost('submit_search_global')) {
                     } elseif (count($this->getPost($modifier)) == 1) {
                         $boards = $this->getPost($modifier);
                         $redirect_url[0] = $boards[0];
                     } elseif (count($this->getPost($modifier)) > 1) {
                         $redirect_url[0] = '_';
                         // avoid setting this if we're just searching on all the boards
                         $sphinx_boards = [];
                         foreach ($this->radix_coll->getAll() as $k => $b) {
                             if ($b->sphinx) {
                                 $sphinx_boards[] = $b;
                             }
                         }
                         if (count($sphinx_boards) !== count($this->getPost($modifier))) {
                             array_push($redirect_url, $modifier);
                             array_push($redirect_url, rawurlencode(implode('.', $this->getPost($modifier))));
                         }
                     }
                 } else {
                     array_push($redirect_url, $modifier);
                     array_push($redirect_url, rawurlencode($this->getPost($modifier)));
                 }
             }
         }
         return new RedirectResponse($this->uri->create($redirect_url), 303);
     }
     $search = $this->uri->uri_to_assoc($this->request->getPathInfo(), 1, $modifiers);
     $this->param_manager->setParam('search', $search);
     // latest searches system
     if (!is_array($cookie_array = @json_decode($this->getCookie('search_latest_5'), true))) {
         $cookie_array = [];
     }
     // sanitize
     foreach ($cookie_array as $item) {
         // all subitems must be array, all must have 'board'
         if (!is_array($item) || !isset($item['board'])) {
             $cookie_array = [];
             break;
         }
     }
     $search_opts = array_filter($search);
     $search_opts['board'] = $this->radix !== null ? $this->radix->shortname : false;
     unset($search_opts['page']);
     // if it's already in the latest searches, remove the previous entry
     foreach ($cookie_array as $key => $item) {
         if ($item === $search_opts) {
             unset($cookie_array[$key]);
             break;
         }
     }
     // we don't want more than 5 entries for latest searches
     if (count($cookie_array) > 4) {
         array_pop($cookie_array);
     }
     array_unshift($cookie_array, $search_opts);
     $this->builder->getPartial('tools_search')->getParamManager()->setParam('latest_searches', $cookie_array);
     $this->response->headers->setCookie(new Cookie($this->getContext(), 'search_latest_5', json_encode($cookie_array), 60 * 60 * 24 * 30));
     foreach ($search as $key => $value) {
         if ($value !== null) {
             $search[$key] = trim(rawurldecode($value));
         }
     }
     if ($search['boards'] !== null) {
         $search['boards'] = explode('.', $search['boards']);
     }
     if ($search['image'] !== null) {
         $search['image'] = base64_encode(Media::urlsafe_b64decode($search['image']));
     }
     if ($this->getAuth()->hasAccess('comment.see_ip') && $search['poster_ip'] !== null) {
         if (!filter_var($search['poster_ip'], FILTER_VALIDATE_IP)) {
             return $this->error(_i('The poster IP you inserted is not a valid IP address.'));
         }
         $search['poster_ip'] = Inet::ptod($search['poster_ip']);
     }
     try {
         $board = Search::forge($this->getContext())->getSearch($search)->setRadix($this->radix)->setPage($search['page'] ? $search['page'] : 1);
         $board->getComments();
     } catch (\Foolz\Foolfuuka\Model\SearchException $e) {
         return $this->error($e->getMessage());
     } catch (\Foolz\Foolfuuka\Model\BoardException $e) {
         return $this->error($e->getMessage());
     } catch (\Foolz\SphinxQL\ConnectionException $e) {
         return $this->error($this->preferences->get('foolfuuka.sphinx.custom_message', 'It appears that the search engine is offline at the moment. Please try again later.'));
     }
     // Generate the $title with all search modifiers enabled.
     $title = [];
     if ($search['text']) {
         array_push($title, sprintf(_i('that contain &lsquo;%s&rsquo;'), e($search['text'])));
     }
     if ($search['subject']) {
         array_push($title, sprintf(_i('with the subject &lsquo;%s&rsquo;'), e($search['subject'])));
     }
     if ($search['username']) {
         array_push($title, sprintf(_i('with the username &lsquo;%s&rsquo;'), e($search['username'])));
     }
     if ($search['tripcode']) {
         array_push($title, sprintf(_i('with the tripcode &lsquo;%s&rsquo;'), e($search['tripcode'])));
     }
     if ($search['filename']) {
         array_push($title, sprintf(_i('with the filename &lsquo;%s&rsquo;'), e($search['filename'])));
     }
     if ($search['image']) {
         array_push($title, sprintf(_i('with the image hash &lsquo;%s&rsquo;'), e($search['image'])));
     }
     if ($search['deleted'] == 'deleted') {
         array_push($title, _i('that have been deleted'));
     }
     if ($search['deleted'] == 'not-deleted') {
         array_push($title, _i('that has not been deleted'));
     }
     if ($search['ghost'] == 'only') {
         array_push($title, _i('that are by ghosts'));
     }
     if ($search['ghost'] == 'none') {
         array_push($title, _i('that are not by ghosts'));
     }
     if ($search['type'] == 'sticky') {
         array_push($title, _i('that were stickied'));
     }
     if ($search['type'] == 'op') {
         array_push($title, _i('that are only OP posts'));
     }
     if ($search['type'] == 'posts') {
         array_push($title, _i('that are only non-OP posts'));
     }
     if ($search['filter'] == 'image') {
         array_push($title, _i('that do not contain images'));
     }
     if ($search['filter'] == 'text') {
         array_push($title, _i('that only contain images'));
     }
     if ($search['capcode'] == 'user') {
         array_push($title, _i('that were made by users'));
     }
     if ($search['capcode'] == 'mod') {
         array_push($title, _i('that were made by mods'));
     }
     if ($search['capcode'] == 'admin') {
         array_push($title, _i('that were made by admins'));
     }
     if ($search['start']) {
         array_push($title, sprintf(_i('posts after %s'), e($search['start'])));
     }
     if ($search['end']) {
         array_push($title, sprintf(_i('posts before %s'), e($search['end'])));
     }
     if ($search['order'] == 'asc') {
         array_push($title, _i('in ascending order'));
     }
     if (!empty($title)) {
         $title = sprintf(_i('Searching for posts %s.'), implode(' ' . _i('and') . ' ', $title));
     } else {
         $title = _i('Displaying all posts with no filters applied.');
     }
     if ($this->radix) {
         $this->builder->getProps()->addTitle($title);
     } else {
         $this->builder->getProps()->addTitle('Global Search &raquo; ' . $title);
     }
     if ($board->getSearchCount() > 5000) {
         $search_title = sprintf(_i('%s <small>Returning only first %d of %d results found.</small>', $title, $this->preferences->get('foolfuuka.sphinx.max_matches', 5000), $board->getSearchCount()));
     } else {
         $search_title = sprintf(_i('%s <small>%d results found.</small>', $title, $board->getSearchCount()));
     }
     $this->param_manager->setParam('section_title', $search_title);
     $main_partial = $this->builder->createPartial('body', 'board');
     $main_partial->getParamManager()->setParam('board', $board->getComments());
     $pagination = $search;
     unset($pagination['page']);
     $pagination_arr = [];
     $pagination_arr[] = $this->radix !== null ? $this->radix->shortname : '_';
     $pagination_arr[] = 'search';
     foreach ($pagination as $key => $item) {
         if ($item || $item === 0) {
             $pagination_arr[] = rawurlencode($key);
             if (is_array($item)) {
                 $item = implode('.', $item);
             }
             if ($key == 'poster_ip') {
                 $item = Inet::dtop($item);
             }
             $pagination_arr[] = rawurlencode($item);
         }
     }
     $pagination_arr[] = 'page';
     $this->param_manager->setParam('pagination', ['base_url' => $this->uri->create($pagination_arr), 'current_page' => $search['page'] ?: 1, 'total' => ceil($board->getCount() / 25)]);
     $this->param_manager->setParam('modifiers', ['post_show_board_name' => $this->radix === null, 'post_show_view_button' => true]);
     $this->profiler->logMem('Controller Chan $this', $this);
     $this->profiler->log('Controller Chan::search End');
     $this->response->setCallback(function () {
         $this->builder->stream();
     });
     return $this->response;
 }
Beispiel #5
0
 public function handleWeb(Request $request = null)
 {
     if ($request === null) {
         // create the request from the globals if we don't have custom input
         $request = Request::createFromGlobals();
     }
     $this->container->register('uri', '\\Foolz\\FoolFrame\\Model\\Uri')->addArgument($this)->addArgument($request);
     $remember_me = $request->cookies->get($this->config->get('foolz/foolframe', 'config', 'config.cookie_prefix') . 'rememberme');
     if (!count($this->child_contextes)) {
         // no app installed, we need to go to the install
         $this->loadInstallRoutes($this->route_collection);
     } else {
         $this->profiler->log('Start Auth rememberme');
         /** @var Auth $auth */
         $auth = $this->getService('auth');
         if ($remember_me) {
             try {
                 $auth->authenticateWithRememberMe($remember_me);
             } catch (WrongKeyException $e) {
             }
         }
         $this->profiler->log('Stop Auth rememberme');
         Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.afterAuth')->setObject($this)->setParam('route_collection', $this->route_collection)->execute();
         $this->profiler->log('Start Plugins handleWeb');
         $this->getService('plugins')->handleWeb();
         $this->profiler->log('Stop Plugins handleWeb');
         $this->profiler->log('Start language setup');
         $available_langs = $this->config->get('foolz/foolframe', 'package', 'preferences.lang.available');
         $lang = $request->cookies->get('language');
         if (!$lang || !array_key_exists($lang, $available_langs)) {
             $lang = $this->preferences->get('foolframe.lang.default');
         }
         // HHVM does not support gettext
         if (function_exists('bindtextdomain')) {
             $locale = $lang . '.utf8';
             putenv('LANG=' . $locale);
             putenv('LANGUAGE=' . $locale);
             setlocale(LC_ALL, $locale);
             bindtextdomain($lang, DOCROOT . 'assets/locale');
             bind_textdomain_codeset($lang, 'UTF-8');
             textdomain($lang);
         }
         $this->profiler->log('Stop language setup');
         $this->profiler->log('Start routes setup');
         // load the routes from the child contextes first
         Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.routing')->setObject($this)->setParam('route_collection', $this->route_collection)->execute();
         foreach ($this->child_contextes as $context) {
             $context->handleWeb($request);
             $context->loadRoutes($this->route_collection);
         }
         $this->profiler->log('Stop routes setup');
         $this->profiler->log('Start routes load');
         $this->loadRoutes($this->route_collection);
         $this->profiler->log('Stop routes setup');
     }
     // load the framework routes
     Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.context')->setObject($this)->execute();
     // this is the first time we know we have a request for sure
     // hooks that need the request to function must run here
     Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.request')->setObject($this)->setParam('request', $request)->execute();
     $this->container->register('notices', 'Foolz\\FoolFrame\\Model\\Notices')->addArgument($this)->addArgument($request);
     $this->profiler->log('Start HttpKernel loading');
     $request_context = new RequestContext();
     $request_context->fromRequest($request);
     $matcher = new UrlMatcher($this->route_collection, $request_context);
     $resolver = new ControllerResolver($this);
     $dispatcher = new EventDispatcher();
     $dispatcher->addSubscriber(new RouterListener($matcher, null, $this->logger));
     $dispatcher->addSubscriber(new ResponseListener('UTF-8'));
     $this->http_kernel = new HttpKernel($dispatcher, $resolver);
     $this->profiler->log('End HttpKernel loading');
     // if this hook is used, it can override the entirety of the request handling
     $response = Hook::forge('Foolz\\FoolFrame\\Model\\Context::handleWeb#obj.response')->setObject($this)->setParam('request', $request)->execute()->get(false);
     if (!$response) {
         try {
             $this->profiler->log('Request handling start');
             $response = $this->http_kernel->handle($request);
             $this->profiler->log('Request handling end');
         } catch (NotFoundHttpException $e) {
             $controller_404 = $this->route_collection->get('404')->getDefault('_controller');
             $request = new Request();
             $request->attributes->add(['_controller' => $controller_404]);
             $response = $this->http_kernel->handle($request);
         }
         // stick the html of the profiler at the end
         if ($request->getRequestFormat() == 'html' && isset($auth) && $auth->hasAccess('maccess.admin')) {
             $content = explode('</body>', $response->getContent());
             if (count($content) == 2) {
                 $this->profiler->log('Execution end');
                 $response->setContent($content[0] . $this->profiler->getHtml() . '</body>' . $content[1]);
             }
         }
     }
     $this->getService('security')->updateCsrfToken($response);
     $response->send();
 }
Beispiel #6
0
 public function stopQuery()
 {
     $this->profiler->logStop('Doctrine');
 }