예제 #1
0
 public function replacePlaceholders(&$content)
 {
     $this->fetchPhrases();
     $placeholders = array();
     end($this->stack);
     while (!is_null($placeholder_id = key($this->stack))) {
         $phraseName = current($this->stack);
         $phraseInfo = $this->pending[$phraseName][$placeholder_id];
         $phraseInfo[0] = isset($this->cache[$phraseName]) ? $this->cache[$phraseName] : $phraseInfo[0];
         // do parameter replacements in phrases for notices, since we don't want
         // the extra overhead of pulling these phrases in the api method
         if (strpos($phraseName, 'notice_') === 0 and preg_match('/^notice_[0-9]+_html$/', $phraseName)) {
             $phraseInfo[0] = str_replace(array('{musername}', '{username}', '{userid}', '{sessionurl}', '{sessionurl_q}', '{register_page}', '{help_page}'), array(vB5_User::get('musername'), vB5_User::get('username'), vB5_User::get('userid'), vB::getCurrentSession()->get('sessionurl'), vB::getCurrentSession()->get('sessionurl_q'), vB5_Template_Runtime::buildUrl('register'), vB5_Template_Runtime::buildUrl('help')), $phraseInfo[0]);
         }
         $replace = $this->constructPhraseFromArray($phraseInfo);
         $placeholders[$placeholder_id] = $replace;
         //$content = str_replace($placeholder_id, $replace, $content);
         prev($this->stack);
     }
     // If we passed any phrases as parameters to other phrases, we will
     // still have those placeholders in the "replace" content, for example:
     //   {vb:phrase have_x_posts_in_topic_last_y, {vb:var topic.dot_postcount}, {vb:date {vb:var topic.dot_lastpostdate}}}
     // since the date call can return phrases (today, yesterday, etc.).
     // This only goes one level deep (e.g., it's not recursive), since that's
     // all we need at this time.
     // This searches the replace text to see if there are any placeholders
     // left in them, and if so, replaces those placeholders with the phrase text.
     foreach ($placeholders as $k => $replace) {
         if (strpos($replace, '<!-- ##phrase_') !== false or strpos($replace, '&lt;!-- ##phrase_') !== false) {
             if (preg_match_all('/(?:<|&lt;)!-- ##phrase_([a-z0-9_]+)_[0-9]+## --(?:>|&gt;)/siU', $replace, $matches, PREG_SET_ORDER)) {
                 foreach ($matches as $match) {
                     $placeholder_id = $match[0];
                     $phrase_varname = $match[1];
                     $placeholder_id_lookup = str_replace(array('&lt;', '&gt;'), array('<', '>'), $placeholder_id);
                     $phraseInfo = $this->pending[$phrase_varname][$placeholder_id_lookup];
                     $phraseInfo[0] = isset($this->cache[$phrase_varname]) ? $this->cache[$phrase_varname] : $phraseInfo[0];
                     $phraseText = $this->constructPhraseFromArray($phraseInfo);
                     $placeholders[$k] = str_replace($placeholder_id, $phraseText, $placeholders[$k]);
                 }
             }
         }
     }
     if (!empty($placeholders)) {
         $content = str_replace(array_keys($placeholders), $placeholders, $content);
     }
 }
예제 #2
0
 public function __construct($appendCustomTags = true)
 {
     $this->setStripSpace(false);
     parent::__construct($appendCustomTags);
     if (!empty(self::$customTags['no_option'])) {
         foreach (self::$customTags['no_option'] as $tagname => $taginfo) {
             if (!isset($this->unparsed_tags[$tagname])) {
                 $this->unparsed_tags[$tagname] = $tagname;
             }
         }
     }
     if (!empty(self::$customTags['option'])) {
         foreach (self::$customTags['option'] as $tagname => $taginfo) {
             if (!isset($this->unparsed_tags[$tagname])) {
                 $this->unparsed_tags[$tagname] = $tagname;
             }
         }
     }
     // change all unparsable tags to use the unparsable callback
     foreach ($this->unparsed_tags as $remove) {
         if (isset($this->tag_list['option']["{$remove}"])) {
             $this->tag_list['option']["{$remove}"]['callback'] = 'handle_wysiwyg_unparsable';
             unset($this->tag_list['option']["{$remove}"]['html'], $this->tag_list['option']["{$remove}"]['strip_space_after']);
         }
         if (isset($this->tag_list['no_option']["{$remove}"])) {
             $this->tag_list['no_option']["{$remove}"]['callback'] = 'handle_wysiwyg_unparsable';
             unset($this->tag_list['no_option']["{$remove}"]['html'], $this->tag_list['option']["{$remove}"]['strip_space_after']);
         }
     }
     // make the "pre" tags use the correct handler
     foreach (array('code', 'php', 'html') as $pre_tag) {
         if (isset($this->tag_list['no_option']["{$pre_tag}"])) {
             $this->tag_list['no_option']["{$pre_tag}"]['callback'] = 'handle_preformatted_tag';
             unset($this->tag_list['no_option']["{$pre_tag}"]['html'], $this->tag_list['option']["{$pre_tag}"]['strip_space_after']);
         }
     }
     $this->type = vB5_Template_Runtime::isBrowser('ie') ? 'ie' : 'moz_css';
 }
예제 #3
0
 protected function renderPostNoticeTemplate($phrase_name, $data = array())
 {
     /*
     			Template display_threadview_post_notice only supports single phrase var atm.
     			If we need to support variable phrase var, we either need a vb:var_array or
     			use vb:raw on the phrase_var parameter and investigate whether allowing
     			vb:raw there is safe, and html-escape any URLs used in html (nextpageurl).
     */
     $template_name = 'display_threadview_post_notice';
     switch ($phrase_name) {
         case 'new_replies_since_x':
             $phrase_var = vB5_Template_Runtime::time($data['timestamp']);
             break;
         case 'replies_below_on_next_page':
             $phrase_var = $data['nextpageurl'];
             break;
         case 'more_replies_after_current_page':
             $phrase_var = $data['nextpageurl'];
             break;
         default:
             return;
             break;
     }
     $templater = new vB5_Template($template_name);
     $templater->register('phrase_name', $phrase_name);
     $templater->register('phrase_var', $phrase_var);
     return $templater->render(true, true);
 }
예제 #4
0
 /** Responds to a request to create a new user.
  *
  **/
 public function actionRegistration()
 {
     //We need at least a username, email, and password.
     if (empty($_REQUEST['username']) or empty($_REQUEST['password']) or empty($_REQUEST['email'])) {
         $this->sendAsJson(array('error' => 'insufficient data'));
         return;
     }
     $username = trim($_REQUEST['username']);
     $password = trim($_REQUEST['password']);
     $postdata = array('username' => $username, 'email' => $_REQUEST['email']);
     if (isset($_REQUEST['month']) and isset($_REQUEST['day']) and !empty($_REQUEST['year'])) {
         $postdata['birthday'] = $_REQUEST['year'] . '-' . str_pad($_REQUEST['month'], 2, '0', STR_PAD_LEFT) . '-' . str_pad($_REQUEST['day'], 2, '0', STR_PAD_LEFT);
     }
     if (!empty($_REQUEST['guardian'])) {
         $postdata['parentemail'] = $_REQUEST['guardian'];
     }
     $vboptions = vB5_Template_Options::instance()->getOptions();
     $vboptions = $vboptions['options'];
     // Coppa cookie check
     $coppaage = vB5_Cookie::get('coppaage', vB5_Cookie::TYPE_STRING);
     if ($vboptions['usecoppa'] and $vboptions['checkcoppa']) {
         if ($coppaage) {
             $dob = explode('-', $coppaage);
             $month = $dob[0];
             $day = $dob[1];
             $year = $dob[2];
             $postdata['birthday'] = $year . '-' . str_pad($month, 2, '0', STR_PAD_LEFT) . '-' . str_pad($day, 2, '0', STR_PAD_LEFT);
         } else {
             vB5_Cookie::set('coppaage', $_REQUEST['month'] . '-' . $_REQUEST['day'] . '-' . $_REQUEST['year'], 365, 0);
         }
     }
     // Fill in ReCaptcha data
     $recaptchaData = array();
     if (!empty($_REQUEST['recaptcha_challenge_field'])) {
         $recaptchaData['recaptcha_challenge_field'] = $_REQUEST['recaptcha_challenge_field'];
     }
     if (!empty($_REQUEST['recaptcha_response_field'])) {
         $recaptchaData['recaptcha_response_field'] = $_REQUEST['recaptcha_response_field'];
     }
     if (!empty($recaptchaData)) {
         $_REQUEST['humanverify'] = $recaptchaData + (isset($_REQUEST['humanverify']) ? (array) $_REQUEST['humanverify'] : array());
     }
     $api = Api_InterfaceAbstract::instance();
     $data = array('userid' => 0, 'password' => $password, 'user' => $postdata, array(), array(), 'userfield' => !empty($_REQUEST['userfield']) ? $_REQUEST['userfield'] : false, array(), isset($_REQUEST['humanverify']) ? $_REQUEST['humanverify'] : '', array('registration' => true));
     // add facebook data
     if ($api->callApi('facebook', 'isFacebookEnabled') && $api->callApi('facebook', 'userIsLoggedIn')) {
         $fbUserInfo = $api->callApi('facebook', 'getFbUserInfo');
         $data['user']['fbuserid'] = $fbUserInfo['id'];
         $data['user']['fbname'] = $fbUserInfo['name'];
         $data['user']['timezoneoffset'] = $fbUserInfo['timezone'];
         $data['user']['fbjoindate'] = time();
         $fb_profilefield_info = $this->getFacebookProfileinfo($fbUserInfo);
         if (!empty($fb_profilefield_info['birthday']) and empty($data['user']['birthday'])) {
             $data['user']['birthday'] = $fb_profilefield_info['birthday'];
         }
         if (empty($data['userfield'])) {
             $data['userfield'] = array();
         }
         if ($vboptions['fb_userfield_biography']) {
             $data['userfield'] += array($vboptions['fb_userfield_biography'] => $fb_profilefield_info['biography']);
         }
         if ($vboptions['fb_userfield_location']) {
             $data['userfield'] += array($vboptions['fb_userfield_location'] => $fb_profilefield_info['location']);
         }
         if ($vboptions['fb_userfield_occupation']) {
             $data['userfield'] += array($vboptions['fb_userfield_occupation'] => $fb_profilefield_info['occupation']);
         }
     }
     // save data
     $response = $api->callApi('user', 'save', $data);
     if (!empty($response) and (!is_array($response) or !isset($response['errors']))) {
         // try to login
         $loginInfo = $api->callApi('user', 'login', array($username, $password, '', '', ''));
         if (!isset($loginInfo['errors']) or empty($loginInfo['errors'])) {
             // browser session expiration
             vB5_Cookie::set('sessionhash', $loginInfo['sessionhash'], 0, true);
             vB5_Cookie::set('password', $loginInfo['password'], 0);
             vB5_Cookie::set('userid', $loginInfo['userid'], 0);
             $urlPath = '';
             if (!empty($_POST['urlpath'])) {
                 $urlPath = base64_decode(trim($_POST['urlpath']), true);
             }
             if (!$urlPath or strpos($urlPath, '/auth/') !== false or strpos($urlPath, '/register') !== false or !vB5_Template_Runtime::allowRedirectToUrl($urlPath)) {
                 $urlPath = vB5_Template_Options::instance()->get('options.frontendurl');
             }
             $response = array('urlPath' => $urlPath);
         } else {
             if (!empty($loginInfo['errors'])) {
                 $response = array('errors' => $loginInfo['errors']);
             }
         }
         if ($api->callApi('user', 'usecoppa')) {
             $response['usecoppa'] = true;
             $response['urlPath'] = vB5_Route::buildUrl('coppa-form|bburl');
         } else {
             if ($vboptions['verifyemail']) {
                 $response['msg'] = 'registeremail';
                 $response['msg_params'] = array(vB5_String::htmlSpecialCharsUni($postdata['username']), $postdata['email'], vB5_Template_Options::instance()->get('options.frontendurl'));
             } else {
                 if ($vboptions['moderatenewmembers']) {
                     $response['msg'] = 'moderateuser';
                     $response['msg_params'] = array(vB5_String::htmlSpecialCharsUni($postdata['username']), vB5_Template_Options::instance()->get('options.frontendurl'));
                 } else {
                     $frontendurl = vB5_Template_Options::instance()->get('options.frontendurl');
                     $routeProfile = $api->callApi('route', 'getUrl', array('route' => 'profile', 'data' => array('userid' => $loginInfo['userid']), array()));
                     $routeuserSettings = $api->callApi('route', 'getUrl', array('route' => 'settings', 'data' => array('tab' => 'profile'), array()));
                     $routeAccount = $api->callApi('route', 'getUrl', array('route' => 'settings', 'data' => array('tab' => 'account'), array()));
                     $response['msg'] = 'registration_complete';
                     $response['msg_params'] = array(vB5_String::htmlSpecialCharsUni($postdata['username']), $frontendurl . $routeProfile, $frontendurl . $routeAccount, $frontendurl . $routeuserSettings, $frontendurl);
                 }
             }
         }
     }
     $this->sendAsJson(array('response' => $response));
 }
예제 #5
0
 /**
  * This is a temporary function used to get the stylevar 'charset' (added for presentation).
  *
  * @return string, stylevar charset value
  */
 public static function getTempCharset()
 {
     // first check for user info
     $encoding = vB5_User::get('lang_charset');
     if (!$encoding) {
         //todo: we don't have a charset variable, although users can add one.
         $encoding = vB5_Template_Runtime::fetchStyleVar('charset');
     }
     return strtoupper($encoding);
 }
예제 #6
0
 /**
  * Appends the non-inline attachment UI to the passed $text
  *
  * @param	string	Text to append attachments
  * @param	array	Attachment data
  * @param	bool	Whether to show images
  * @param	array	Array of nodeid => (nodeid, filedataid) attachments that should not be included in the attachment box.
  */
 public function append_noninline_attachments($text, $attachments, $do_imgcode = false, $skiptheseattachments = array())
 {
     foreach ($skiptheseattachments as $nodeid => $arr) {
         unset($attachments[$nodeid]);
     }
     if (!empty($attachments)) {
         foreach ($attachments as &$attachment) {
             $attachment['filesize'] = !empty($attachment['filesize']) ? vb_number_format($attachment['filesize'], 1, true) : 0;
         }
         $attach_url = vB5_Template_Options::instance()->get('options.frontendurl') . "/filedata/fetch?id=";
         if ($this->renderImmediate) {
             $text .= vB5_Template::staticRender('bbcode_attachment_list', array('attachments' => $attachments, 'attachurl' => $attach_url), false);
         } else {
             $text .= vB5_Template_Runtime::includeTemplate('bbcode_attachment_list', array('attachments' => $attachments, 'attachurl' => $attach_url));
         }
     }
     return $text;
 }
예제 #7
0
 /**
  * Inserts <link>s for CSS in the content
  *
  * @param	string	The content
  * @param	boolean	true if we are rendering for a call to /ajax/render/ and we want CSS <link>s separate
  */
 public function insertCss(&$content, $isAjaxTemplateRender)
 {
     // register block css templates for blocks that are used in the markup
     $this->registerBlockCssTemplates($content);
     if (empty($this->pending)) {
         return;
     }
     $options = vB5_Template_Options::instance();
     $storecssasfile = $options->get('options.storecssasfile');
     $cssdate = intval($options->get('miscoptions.cssdate'));
     if (!$cssdate) {
         $cssdate = time();
         // fallback so we get the latest css
     }
     $user = vB5_User::instance();
     $textdirection = $user['lang_options']['direction'] ? 'ltr' : 'rtl';
     // we cannot query user directly for styleid, we need to consider other parameters
     $styleid = vB5_Template_Stylevar::instance()->getPreferredStyleId();
     $vbcsspath = $this->getCssPath($storecssasfile, $textdirection, $styleid);
     // Used when css is stored as files
     if ($storecssasfile) {
         $cssfiledate = $this->getCssFileDate($options, $styleid);
     }
     // some css files need to be loaded always from DB
     $vbcssdbpath = $this->getCssPath(false, $textdirection, $styleid);
     $replace = '';
     $replaceAjax = array();
     //if user style customization is enabled we need to hand css_profile specially. It can never come from disk
     //regardless of the option setting.
     $userprofilecss = '';
     $userprofilecssAjax = '';
     // Search for css_additional.css and css_profile.css files, send them to the last in that order (VBV-8781)
     $additionalToQueue = '';
     $profileToQueue = '';
     foreach ($this->pending as $key => $css) {
         if ($css === 'css_additional.css') {
             $additionalToQueue = $css;
             unset($this->pending[$key]);
             continue;
         }
         if (substr($css, 0, 15) === 'css_profile.css') {
             if ($options->get('options.enable_profile_styling')) {
                 $joinChar = strpos($vbcssdbpath . $css, '?') === false ? '?' : '&amp;';
                 $userprofilecss = '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($vbcssdbpath . $css) . "{$joinChar}ts={$cssdate} \" />\n";
                 $userprofilecssAjax = htmlspecialchars($vbcssdbpath . $css) . "{$joinChar}ts={$cssdate}";
                 unset($this->pending[$key]);
             } else {
                 $profileToQueue = $css;
                 unset($this->pending[$key]);
             }
         }
     }
     if (!empty($additionalToQueue)) {
         $this->pending[] = $additionalToQueue;
     }
     if (!empty($profileToQueue)) {
         $this->pending[] = $profileToQueue;
     }
     if ($storecssasfile) {
         foreach ($this->pending as $css) {
             $cssfile = $vbcsspath . $cssfiledate . '-' . $css;
             $replace .= '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($cssfile) . "\" />\n";
             $replaceAjax[] = htmlspecialchars($cssfile);
         }
     } else {
         // Deconstruct bundle logic
         if ($this->cssBundles == null) {
             $this->loadCSSBundles();
         }
         $joinChar = strpos($vbcsspath, '?') === false ? '?' : '&amp;';
         $templates = array();
         //for dupe checking
         $ieLinks = '';
         $nonIeLinks = '';
         $ieLinksAjax = array();
         $nonIeLinksAjax = array();
         // We're using css bunldes instead of combining everything into a single css.php call
         // to take advantage of client side caching. We're also incoporating the rollup system into
         // css files stored on the db by linking css.php with all the templates of that bundle in one call.
         // And we're also avoiding single templates having their own <link> tag if they're already used
         // in a bundle or elsewhere.
         foreach ($this->pending as $bundle) {
             if (isset($this->cssBundles[$bundle])) {
                 $templates = array_merge($templates, $this->cssBundles[$bundle]);
                 // Output the stylesheets twice-- once for IE, once for the rest.
                 // For IE, we split into groups of 5 so we don't exceed IE's limit
                 // on the number of CSS rules in a file. See VBV-7077
                 $pendingChunks = array_chunk($this->cssBundles[$bundle], 5);
                 foreach ($pendingChunks as $pendingSheets) {
                     $ieLinks .= '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($vbcsspath . implode(',', $pendingSheets)) . "{$joinChar}ts={$cssdate} \" />\n";
                     $ieLinksAjax[] = htmlspecialchars($vbcsspath . implode(',', $pendingSheets)) . "{$joinChar}ts={$cssdate}";
                 }
                 $nonIeLinks .= '<link rel="stylesheet" type="text/css" href="' . htmlspecialchars($vbcsspath . implode(',', $this->cssBundles[$bundle])) . "{$joinChar}ts={$cssdate} \" />\n";
                 $nonIeLinksAjax[] = htmlspecialchars($vbcsspath . implode(',', $this->cssBundles[$bundle])) . "{$joinChar}ts={$cssdate}";
             } else {
                 if (!in_array($bundle, $templates)) {
                     //mark additional css for JS processing.
                     $mark = ' ';
                     if ($bundle == 'css_additional.css') {
                         $mark = ' class="js-additional-css" ';
                     }
                     // we have a single template. that wasn't caught before. link it.
                     $templates[] = $bundle;
                     $link = '<link' . $mark . 'rel="stylesheet" type="text/css" href="' . htmlspecialchars($vbcsspath . $bundle) . "{$joinChar}ts={$cssdate} \" />\n";
                     $ieLinks .= $link;
                     $nonIeLinks .= $link;
                     $ieLinksAjax[] = htmlspecialchars($vbcsspath . $bundle) . "{$joinChar}ts={$cssdate}";
                     $nonIeLinksAjax[] = htmlspecialchars($vbcsspath . $bundle) . "{$joinChar}ts={$cssdate}";
                 }
             }
         }
         unset($templates);
         $replace .= "\n<!--[if IE]>\n";
         $replace .= $ieLinks;
         $replace .= "<![endif]-->\n<!--[if !IE]><!-->\n";
         $replace .= $nonIeLinks;
         $replace .= "<!--<![endif]-->\n";
         if (vB5_Template_Runtime::isBrowser('ie')) {
             $replaceAjax = array_merge($replaceAjax, $ieLinksAjax);
         } else {
             $replaceAjax = array_merge($replaceAjax, $nonIeLinksAjax);
         }
     }
     // Note: This places user profile customized css after css_additional.css.
     $replace .= $userprofilecss . "\n";
     if ($userprofilecssAjax) {
         $replaceAjax[] = $userprofilecssAjax;
     }
     if (!$isAjaxTemplateRender) {
         // insert the css before the first <script> tag in head element
         // if there is no script tag in <head>, then insert it at the
         // end of <head>
         $scriptPos = stripos($content, '<script');
         $headPos = stripos($content, '</head>');
         if ($scriptPos !== false && $scriptPos < ($headPos === false ? PHP_INT_MAX : $headPos)) {
             $top = substr($content, 0, $scriptPos);
             $bottom = substr($content, $scriptPos);
             $content = $top . $replace . $bottom;
         } else {
             if ($headPos !== false) {
                 $replace .= '</head>';
                 $content = str_replace('</head>', $replace, $content);
             }
         }
     } else {
         // We can't use the CDN URL for these, since they will be fetched via AJAX;
         // fall back to the local URL. VBV-8960
         $cdnurl = $options->get('options.cdnurl');
         if ($cdnurl) {
             $baseurl = vB5_Template_Options::instance()->get('options.frontendurl');
             $cdnurllen = strlen($cdnurl);
             foreach ($replaceAjax as $key => $url) {
                 $replaceAjax[$key] = $baseurl . substr($url, $cdnurllen);
             }
         }
         $this->ajaxCssLinks = array_unique(array_merge($this->ajaxCssLinks, $replaceAjax));
     }
 }
예제 #8
0
 function actionResult()
 {
     //the api init can redirect.  We need to make sure that happens before we echo anything
     $api = Api_InterfaceAbstract::instance();
     $top = '';
     if (vB5_Request::get('cachePageForGuestTime') > 0 and !vB5_User::get('userid')) {
         $fullPageKey = md5(serialize($_REQUEST));
         $fullPage = vB_Cache::instance()->read($fullPageKey);
         if (!empty($fullPage)) {
             echo $fullPage;
             exit;
         }
     }
     $preheader = vB5_ApplicationAbstract::getPreheader();
     $top .= $preheader;
     if (vB5_Request::get('useEarlyFlush')) {
         echo $preheader;
         flush();
     }
     $serverData = array_merge($_GET, $_POST);
     $router = vB5_ApplicationAbstract::instance()->getRouter();
     $arguments = $router->getArguments();
     $userAction = $router->getUserAction();
     if (!empty($userAction)) {
         $api->callApi('wol', 'register', array($userAction['action'], $userAction['params']));
     }
     // if Human verification is required, and we don't have 'q' set in serverData (means the user is using
     // the quick search box), we redirect user to advanced search page with HV
     $requirehv = $api->callApi('hv', 'fetchRequireHvcheck', array('search'));
     if (!empty($serverData['AdvSearch']) or $requirehv and isset($serverData['q'])) {
         $adv_search = $api->callApi('route', 'getRoute', array('pathInfo' => 'advanced_search', 'queryString' => ''), true);
         $arguments = $adv_search['arguments'];
     } elseif ($requirehv) {
         // Advanced search form submitted
         if (empty($serverData['humanverify'])) {
             $serverData['humanverify'] = array();
         }
         $return = $api->callApi('hv', 'verifyToken', array($serverData['humanverify'], 'search'));
         if ($return !== true) {
             $adv_search = $api->callApi('route', 'getRoute', array('pathInfo' => 'advanced_search', 'queryString' => ''), true);
             $arguments = $adv_search['arguments'];
             $error = $return['errors'][0][0];
         }
     }
     $pageid = (int) (isset($arguments['pageid']) ? $arguments['pageid'] : $arguments['contentid']);
     $page = $api->callApi('page', 'fetchPageById', array($pageid, $arguments));
     if (!$page) {
         echo 'Could not find page.';
         exit;
     }
     $phrases = $api->callApi('phrase', 'fetch', array(array('advanced_search', 'search_results')));
     $page['crumbs'] = array(0 => array('title' => $phrases['advanced_search'], 'url' => vB5_Template_Runtime::buildUrl('advanced_search', array(), array(), array('noBaseUrl' => true))), 1 => array('title' => $phrases['search_results'], 'url' => ''));
     // avoid search page itself being indexed
     $page['noindex'] = 1;
     if (!empty($serverData['cookie'])) {
         $serverData['searchJSON'] = '{"specific":[' . $_COOKIE[$serverData['cookie']] . ']}';
     }
     if (!empty($serverData['searchJSON'])) {
         if (is_string($serverData['searchJSON'])) {
             if (preg_match('/[^\\x00-\\x7F]/', $serverData['searchJSON'])) {
                 $serverData['searchJSON'] = vB5_String::toUtf8($serverData['searchJSON'], vB5_String::getTempCharset());
             }
             $serverData['searchJSON'] = json_decode($serverData['searchJSON'], true);
         }
         if (!empty($serverData['searchJSON'])) {
             if (!empty($serverData['searchJSON']['keywords'])) {
                 $serverData['searchJSON']['keywords'] = str_replace(array('"', '\\'), '', $serverData['searchJSON']['keywords']);
                 $serverData['searchJSON']['keywords'] = filter_var($serverData['searchJSON']['keywords'], FILTER_SANITIZE_STRING);
             }
             $serverData['searchJSON'] = json_encode($serverData['searchJSON']);
         } else {
             $serverData['searchJSON'] = '';
         }
         $page['searchJSON'] = $serverData['searchJSON'];
         $extra = array('searchJSON' => !empty($serverData['searchJSON']) ? $serverData['searchJSON'] : '{}');
         if (!empty($serverData['AdvSearch'])) {
             $extra['AdvSearch'] = 1;
         }
         $page['url'] = str_replace('&amp;', '&', vB5_Route::buildUrl('search', array(), $extra));
         //$page['searchJSONStructure'] = json_decode($page['searchJSON'],true);
         $page['crumbs'][0]['url'] = vB5_Template_Runtime::buildUrl('advanced_search', array(), array('searchJSON' => $page['searchJSON']), array('noBaseUrl' => true));
     } elseif (!empty($serverData['q'])) {
         $serverData['q'] = str_replace(array('"', '\\'), '', $serverData['q']);
         $serverData['q'] = filter_var($serverData['q'], FILTER_SANITIZE_STRING);
         $searchType = '';
         if (!empty($serverData['type'])) {
             $serverData['type'] = str_replace(array('"', '\\'), '', $serverData['type']);
             $serverData['type'] = filter_var($serverData['type'], FILTER_SANITIZE_STRING);
             $searchType = ',"type":"' . $serverData['type'] . '"';
         }
         $page['searchJSON'] = '{"keywords":"' . $serverData['q'] . '","sort":"title"' . $searchType . '}';
         $extra = array('q' => $serverData['q']);
         if (!empty($serverData['AdvSearch'])) {
             $extra['AdvSearch'] = 1;
         }
         $page['url'] = str_replace('&amp;', '&', vB5_Route::buildUrl('search', array(), $extra));
         $page['searchStr'] = $serverData['q'];
         $page['crumbs'][0]['url'] = vB5_Template_Runtime::buildUrl('advanced_search', array(''), array('searchJSON' => $page['searchJSON']), array('noBaseUrl' => true));
     } elseif (!empty($serverData['r'])) {
         unset($page['crumbs'][0]);
         $page['url'] = str_replace('&amp;', '&', vB5_Route::buildUrl('search', array(), array('r' => $serverData['r'])));
         $page['resultId'] = $serverData['r'];
         if (!empty($serverData['p']) && is_numeric($serverData['p'])) {
             $page['currentPage'] = intval($serverData['p']);
         }
         $page['crumbs'][0]['url'] = vB5_Template_Runtime::buildUrl('advanced_search', array(), array('r' => $serverData['r']), array('noBaseUrl' => true));
     } else {
         return $this->actionIndex();
     }
     $page['ignore_np_notices'] = vB5_ApplicationAbstract::getIgnoreNPNotices();
     if (!empty($error)) {
         $page['error'] = $error;
     }
     $templater = new vB5_Template($page['screenlayouttemplate']);
     $templater->registerGlobal('page', $page);
     $page = $this->outputPage($templater->render(), false);
     $fullPage = $top . $page;
     if (vB5_Request::get('cachePageForGuestTime') > 0 and !vB5_User::get('userid')) {
         vB_Cache::instance()->write($fullPageKey, $fullPage, vB5_Request::get('cachePageForGuestTime'));
     }
     if (!vB5_Request::get('useEarlyFlush')) {
         echo $fullPage;
     } else {
         echo $page;
     }
 }