/** * Returns a matching route if available for $pathInfo * * @param string $pathInfo * @param string $queryString * @return vB_Frontend_Route */ public function getRoute($pathInfo, $queryString, $anchor = '') { static $closed; // clean the path if necessary $parsed = vB_String::parseUrl($pathInfo); $pathInfo = $parsed['path']; // check for any querystring to append if (!empty($parsed['query'])) { if (!empty($queryString)) { $queryString = $parsed['query'] . '&' . $queryString; } else { $queryString = $parsed['query']; } } if (empty($anchor) and !empty($parsed['anchor'])) { $anchor = $parsed['anchor']; } //Check for standard routes. if (is_string($pathInfo)) { $common = vB5_Route::fetchCommonRoutes(); if (isset($common[$pathInfo])) { //See if we have a match // pattern matching is case-insensitive $pattern = '#^' . $common[$pathInfo]['regex'] . '(?:/)?$#i'; if (preg_match($pattern, $pathInfo, $matches)) { $className = (isset($common[$pathInfo]['class']) and !empty($common[$pathInfo]['class']) and class_exists($common[$pathInfo]['class'])) ? $common[$pathInfo]['class'] : self::DEFAULT_CLASS; if (!empty($common[$pathInfo]['arguments'])) { $common[$pathInfo]['arguments'] = unserialize($common[$pathInfo]['arguments']); } try { $route = new $className($common[$pathInfo], $matches, $queryString, $anchor); } catch (vB_Exception $ex) { return $this->handleRouteExceptions($ex); } } } } if (!isset($route)) { // calculate prefixes set $prefixes = vB5_Route::getPrefixSet($pathInfo); // get matching routes $result = vB::getDbAssertor()->assertQuery('routenew', array('prefix' => $prefixes)); if (in_array($result->db()->errno, $result->db()->getCriticalErrors())) { throw new Exception('no_vb5_database'); } $prefixMatches = array(); foreach ($result as $route) { if (($unserialized = @unserialize($route['arguments'])) !== false) { $route['arguments'] = $unserialized; } else { $route['arguments'] = array(); } $prefixMatches[$route['routeid']] = $route; } unset($route); } // check for banned $bannedInfo = vB_Library::instance('user')->fetchBannedInfo(false); // get best route try { if (!isset($route)) { $route = vB5_Route::selectBestRoute($pathInfo, $queryString, $anchor, $prefixMatches); } if ($route) { // Check if forum is closed $routeInfo = array('routeguid' => $route->getRouteGuid(), 'controller' => $route->getController(), 'action' => $route->getAction(), 'arguments' => $route->getArguments()); $segments = $route->getRouteSegments(); $cleanedRoute = implode('/', $segments); if (in_array($cleanedRoute, $this->GetSpecialRoutes())) { return array('no_permission' => 1); } //Always allow login and access to the admincp, even if closed. if (!in_array($cleanedRoute, $this->whitelistRoute)) { if (!isset($closed)) { if (vB_Cache::instance(vB_Cache::CACHE_FAST)->isLoaded('vB_State_checkBeforeView')) { $closed = vB_Cache::instance(vB_Cache::CACHE_FAST)->read('vB_State_checkBeforeView'); } else { $closed = vB_Api::instanceInternal('state')->checkBeforeView($routeInfo); } } if ($closed !== false) { return array('forum_closed' => $closed['msg']); } } if ($bannedInfo['isbanned']) { return array('banned_info' => $bannedInfo); } if (!vB::getUserContext()->getChannelPermission('forumpermissions', 'canview', 1)) { $prefix = $route->getCanonicalPrefix(); if (!in_array($prefix, $this->whitelistPrefix)) { if ($route->getPrefix() == 'admincp' or $route->getPrefix() == 'modcp') { // do nothing really, just allow passage } else { if ($route->getPrefix() == 'ajax') { $arguments = $route->getArguments(); $allowedOptions = array('/api/contactus/sendMail', '/api/hv/generateToken'); if (!isset($arguments['route']) or !in_array($arguments['route'], $allowedOptions)) { return array('no_permission' => 1); } } else { return array('no_permission' => 1); } } } } if (is_array($route) and (isset($route['no_permission']) or isset($route['internal_error']))) { return $route; } $canonicalUrl = $route->getCanonicalUrl(); $canonicalUrl = str_replace('&', '&', $canonicalUrl); $canonicalPathInfo = $canonicalUrl ? vB_String::parseUrl($canonicalUrl, PHP_URL_PATH) : $pathInfo; $canonicalParam = $route->getCanonicalQueryParameters(); if ($canonicalPathInfo and $canonicalPathInfo[0] == '/') { $canonicalPathInfo = substr($canonicalPathInfo, 1); } $queryParams = $route->getQueryParameters(); $routeId = $route->getRouteId(); // return routeid even for 301 redirects. Certain callers expect // this function to return the routeid in order to write a cache record if ($redirectId = $route->getRedirect301()) { return array('routeid' => $routeId, 'redirect' => vB5_Route::buildUrl($redirectId, $route->getArguments(), $queryParams, $route->getAnchor()), 'redirectRouteId' => $redirectId); } else { if ($pathInfo != $canonicalPathInfo or $canonicalParam !== false and $queryParams != $canonicalParam) { $hashtag = ''; if (isset($queryParams['p'])) { $hashtag = '#post' . $queryParams['p']; // some browers do not preserve fragment during redirects, VBV-10255 } return array('routeid' => $routeId, 'redirect' => $canonicalUrl . $hashtag, 'redirectRouteId' => $routeId); } else { return array('routeid' => $routeId, 'routeguid' => $route->getRouteGuid(), 'controller' => $route->getController(), 'action' => $route->getAction(), 'template' => $route->getTemplate(), 'arguments' => $route->getArguments(), 'queryParameters' => $queryParams, 'pageKey' => $route->getPageKey(), 'userAction' => $route->getUserAction(), 'breadcrumbs' => $route->getBreadcrumbs(), 'headlinks' => $route->getHeadLinks()); } } } else { return false; } } catch (vB_Exception $ex) { return $this->handleRouteExceptions($ex); } }