protected function fetchNodeText()
 {
     if (!empty($this->placeHolders)) {
         // first try with cache
         $api = Api_InterfaceAbstract::instance();
         $cache = $api->cacheInstance(0);
         $found = $cache->read(array_keys($this->placeHolders));
         if (!empty($found)) {
             $foundValues = array();
             foreach ($found as $cacheKey => $parsedText) {
                 if ($parsedText !== false and !empty($this->cacheIdToNodeid[$cacheKey])) {
                     $nodeId = $this->cacheIdToNodeid[$cacheKey];
                     $placeHolder = $this->placeHolders[$cacheKey];
                     $this->cache[$placeHolder] = $parsedText;
                     unset($this->placeHolders[$cacheKey]);
                     unset($this->pending[$placeHolder]);
                 }
             }
         }
         if (!empty($this->pending)) {
             // we still have to parse some nodes, fetch data for them
             $textDataArray = Api_InterfaceAbstract::instance()->callApi('content_text', 'getDataForParse', array($this->pending));
             $templateCache = vB5_Template_Cache::instance();
             $phraseCache = vB5_Template_Phrase::instance();
             $urlCache = vB5_Template_Url::instance();
             // In BBCode parser, the templates of inner BBCode are registered first,
             // so they should be replaced after the outer BBCode templates. See VBV-4834.
             //Also- if we have a preview we're likely to need the full text, and vice versa. So if either is requested
             // let's parse both.
             $templateCache->setRenderTemplatesInReverseOrder(true);
             if (empty($this->previewLength)) {
                 $options = Api_InterfaceAbstract::instance()->callApiStatic('options', 'fetchStatic', array('previewLength'));
                 $this->previewLength = $options['previewLength'];
             }
             foreach ($this->placeHolders as $cacheKey => $placeHolder) {
                 $nodeId = isset($this->pending[$placeHolder]) ? $this->pending[$placeHolder] : 0;
                 if ($nodeId and !empty($textDataArray[$nodeId])) {
                     //If we got previewtext in textDataArray, we are done.
                     if (isset($textDataArray[$nodeId]['preview_only'])) {
                         $previewText = $parsed = $textDataArray[$nodeId]['previewtext'];
                         $canview = false;
                     } else {
                         $canview = true;
                         list($previewText, $parsed) = $this->parseNode($textDataArray, $nodeId, $this->bbCodeOptions[$placeHolder]);
                         // It's safe to do it here cause we already are in delayed rendering.
                         $templateCache->replacePlaceholders($parsed);
                         $phraseCache->replacePlaceholders($parsed);
                         $urlCache->replacePlaceholders($parsed);
                         // also need to replace phrase & url placeholders for preview text
                         $phraseCache->replacePlaceholders($previewText);
                         $urlCache->replacePlaceholders($previewText);
                         $canview = true;
                     }
                     // writing to cache has been moved from parseNode() to here so that
                     // the cached text has the placeholders replaced. (VBV-9507)
                     // any changes to the node requires update
                     $events = array('nodeChg_' . $nodeId);
                     // need to update cache if channel changes options
                     $events[] = 'nodeChg_' . $textDataArray[$nodeId]['channelid'];
                     // also need to update if phrases have been modified
                     $events[] = 'vB_Language_languageCache';
                     // write the parsed text values to cache. cache for a week.
                     $cache->write($this->getCacheKey($nodeId, $this->bbCodeOptions[$placeHolder], false, $canview), $parsed, 10080, $events);
                     $cache->write($this->getCacheKey($nodeId, $this->bbCodeOptions[$placeHolder], true, $canview), $previewText, 10080, $events);
                     if ($parsed !== false) {
                         if (stripos($placeHolder, '_pre_') === false) {
                             $this->cache[$placeHolder] = $parsed;
                         } else {
                             $this->cache[$placeHolder] = $previewText;
                         }
                     }
                 }
             }
             $templateCache->setRenderTemplatesInReverseOrder(false);
         }
     }
 }
Exemple #2
0
 /**
  * Handles a [USER] tag. Creates a link to the user profile
  *
  * @param	string	The username
  * @param	string	The userid
  *
  * @return	string	HTML representation of the tag.
  */
 function handle_bbcode_user($username = '', $userid = '')
 {
     $userid = (int) $userid;
     if ($userid > 0) {
         // fetch URL
         $userInfo = array('userid' => $userid, 'username' => $username);
         $url = vB5_Template_Runtime::buildUrl('profile', $userInfo);
         vB5_Template_Url::instance()->replacePlaceholders($url);
     } else {
         $url = false;
     }
     if ($url) {
         return "<a href=\"{$url}\" class=\"b-bbcode-user js-bbcode-user\" data-userid=\"{$userid}\">{$username}</a>";
     } else {
         return "<span class=\"b-bbcode-user js-bbcode-user\">{$username}</span>";
     }
 }
 /**
  * Handle any delayed rendering. Currently delayed urls and node texts.
  *
  * @param	string
  * @param	boolean	true if we are rendering for a call to /ajax/render/ and we want CSS <link>s separate
  *
  * @return	string
  */
 protected function renderDelayed(&$final_rendered_orig, $isAjaxTemplateRender = false)
 {
     $javascript = vB5_Template_Javascript::instance();
     $javascript->insertJs($final_rendered_orig);
     $javascript->resetPending();
     $stylesheet = vB5_Template_Stylesheet::instance();
     $stylesheet->insertCss($final_rendered_orig, $isAjaxTemplateRender);
     $stylesheet->resetPending();
     $link = vB5_Template_Headlink::instance();
     $link->insertLinks($final_rendered_orig);
     $link->resetPending();
     $phrase = vB5_Template_Phrase::instance();
     $phrase->replacePlaceholders($final_rendered_orig);
     $phrase->resetPending();
     // we do not reset pending urls, since they may be required by nodetext
     vB5_Template_Url::instance()->replacePlaceholders($final_rendered_orig);
     $nodeText = vB5_Template_NodeText::instance();
     $nodeText->replacePlaceholders($final_rendered_orig);
     $nodeText->resetPending();
     $templateCache = vB5_Template_Cache::instance();
     $templateCache->replaceTextOnly($final_rendered_orig);
     //We should keep the debug info for truly last.
     if (vB5_Frontend_Controller_Bbcode::needDebug()) {
         $config = vB5_Config::instance();
         if (!$config->debug) {
             return $final_rendered_orig;
         }
         self::$renderedTemplateNames[] = 'debug_info';
         self::$renderedTemplates[] = array('templateName' => 'debug_info', 'isParentTemplate' => (bool) 0, 'indent' => str_repeat('|----', 2));
         $user = vB5_User::instance();
         $this->register('user', $user, true);
         extract(self::$globalRegistered, EXTR_SKIP | EXTR_REFS);
         extract($this->registered, EXTR_OVERWRITE | EXTR_REFS);
         $vboptions = vB5_Template_Options::instance()->getOptions();
         $vboptions = $vboptions['options'];
         $renderedTemplates = array('count' => count(self::$renderedTemplates), 'countUnique' => count(array_unique(self::$renderedTemplateNames)), 'templates' => self::$renderedTemplates, 'styleid' => vB5_Template_Stylevar::instance()->getPreferredStyleId());
         $cssDebugLog = vB5_Template_Stylesheet::getDebugLog();
         $jsDebugLog = vB5_Template_Javascript::instance()->getDebugLog();
         $templateCode = $templateCache->getTemplate('debug_info');
         if ($templateCache->isTemplateText()) {
             @eval($templateCode);
         } else {
             @(include $templateCode);
         }
         $phrase->replacePlaceholders($final_rendered);
         $phrase->resetPending();
         $final_rendered_orig = str_replace('<!-DebugInfo-->', $final_rendered, $final_rendered_orig);
     }
 }
Exemple #4
0
 public function index($pageid)
 {
     //the api init can redirect.  We need to make sure that happens before we echo anything
     $api = Api_InterfaceAbstract::instance();
     $top = '';
     // We should not cache register page for guest. See VBV-7695.
     if (vB5_Request::get('cachePageForGuestTime') > 0 and !vB5_User::get('userid') and (empty($_REQUEST['routestring']) or $_REQUEST['routestring'] != 'register' and $_REQUEST['routestring'] != 'lostpw')) {
         // languageid should be in the pagekey to fix VBV-8095
         $fullPageKey = 'vBPage_' . md5(serialize($_REQUEST)) . '_' . vB::getCurrentSession()->get('languageid');
         $styleid = vB5_Cookie::get('userstyleid', vB5_Cookie::TYPE_UINT);
         if (!empty($styleid)) {
             $fullPageKey .= '_' . $styleid;
         }
         $fullPage = vB_Cache::instance(vB_Cache::CACHE_LARGE)->read($fullPageKey);
         if (!empty($fullPage)) {
             echo $fullPage;
             exit;
         }
     }
     $preheader = vB5_ApplicationAbstract::getPreheader();
     $top .= $preheader;
     if (vB5_Request::get('useEarlyFlush')) {
         echo $preheader;
         flush();
     }
     $router = vB5_ApplicationAbstract::instance()->getRouter();
     $arguments = $router->getArguments();
     $userAction = $router->getUserAction();
     $pageKey = $router->getPageKey();
     $api->callApi('page', 'preload', array($pageKey));
     if (!empty($userAction)) {
         $api->callApi('wol', 'register', array($userAction['action'], $userAction['params'], $pageKey, vB::getRequest()->getScriptPath(), !empty($arguments['nodeid']) ? $arguments['nodeid'] : 0));
     }
     if (isset($arguments['pagenum'])) {
         $arguments['pagenum'] = intval($arguments['pagenum']) > 0 ? intval($arguments['pagenum']) : 1;
     }
     $pageid = (int) (isset($arguments['pageid']) ? $arguments['pageid'] : (isset($arguments['contentid']) ? $arguments['contentid'] : 0));
     if ($pageid < 1) {
         // @todo This needs to output a user-friendly "page not found" page
         throw new Exception('Could not find page.');
     }
     $page = $api->callApi('page', 'fetchPageById', array($pageid, $arguments));
     if (!$page) {
         // @todo This needs to output a user-friendly "page not found" page
         throw new Exception('Could not find page.');
     }
     // Go to the first new / unread post for this user in this topic
     if (!empty($_REQUEST['goto']) and $_REQUEST['goto'] == 'newpost' and !empty($arguments['nodeid']) and !empty($arguments['channelid'])) {
         if ($this->vboptions['threadmarking'] and vB5_User::get('userid')) {
             // Database read marking
             $channelRead = $api->callApi('node', 'getNodeReadTime', array($arguments['channelid']));
             $topicRead = $api->callApi('node', 'getNodeReadTime', array($arguments['nodeid']));
             $topicView = max($topicRead, $channelRead, time() - $this->vboptions['markinglimit'] * 86400);
         } else {
             // Cookie read marking
             $topicView = intval(vB5_Cookie::fetchBbarrayCookie('discussion_view', $arguments['nodeid']));
             if (!$topicView) {
                 $topicView = vB5_User::get('lastvisit');
             }
         }
         $topicView = intval($topicView);
         // Get the first unread reply
         $goToNodeId = $api->callApi('node', 'getFirstChildAfterTime', array($arguments['nodeid'], $topicView));
         if (empty($goToNodeId)) {
             $thread = $api->callApi('node', 'getNodes', array(array($arguments['nodeid'])));
             if (!empty($thread) and isset($thread[$arguments['nodeid']])) {
                 $goToNodeId = $thread[$arguments['nodeid']]['lastcontentid'];
             }
         }
         if ($goToNodeId) {
             // Redirect to the new post
             $urlCache = vB5_Template_Url::instance();
             $urlKey = $urlCache->register($router->getRouteId(), array('nodeid' => $arguments['nodeid']), array('p' => $goToNodeId));
             $replacements = $urlCache->finalBuildUrls(array($urlKey));
             $url = $replacements[$urlKey];
             if ($url) {
                 $url .= '#post' . $goToNodeId;
                 if (headers_sent()) {
                     echo '<script type="text/javascript">window.location = "' . $url . '";</script>';
                 } else {
                     header('Location: ' . $url);
                 }
                 exit;
             }
         }
     }
     $page['routeInfo'] = array('routeId' => $router->getRouteId(), 'arguments' => $arguments, 'queryParameters' => $router->getQueryParameters());
     $page['crumbs'] = $router->getBreadcrumbs();
     $page['headlinks'] = $router->getHeadLinks();
     $page['pageKey'] = $pageKey;
     // default value for pageSchema
     $page['pageSchema'] = 'http://schema.org/WebPage';
     $queryParameters = $router->getQueryParameters();
     /*
      *	VBV-12506
      *	this is where we would add other things to clean up dangerous query params.
      *	For VBV-12486, I'll just unset anything here that can't use vb:var in the templates,
      *	but really we should just make a whitelist of expected page object parameters that
      *	come from the query string and unset EVERYTHING else. For the expected ones, we
      *	should also force the value into the expected (and hopefully safer) range
      */
     /*
      *	VBV-12506
      *	$doNotReplaceWithQueryParams is a list of parameters that the page object usually
      *	gets naturally/internally, and we NEVER want to replace with a user provided query
      *	parameter. (In fact, *when* exactly DO we want to do this???)
      *	If we don't do this, it's a potential XSS vulnerability for the items that we
      *	cannot send through vb:var for whatever reason (title for ex)
      * 	and even if they *are* sent through vb:var, the replacements can sometimes just
      *	break the page even when it's sent through vb:var (for example, ?pagetemplateid=%0D,
      *	the new line this inserts in var pageData = {...} in the header template tends to
      *	break things (tested on Chrome).
      *	Furthermore, any script that uses the pageData var would get the user injected data
      *	that might cause more problems down the line.
      *	Parameter Notes:
      *		'titleprefix'
      *			As these two should already be html escaped, we don't want to double escape
      *			them. So we can't us vb:var in the templates. As such, we must prevent a
      *			malicious querystring from being injected into the page object here.
      *		'title'
      *			Similar to above, but channels are allowed to have HTML in the title, so
      *			they are intentinoally not escaped in the DB, and the templates can't use
      *			vb:var.
      *		'pageid', 'channelid', 'nodeid'
      *			These are usually set in the arguments, so the array_merge below usually
      *			takes care of not passing a pageid query string through to the page object,
      *			but I'm leaving them in just in case.
      */
     $doNotReplaceWithQueryParams = array('titleprefix', 'title', 'pageid', 'channelid', 'nodeid', 'pagetemplateid', 'url', 'pagenum', 'tagCloudTitle');
     foreach ($doNotReplaceWithQueryParams as $key) {
         unset($queryParameters[$key]);
     }
     $arguments = array_merge($queryParameters, $arguments);
     foreach ($arguments as $key => $value) {
         $page[$key] = $value;
     }
     $options = vB5_Template_Options::instance();
     $page['phrasedate'] = $options->get('miscoptions.phrasedate');
     $page['optionsdate'] = $options->get('miscoptions.optionsdate');
     // if no meta description, use node data or global one instead, prefer node data
     if (empty($page['metadescription']) and !empty($page['nodedescription'])) {
         $page['metadescription'] = $page['nodedescription'];
     }
     if (empty($page['metadescription'])) {
         $page['metadescription'] = $options->get('options.description');
     }
     $config = vB5_Config::instance();
     // Non-persistent notices @todo - change this to use vB_Cookie
     $page['ignore_np_notices'] = vB5_ApplicationAbstract::getIgnoreNPNotices();
     $templateCache = vB5_Template_Cache::instance();
     $templater = new vB5_Template($page['screenlayouttemplate']);
     //IMPORTANT: If you add any variable to the page object here,
     // please make sure you add them to other controllers which create page objects.
     // That includes at a minimum the search controller (in two places currently)
     // and vB5_ApplicationAbstract::showErrorPage
     $templater->registerGlobal('page', $page);
     $page = $this->outputPage($templater->render(), false);
     $fullPage = $top . $page;
     if (!empty($fullPageKey) and is_string($fullPageKey)) {
         vB_Cache::instance(vB_Cache::CACHE_LARGE)->write($fullPageKey, $fullPage, vB5_Request::get('cachePageForGuestTime'), 'vbCachedFullPage');
     }
     // these are the templates rendered for this page
     $loadedTemplates = vB5_Template::getRenderedTemplates();
     $api->callApi('page', 'savePreCacheInfo', array($pageKey));
     if (!vB5_Request::get('useEarlyFlush')) {
         echo $fullPage;
     } else {
         echo $page;
     }
 }
 /**
  * Returns the URL for a route with the passed parameters
  * @param mixed $route - Route identifier (routeid or name)
  * @param array $data - Data for building route
  * @param array $extra - Additional data to be added
  * @param array $options - Options for building URL
  *					- noBaseUrl: skips adding the baseurl
  *					- anchor: anchor id to be added
  * @return type
  * @throws vB5_Exception_Api
  */
 public static function buildUrl($route, $data = array(), $extra = array(), $options = array())
 {
     return vB5_Template_Url::instance()->register($route, $data, $extra, $options);
 }