0byt3m1n1
Path:
/
data
/
applications
/
aps
/
gallery
/
2.2-08
/
htdocs
/
modules
/
core
/
classes
/
[
Home
]
File: GalleryUrlGenerator.class
<?php /* * Gallery - a web based photo album viewer and editor * Copyright (C) 2000-2007 Bharat Mediratta * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or (at * your option) any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ /* Don't use GalleryCoreApi::requireOnce here; index.php uses this file without GalleryCoreApi */ require_once(dirname(__FILE__) . '/GalleryUtilities.class'); if (!defined('GALLERY_MAIN_PHP')) { define('GALLERY_MAIN_PHP', 'main.php'); } /** * This class generates all URLs for Gallery based on the auto-detected protocol, hostname, URL * path and the given GALLERY_MAIN_PHP. Handles normal standalone as well as embedded and * multisite operation when some URLs need to go to the Gallery codebase directly. Also handles * the navigation (history) together with GallerySession. All auto-detected URL parts can be * overrided with the init() parameters (originating either from the optional config.php parameter * 'baseUri' or from GalleryEmbed). * * @package GalleryCore * @subpackage Classes * @author Bharat Mediratta <bharat@menalto.com> * @author Alan Harder <alan.harder@sun.com> * @version $Revision: 16471 $ */ class GalleryUrlGenerator { /** * URL base filename of Gallery, defaults to 'main.php'. Can also include some parameters, eg. * main.php?foo=bar. * * Index of array = $forceDirect (true/false) only relevant for embedded Gallery * array (0 => string file, 1 => string forceDirect file) * @var array * @access private */ var $_file; /** * URL path to Gallery, eg. '/gallery2/' of http://example.com/gallery2/main.php. * * Index of array = $forceDirect (true/false) only relevant for embedded Gallery * array (0 => string path, 1 => string forceDirect path) * @var array * @access private */ var $_path; /** * The host string of generated URLs (including optional port) eg. 'www.example.com'. * * Index of array = $forceDirect (true/false) only relevant for embedded Gallery * array (0 => string host, 1 => string forceDirect host) * @var array * @access private */ var $_host; /** * The protocol of generated URLs, 'http' or 'https'. * * Index of array = $forceDirect (true/false) only relevant for embedded Gallery * array (0 => string protocol, 1 => string forceDirect protocol) * @var array * @access private */ var $_protocol; /** * The session key=value for the CMS application in which Gallery is embedded. Should only be * non-empty when cookieless browsing is supported by CMS, eg. 'session=3838562834573' which is * then added to all URLs generated by Gallery. * @var string * @access private */ var $_embedSessionString; /** * The base host (protocol + host name) of all URLs generated with function makeUrl. * * Index of array = $forceDirect (true/false), eg. 'http://example.com/' * array (0 => string base host, 1 => string forceDirect base host) * @var array * @access private */ var $_currentBaseHost; /** * The complete URL (protocol + host name + path + file + query string) of the current request * eg. 'http://example.com/gallery2/main.php?g2_view=core.ShowItem&g2_itemId=15'. * * Index of array = $forceDirect (true/false) only relevant for embedded Gallery * array (0 => string base URL, 1 => string forceDirect base URL) * @var array * @access private */ var $_currentUrl; /** * The complete URL dir (protocol + host name + path) of all URLs to be generated eg. * 'http://example.com/gallery2/. * * Index of array = $forceDirect (true/false) only relevant for embedded Gallery * array (0 => string base URL dir, 1 => string forceDirect base URL dir) * @var array * @access private */ var $_currentUrlBaseDir; /** * The navigation id of the current URL. * @var string * @access private */ var $_navId = ''; /** * Whether the cookie path was configured by the admin. * @var boolean * @access private */ var $_isCookiePathConfigured; /* * **************************************** * Static Methods */ /** * Return the current request URI. * Example: for http://domain.com/gallery2/main.php?g2_view=core.ShowItem * it returns /gallery2/main.php?g2_view=core.ShowItem * * @return string the current URL path component plus query parameters * @static */ function getCurrentRequestUri() { if ($path = GalleryUtilities::getServerVar('REQUEST_URI')) { /* Sometimes, REQUEST_URI has a host part. Remove it. */ if ($path{0} != '/') { $components = parse_url($path); $path = $components['path']; $path .= empty($components['query']) ? '' : '?' . $components['query']; $path .= empty($components['fragment']) ? '' : '#' . $components['fragment']; } } else if ($path = GalleryUtilities::getServerVar('SCRIPT_NAME')) { if (($tmp = GalleryUtilities::getServerVar('PATH_INFO')) && $tmp != $path) { $path .= $tmp; } if ($tmp = GalleryUtilities::getServerVar('QUERY_STRING')) { $path .= '?' . $tmp; } } GalleryUtilities::unsanitizeInputValues($path, false); return $path; } /** * Append parameters to a URL using the Gallery prefix and URL encoding keys and values. * @param string $url the original URL * @param array $params key/value pairs to be appended; may contain nested arrays * @param boolean $addPrefix (optional) false to not add prefix to parameter names * @param boolean $htmlEntities (optional) false to not convert ampersands to HTML entities * @param boolean $urlEncode (optional) false to not URL encode parameter names and values * @return string the new URL (& separates added params) * @static */ function appendParamsToUrl($url, $params, $addPrefix=true, $htmlEntities=true, $urlEncode=true) { if (empty($params)) { return $url; } $args = $flatParams = array(); GalleryUrlGenerator::_flattenParamsArray($params, $flatParams); foreach ($flatParams as $key => $value) { if ($addPrefix) { $key = GalleryUtilities::prefixFormVariable($key); } if ($urlEncode) { $key = urlencode($key); $value = urlencode($value); } $args[] = $key . '=' . $value; } /* Prefix appended params with ? if the URL doesn't already have a query string */ $amp = $htmlEntities ? '&' : '&'; return $url . ((strpos($url, '?') === false) ? '?' : $amp) . implode($amp, $args); } /** * Convert a structure of nested URL parameters into a flat array of parameters. * * Preserves the order of the parameters and does not encode them yet. * Example: Input array('a' => '1', 'b' => array('c' => 2), 'd' = 3) * Result array('a' => '1', 'b[c]' => 2, 'd' = 3) * * @param array $nestedParams array of URL parameters, can have nested arrays * @param array $flatParams flat array of URL parameters * @param string $keyBase (optional) base of the key for nested array parameters * @static * @access private */ function _flattenParamsArray($nestedParams, &$flatParams, $keyBase=null) { foreach ($nestedParams as $key => $value) { $key = empty($keyBase) ? $key : $keyBase . '[' . $key . ']'; if (is_array($value)) { GalleryUrlGenerator::_flattenParamsArray($value, $flatParams, $key); } else { $flatParams[$key] = $value; } } } /** * Old multisite system used a galleryId based on the current URL. Return a value here so sites * won't break before they can upgrade. * @todo Remove on next major bump of core api * * @static * @deprecated */ function getGalleryId() { return ''; } /** * Split a URI string into file, path, host and protocol substrings and normalize them. * * Used to allow overriding auto-detected protocol, host, path and default base file. Also used * to accept various embedUri formats * * @param string $uri URI * @return array $protocol, $host, $path, $file (incl. query string) * @access private * @static */ function _parseUri($uri) { /* * baseUri / g2Uri can have the following patterns: * - Everything before the two last '/' is interpreted as path * (minus the host part, if specified). * - Thus URI with leading '/' are interpreted as path (+ optional file). * - If there is a '/' and no http://, everything before the first '/' is * interpreted as host string and the protocol defaults to http. * - If it starts with http://, everything after it up to the first '/' * is interpreted as the host string. * - Everything after the last '/' is interpreted as file + query string. * Examples of allowed URI strings: * http://www.example.com * http://example.com/gallery2/ * https://127.0.0.1/gallery2/main.php * www.example.com/main.php * /gallery2/ * /gallery2/main.php * /main.php * main.php * Notes (= what you shouldn't do): * www.example.com (no '/' -> interpreted as file and not as host) * main.php/ (everything before the last '/' is interpreted as path) */ $file = $uri; $path = $host = $protocol = ''; if (strpos($file, '/') !== false) { /* Check if it's a URL including host and optional protocol part */ if (preg_match('{^(?:(https?)://)?([^/]+)(.*)$}', $file, $matches)) { $protocol = $matches[1]; $host = $matches[2]; $file = $matches[3]; } /* $file = '/...', '/.../', '/.../...' or '...' '*/ if (preg_match('{^(/(?:.*/)?)?([^/]*)$}', $file, $matches)) { $path = $matches[1]; $file = $matches[2]; } } return array($protocol, $host, $path, $file); } /* * **************************************** * Object Methods */ /** * Configure the GalleryUrlGenerator with all the data it needs. * * @param string $baseUri the base URL (optional), eg. index.php?mod=gallery will override * main.php, /index.php or /gallery/index.php will override the path and file, * /gallery/ overrides the path only, example.com/, overrides the host and the path and * http://example.com/gallery/index.php?page=gallery overrides all parts * All non-specified parts fall back to auto-detected values * @param string $g2Uri (optional) when embedded, base URL to Gallery standalone. Same format * as baseUri * @param string $embedSessionString (optional) when embedded in CMS app that supports * cookieless browsing, key=value string for CMS session key and id */ function init($baseUri=null, $g2Uri=null, $embedSessionString=null) { $this->_embedSessionString = $embedSessionString; if (isset($baseUri)) { list ($this->_protocol[0], $this->_host[0], $this->_path[0], $this->_file[0]) = $this->_parseUri($baseUri); } else { $this->_file[0] = GALLERY_MAIN_PHP; /* * Set the default value for the path part, if necessary (path = empty string is * interpreted as not set / forced in URL generators ('/' would be interpreted as set) */ $this->_path[0] = ''; $this->_protocol[0] = $this->_host[0] = null; } /* Set the forceDirect configuration parameters (only different if Gallery is embedded) */ if (!empty($g2Uri)) { list ($this->_protocol[1], $this->_host[1], $this->_path[1], $this->_file[1]) = $this->_parseUri($g2Uri); /* If file[1] is empty, we default to GALLERY_MAIN_PHP, unless it's intended */ if ($this->_file[1] == '|') { /* User actually intends to set the file to an empty string */ $this->_file[1] = ''; } else if (empty($this->_file[1])) { $this->_file[1] = GALLERY_MAIN_PHP; } } else { $this->_file[1] = $this->_file[0]; $this->_path[1] = $this->_path[0]; $this->_host[1] = $this->_host[0]; $this->_protocol[1] = $this->_protocol[0]; } /* Set the default value for the host part, if necessary */ foreach (array(false, true) as $forceDirect) { if (empty($this->_host[$forceDirect])) { if (!isset($defaultHost) && !($defaultHost = GalleryUtilities::getServerVar('HTTP_X_FORWARDED_HOST'))) { $defaultHost = GalleryUtilities::getServerVar('HTTP_HOST'); } $this->_host[$forceDirect] = $defaultHost; } } /* Set the default value for the protocol part, if necessary */ foreach (array(false, true) as $forceDirect) { if (empty($this->_protocol[$forceDirect])) { $this->_protocol[$forceDirect] = (GalleryUtilities::getServerVar('HTTPS') == 'on') ? 'https' : 'http'; } } /* Set the base host (protocol + host name) for makeUrl() (caching/performance) */ foreach (array(false, true) as $forceDirect) { $this->_currentBaseHost[$forceDirect] = sprintf('%s://%s', $this->_protocol[$forceDirect], $this->_host[$forceDirect]); } /* Check if the cookie path is configured */ if (GalleryUtilities::isEmbedded()) { list ($ret, $path) = GalleryCoreApi::getPluginParameter('module', 'core', 'cookie.path'); if ($ret) { return $ret; } if (!empty($path)) { $this->_isCookiePathConfigured = true; } else { $this->_isCookiePathConfigured = false; } } return null; } /** * Return the host name for the current request. * * @param boolean $forceDirect (optional) if true, ensure Gallery base protocol/host is used * @return string the host name */ function getHostName($forceDirect=false) { return $this->_host[$forceDirect]; } /** * Add given path to current protocol/server/port to create full URL. * * @param string $path the URL path; leading slash will be added if missing * @param boolean $forceDirect (optional) if true, ensure Gallery base protocol/host is used * @return string the URL */ function makeUrl($path, $forceDirect=false) { if (empty($path)) { $path = '/'; } else if ($path{0} != '/') { $path = '/' . $path; } return $this->_currentBaseHost[$forceDirect] . $path; } /** * Make a given URL an absolute Gallery URL. The specified URL can be relative (e.g. main.php), * server-relative (e.g. /gallery2/main.php) or already absolute. * * @param string a relative, server-relative or absolute URL * @param boolean $forceDirect (optional) if true, Gallery base protocol/host is used in case * the URL isn't absolute already * @return string the absolute URL */ function makeAbsoluteUrl($url, $forceDirect=false) { $url = trim($url); if (!preg_match('#^[A-Za-z0-9+.\-]+://#', $url)) { if (substr($url, 0, 1) == '/') { $url = $this->makeUrl($url, $forceDirect); } else { $url = $this->getCurrentUrlDir($forceDirect) . $url; } } return $url; } /** * Return the complete URL of the current request. * * The returned URL may differ from the actual request URL since we allow for overriding the * discovered protocol/host/host/path/file * * @param boolean $forceDirect (optional) if true, ensure Gallery base protocol/host is used * @return string the current URL */ function getCurrentUrl($forceDirect=false) { if (!isset($this->_currentUrl[$forceDirect])) { /* Allow overriding protocol / host part, but keep request string unchanged */ $this->_currentUrl[$forceDirect] = $this->makeUrl(GalleryUrlGenerator::getCurrentRequestUri(), $forceDirect); } return $this->_currentUrl[$forceDirect]; } /** * Return a URL that is stripped of all parameters that don't directly affect the output of the * page, like navigation parameters. This URL can be used as the cache key for this page. * * @return string */ function getCacheableUrl() { $url = $this->getCurrentUrl(); $parsed = parse_url($url); $url = !empty($parsed['scheme']) ? $parsed['scheme'] . ':' . '//' : ''; $url .= !empty($parsed['user']) ? $parsed['user'] . ($parsed['pass'] ? ':'.$parsed['pass'] : '') . '@' : ''; $url .= !empty($parsed['host']) ? $parsed['host'] : ''; $url .= !empty($parsed['port']) ? ':' . $parsed['port'] : ''; $url .= !empty($parsed['path']) ? $parsed['path'] : ''; if (!empty($parsed['query'])) { parse_str($parsed['query'], $components); foreach (array('statusId', 'return', 'returnName', 'navId', 'fromNavId') as $special) { unset($components[GALLERY_FORM_VARIABLE_PREFIX . $special]); } $first = true; foreach ($components as $key => $value) { $url .= $first ? '?' : '&'; $url .= "$key=$value"; $first = false; } } $url .= !empty($parsed['fragment']) ? '#' . $parsed['fragment'] : ''; return $url; } /** * Return the base directory of all generated URLs. Eg, if the URL is: * http://example.com/gallery2/main.php * Then we return: * http://example.com/gallery2/ * * Usually, it's the same as the URL directory of the current request URL, unless we're using * short URLs. Also, the base URL can be overridden * * @param boolean $forceDirect (optional) if true, ensure Gallery base URL is returned * (different when embedded) * @return string the base URL directory */ function getCurrentUrlDir($forceDirect=false) { if (!isset($this->_currentUrlBaseDir[$forceDirect])) { if (!empty($this->_path[$forceDirect])) { /* An override for the path was defined (most likely an embedded Gallery request) */ $url = $this->makeUrl($this->_path[$forceDirect], $forceDirect); } else { /* * Non-embedded request (else path must be set) * Auto-detect the path in the current URL */ $url = $this->getCurrentUrl($forceDirect); /* * Remove the base file and any query string after it * http://example.com/gallery2/main.php?g2_foo=foo/bar * Extract everything up to but not including main.php: * http://example.com/gallery2/ * Note: PathInfo is handled by the PathInfoUrlGenerator */ if (empty($this->_file[0])) { $url = substr($url, 0, strrpos($url, '/') + 1); } else if (($i = strpos($url, $this->_file[0])) !== false) { $url = substr($url, 0, $i); } else if (($i = strpos($url, '?')) !== false) { /* We couldn't find the file name, at least remove the query string */ $url = substr($url, 0, $i); } } $url .= substr($url, -1) != '/' ? '/' : ''; $this->_currentUrlBaseDir[$forceDirect] = $url; } return $this->_currentUrlBaseDir[$forceDirect]; } /** * Generate a Gallery URL. * @param array $params (optional) key=value pairs to be included in the URL * special 'href' key specifies path to append to Gallery base URL instead of a query param * %CURRENT_URL% token in a parameter value will be replaced with current URL * @param array $options (optional) additional URL generation options: * 'baseUrl' => string; to override the default baseUrl * 'forceDirect' => true; to generate from Gallery site URL even if embedded or multisite * 'forceFullUrl' => true; to generate absolute URL instead of relative path URL * 'forceSessionId' => boolean; to force session id to be included or excluded; by default * it is included when cookies are not in use (by default it is excluded from href URLs) * 'htmlEntities' => false; to use '&' parameter separator instead of '&' * 'urlEncode' => false; to not URL encode parameter names and values * 'forceServerRelativeUrl' => true; to generate server-relative URLs if possible but no * relative URLs (e.g. /gallery2/main.php instead of * http://example.com/gallery2/main.php but never just main.php (without path)) * 'useAuthToken' => boolean; to force auth token to be included or excluded; by default it * is included in controller URLs * 'protocol' => string; to override the URL scheme * @return string URL */ function generateUrl($params=array(), $options=array()) { global $gallery; $currentView = $gallery->getCurrentView(); /* * For 'core.DownloadItem' URLs or if 'forceDirect' option given, use Gallery site URL * (direct to main.php in directory for active config.php, even if embedded/multisite). For * other non-absolute 'href' URLs use Gallery base URL (direct to Gallery codebase location, * even if multisite or embedded). Otherwise use application URL (embed URL; same as * Gallery site URL if not embedded). */ if (isset($options['baseUrl'])) { $url = $options['baseUrl']; $appSession = true; } else if (isset($params['href'])) { /* In case of multisites, get the codebase base URL */ $url = $gallery->getConfig('galleryBaseUrl'); if (empty($url) || !empty($options['forceDirect'])) { $url = $this->getCurrentUrlDir(true); } /* Default to not including session id in href URLs */ if (!isset($options['forceSessionId'])) { $options['forceSessionId'] = false; } $href = $params['href']; unset($params['href']); if (preg_match('/^[a-zA-Z0-9\+\.\-]+:\/\//', $href)) { /* Absolute URL */ $url = $href; } else if (($pos = strpos($href, '/')) === 0) { /* Absolute URL path (use $options['baseUrl'] if you need non forceDirect URLs) */ $url = $this->makeUrl($href, true); } else if ($pos > 0) { /* Check for local override */ $override = sprintf('%s/local/%s', dirname($href), basename($href)); $platform =& $gallery->getPlatform(); if ($platform->file_exists(dirname(__FILE__) . '/../../../' . $override)) { $href = $override; } $url .= $href; } else { $url .= $href; } } else if ((isset($params['view']) && $params['view'] == 'core.DownloadItem') || !empty($options['forceDirect'])) { /* DownloadItem requests go always directly to Gallery, even when embedded */ $url = $this->getCurrentUrlDir(true) . $this->_file[true]; /* Check if we are forced to append the session id in embedded Gallery */ if (!isset($options['forceSessionId']) && $this->embedForceSessionId($params)) { $options['forceSessionId'] = true; } } else { $url = $this->getCurrentUrlDir() . $this->_file[0]; $appSession = true; } /* Swap in the actual URL for the 'return' placeholder */ if (isset($params['return'])) { list ($ret, $view) = GalleryView::loadView($currentView); if (!$ret) { list ($ret, $viewDescription) = $view->getViewDescription(); if (!$ret) { $params['returnName'] = $viewDescription; } } $params['return'] = str_replace('&', '&', $this->getNavigationReturnUrl()); if (!empty($this->_navId)) { $params['navId'] = $this->_navId; } } /* Navigation */ $targetView = isset($params['view']) ? $params['view'] : ''; if (!empty($this->_navId) && empty($options['forceDirect']) && (empty($currentView) || $currentView == $targetView || !empty($params['controller']))) { /* * We are moving around in the same view or we are redirecting to a controller, * who knows where it will redirect to. Let's keep the navigation. */ $params['navId'] = $this->_navId; } /* Replace any known tokens */ foreach (array_keys($params) as $key) { if ($params[$key] === '%CURRENT_URL%') { $params[$key] = $this->getCurrentUrl(); } } /* Shorten URLs by removing default values */ if (isset($params['view']) && $params['view'] == GALLERY_DEFAULT_VIEW) { unset($params['view']); if (empty($this->_rootItemId)) { list ($ret, $this->_rootItemId) = GalleryCoreApi::getDefaultAlbumId(); if ($ret) { $this->_rootItemId = -1; } } if (isset($params['itemId']) && $params['itemId'] == $this->_rootItemId) { unset($params['itemId']); } } if ($session =& $gallery->getSession()) { $sessionId = $session->getId(); /* * Remove session related parameters if requested (we're already outputting or output * without fetching the HTML (immediate view / progressbar) */ if (empty($sessionId) || !$session->isPersistent()) { unset($params['navId']); } else { /* Add authToken to all controller URLs */ if (!empty($options['useAuthToken']) || (!isset($options['useAuthToken']) && !empty($params['controller']))) { $params['authToken'] = $session->getAuthToken(); } } /* Add session parameters to URL */ if (!empty($options['forceSessionId']) || (!isset($options['forceSessionId']) && !$session->isUsingCookies())) { if (!empty($this->_embedSessionString) && !empty($appSession)) { list ($sessionKey, $sessionId) = explode( '=', $this->_embedSessionString, 2); $embedSessionParams = array(); $embedSessionParams[$sessionKey] = $sessionId; } else if (!empty($sessionId)) { $params[$session->getKey()] = $sessionId; } } } /* Add parameters to URL */ $url = GalleryUrlGenerator::appendParamsToUrl($url, $params, true, !empty($options['htmlEntities']) || !isset($options['htmlEntities']), !empty($options['urlEncode']) || !isset($options['urlEncode'])); /* Add embed session parameters to URL */ if (!empty($embedSessionParams)) { $url = GalleryUrlGenerator::appendParamsToUrl($url, $embedSessionParams, false, !empty($options['htmlEntities']) || !isset($options['htmlEntities']), false); } /* Replace protocol with $options['protocol']. See RFC1738 section 2.1. */ if (isset($options['protocol'])) { $url = preg_replace('/^[a-zA-Z0-9\+\.\-]+:/', $options['protocol'] . ':', $url); } /* * Elide as much of the common URL as we can to save space. This won't cover all cases, * since other URL generators could be subclassing this, but it should be relatively safe * because it's only removing substrings that match exactly. If rewrite is on, then we have * to use a server relative path since we may be at a URL like /v/foo/bar so if we try for a * pure relative path then we'll wind up using /v/foo/bar as the base for relative URLs */ if (empty($options['forceFullUrl'])) { $url = $this->makeRelativeUrl($url, !empty($options['forceServerRelativeUrl'])); } return $url; } /** * Translate the given absolute URL to a relative URL. * * The result will be either a server relative URL /..., a URL relative to the current URL * directory or an unchanged absolute URL (some URLs in multisite go to the codebase, embedded * Gallery could be on a different subdomain, ..) * * Note: don't be fooled if $this->_file shows up in the query string! * * @param string $url absolute URL * @return string relative URL (or unchanged absolute URL) */ function makeRelativeUrl($url, $forceServerRelativeUrl=false) { $requestUri = $this->getCurrentRequestUri(); /* When embedded, file can be empty */ if ($forceServerRelativeUrl || empty($this->_file[0]) || ($pos = strpos($requestUri, $this->_file[0])) === false || (($qPos = strpos($requestUri, '?')) !== false && $pos >= $qPos) || strpos($url, $this->getCurrentUrlDir()) !== 0) { /* Don't use forceDirect, keep the URL absolute if necessary */ $url = str_replace($this->makeUrl('/'), '/', $url); } else { $url = str_replace($this->getCurrentUrlDir(), '', $url); } return $url; } /** * Get the cookie path that will encompass Gallery (and CMS app if embedded). * * The forceDirect parameter forces the function to return the path to Gallery and not to the * current dir of the URL. This is only relevant when Gallery is embedded. forceDirect is only * used for applets because they talk to Gallery directly and not through the embedding * application. If the cookie path wouldn't be set to the Gallery base in this case, the applet * wouldn't select the cookie for requests, because it wasn't allowed to (according to the * cookie specs) * * Examples: * Current URL forceDirect cookie path * http://example.com/gallery2/main.php false /gallery2/ * http://example.com/gallery2/main.php true /gallery2/ * http://example.com/applicationXy/index.php false /applicationXy/ * http://example.com/applicationXy/index.php true /gallery2/ * * In the last example we assumed that Gallery is installed at that location. * * @param boolean $forceDirect (optional) if true, ensure Gallery path of base URL is returned * (different when embedded) * @return array (object Gallery status, string path) */ function getCookiePath($forceDirect=false) { if (!isset($this->_cookiePath[$forceDirect])) { /* Return the configured path is it is set */ list ($ret, $path) = GalleryCoreApi::getPluginParameter('module', 'core', 'cookie.path'); if ($ret) { return array($ret, null); } if (empty($path)) { if (!empty($this->_path[$forceDirect])) { $path = $this->_path[$forceDirect]; } else { $urlComponents = parse_url($this->getCurrentUrlDir($forceDirect)); $path = $urlComponents['path']; } } $this->_cookiePath[$forceDirect] = $path; } return array(null, $this->_cookiePath[$forceDirect]); } /** * Initialize the navigation branch. * * If we came here with a 'return' set, we need to branch a new navigation. If we are just * navigating through options in the same navigation level, simply pass the navId along. If we * are coming back from a navigation, clean up our mess. In other cases we simply have no * navigation support * * Note: This should be called as soon as we have access to our session and the * requestVariables, but before we start generating URLs with generateUrl(). Currently it's * called from GalleryInitSecondPass * * @return object GalleryStatus */ function initNavigation() { global $gallery; $variables = GalleryUtilities::getRequestVariables('return', 'returnName', 'navId', 'fromNavId'); foreach ($variables as $key => $value) { $variables[$key] = is_string($value) ? $value : null; } list ($returnUrl, $returnName, $navId, $fromNavId) = $variables; if (!empty($returnUrl)) { /* Detect header injection attempts */ if (!GalleryUtilities::isSafeHttpHeader($returnUrl)) { $message = sprintf('Invalid return URL! The requested URL %s contains malicious ' . 'characters.', $this->makeUrl($this->getCurrentRequestUri()), $returnUrl); return GalleryCoreApi::error(ERROR_PERMISSION_DENIED, __FILE__, __LINE__, $message); } /* * Check for phishing attacks, don't allow return URLs to other sites or to other paths. * Therefore first get the validPath, e.g. '/gallery2/' Do not allow ../ to break out of * the path Allow all URLs that don't start with a protocol and neither with '/', eg. * v/albumname but also www.EVIL.com is fine, since it's interpreted as a relative URL */ $validPath = '/' . str_replace($this->makeUrl(''), '', $this->getCurrentUrlDir()); /* * We check for ../ and /../ patterns and on windows \../ would also break out, * normalize to URL / *nix style paths to check fewer cases */ $normReturnUrl = str_replace("\\", '/', $returnUrl); if (((empty($this->_file[0]) || strpos($returnUrl, $this->_file[0]) !== 0) && strpos($normReturnUrl, $validPath) !== 0 && strpos($returnUrl, $this->getCurrentUrlDir()) !== 0 && !( !preg_match('{^\s*\w*://}i', $normReturnUrl) && preg_match('{^\s*[^/\s]}i', $normReturnUrl))) || preg_match('{^\s*\.\./}', $normReturnUrl) || strpos($normReturnUrl, '/../') !== false) { $message = sprintf('Invalid return URL! The requested URL %s tried to insert a ' . 'redirection to %s which is not a part of this Gallery.', $this->makeUrl($this->getCurrentRequestUri()), $returnUrl); return GalleryCoreApi::error(ERROR_PERMISSION_DENIED, __FILE__, __LINE__, $message); } /* Branch a new navigation */ $navData = array('returnUrl' => $returnUrl, 'returnName' => $returnName); if (!empty($navId)) { $navData['returnNavId'] = $navId; } $session =& $gallery->getSession(); $this->_navId = $session->addToNavigation($navData); } else { if (!empty($fromNavId)) { /* We came back from a navigational branch. Delete it */ $session =& $gallery->getSession(); $session->jumpNavigation($fromNavId, $navId); } if (!empty($navId)) { /* Just continue in our current navigation level */ $this->_navId = $navId; } } return null; } /** * Get the current navigation id. * * @return string the navigation id */ function getNavigationId() { return $this->_navId; } /** * Get an URL to return to the currently loaded view, stripping all parameters that are of * navigational nature. * * @return string the URL */ function getNavigationReturnUrl() { global $gallery; $formUrl = GalleryUtilities::getRequestVariables('formUrl'); if (!empty($formUrl)) { /* * We don't really have an URL, because we are in a POST request. This is the last * known URL when the form was originally rendered */ return $formUrl; } $params = GalleryUtilities::getUrlVariablesFiltered( array('return', 'returnName', 'navId', 'fromNavId', 'authorization'), true); return $this->generateUrl($params, array('forceServerRelativeUrl' => 1)); } /** * Check if we currently have a back link to where we came from. * * @return boolean true if we can go back */ function isNavigationBackPossible() { global $gallery; if (empty($this->_navId)) { return false; } $session =& $gallery->getSession(); $navData = $session->getNavigation($this->_navId); return (count($navData) > 0); } /** * Get a list of navigation links to go back to where we came from. * * @param int $depth set this to get links back to a certain depth * @return array ( object GalleryStatus a status code, * array of navigational links: array('url' => ..., * 'name' => 'Back to ...')) */ function getNavigationLinks($depth=null) { global $gallery; if (empty($this->_navId)) { return array(null, array()); } list ($ret, $core) = GalleryCoreApi::loadPlugin('module', 'core'); if ($ret) { return array($ret, null); } $session =& $gallery->getSession(); $navData = $session->getNavigation($this->_navId); $links = array(); $i = 0; foreach ($navData as $navItem) { $i++; if (isset($depth) && $i > $depth) { break; } $url = $navItem['returnUrl']; $params = array('fromNavId' => $this->_navId); if (isset($navItem['returnNavId'])) { $params['navId'] = $navItem['returnNavId']; } if (!empty($navItem['returnName'])) { $name = $core->translate(array('text' => 'Back to %s', 'arg1' => $navItem['returnName'])); } else { $name = $core->translate('Back'); } $url = GalleryUrlGenerator::appendParamsToUrl($url, $params); $links[] = array('url' => $url, 'name' => $name); } return array(null, $links); } /** * Decide whether to include session id in the URL. * * Force the session id in the URL for embedded DownloadItem URLs if the cookie.path plugin * parameter is not set. See GallerySession::init for details * * @param array $params (string param) * @return boolean forceSessionId * @access protected */ function embedForceSessionId($params) { if (isset($params['view']) && $params['view'] == 'core.DownloadItem' && GalleryUtilities::isEmbedded() && empty($this->_isCookiePathConfigured)) { /* * It is assumed that the Gallery session is initiated before generateUrl() is called * for the first time */ return true; } else { return false; } } } ?>