This repository has been archived on 2024-12-02. You can view files and clone it, but cannot push or open issues or pull requests.
AbetoArmarios_Web/Source/gallery2/modules/rewrite/classes/RewriteHelper.class

440 lines
14 KiB
Plaintext

<?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.
*/
/**
* URL rewrite helper.
* @package Rewrite
* @subpackage Classes
* @author Douglas Cau <douglas@cau.se>
* @version $Revision: 15865 $
* @static
*/
/* General status codes */
define('REWRITE_STATUS_OK', 0);
define('REWRITE_STATUS_BAD_KEYWORD', 1);
define('REWRITE_STATUS_MULTISITE', 2);
define('REWRITE_STATUS_DUPE_SHORT_URL', 3); /* Deprecated */
define('REWRITE_STATUS_INVALID_PATTERN', 4);
define('REWRITE_STATUS_EMPTY_VALUE', 5);
/**
* URL rewrite helper.
* @static
*/
class RewriteHelper {
/**
* Load and initialize the rewrite plugin. If no plugin has been configured yet it returns a
* GalleryStatus ERROR_MISSING_VALUE.
* @param boolean $new (optional) true if we need a new instance
* @return array object GalleryStatus a status code
* object RewritePlugin a loaded parser
*/
function getRewriteParser($new=false) {
global $gallery;
static $rewriteParser;
$platform =& $gallery->getPlatform();
if (!isset($rewriteParser) || $new) {
list ($ret, $rewriteParserId) = GalleryCoreApi::getPluginParameter(
'module', 'rewrite', 'parserId');
if ($ret) {
return array($ret, null);
}
if (empty($rewriteParserId)) {
return array(GalleryCoreApi::error(ERROR_MISSING_VALUE), null);
}
$path = 'modules/rewrite/classes/parsers/' . $rewriteParserId . '/parser.inc';
if ($platform->file_exists(
GalleryCoreApi::getPluginBaseDir('module', 'rewrite') . $path)) {
GalleryCoreApi::requireOnce($path);
}
$class = $rewriteParserId . 'Parser';
$rewriteParser = new $class();
}
return array(null, $rewriteParser);
}
/**
* Parse active rules into an array of regular expressions for parsing URLs during page requests
* and build an array for the URL generator to use when generating short URLs.
* @param array $activeRules array array ('pattern' => string pattern) active rules by reference
* @param object RewriteParser $rewriteParser
* @param object GalleryModule $upgradeModule (optional) passed in during activate / upgrade
* @param array $flags optional definition of default and mandatory flags
* @return array object GalleryStatus a status code
* int rewrite status code (REWRITE_STATUS_OK on success)
* array parsed patterns translated to regular expressions
* array short URLs which will used by to generate URLs
* array string module (on error)
* int rule id (on error)
*/
function parseActiveRules(&$activeRules, $rewriteParser, $upgradeModule=null, $flags=null) {
global $gallery;
$urlGenerator =& $gallery->getUrlGenerator();
/* Get access list information */
list ($ret, $accessList) = GalleryCoreApi::getPluginParameter(
'module', 'rewrite', 'accessList');
if ($ret) {
return array($ret, null, null, null, null);
}
$accessList = unserialize($accessList);
$ourHostNames[$urlGenerator->getHostName()] = true;
$ourHostNames[$urlGenerator->getHostName(true)] = true;
$accessList = array_merge($accessList, array_keys($ourHostNames));
/* Get allow empty referer */
list ($ret, $allowEmptyReferer) = GalleryCoreApi::getPluginParameter(
'module', 'rewrite', 'allowEmptyReferer');
if ($ret) {
return array($ret, null, null, null, null);
}
$regexRules = array();
$shortUrls = array();
foreach (array_keys($activeRules) as $moduleId) {
if (isset($upgradeModule) && $upgradeModule->getId() == $moduleId) {
/* Avoid PLUGIN_VERSION_MISMATCH during upgrade by passing in module */
$module = $upgradeModule;
} else {
list ($ret, $module) = GalleryCoreApi::loadPlugin('module', $moduleId);
if ($ret) {
if ($ret->getErrorCode() & ERROR_PLUGIN_VERSION_MISMATCH) {
/*
* Add CONFIGURATION_REQUIRED code to more gracefully abort upgrade if a
* dependent module for one of our rules also needs upgrading.
*/
$ret->addErrorCode(ERROR_CONFIGURATION_REQUIRED);
}
return array($ret, null, null, null, null);
}
}
$rules = $module->getRewriteRules();
foreach ($activeRules[$moduleId] as $ruleId => $activeRule) {
/* Make sure this rule still exists, if not silently continue */
if (!isset($rules[$ruleId])) {
unset($activeRules[$moduleId][$ruleId]);
continue;
}
/* Make sure this parser supports this kind of rule */
if (!$rewriteParser->isValidRule($rules[$ruleId], $activeRule)) {
return array(null, REWRITE_STATUS_INVALID_PATTERN,
null, null, array($moduleId, $ruleId));
}
/* Save the pattern for the URL generator to use */
if (isset($rules[$ruleId]['match']) && isset($activeRule['pattern'])) {
$shortUrl = array('match' => $rules[$ruleId]['match'],
'pattern' => $activeRule['pattern']);
/* Get custom function information */
if (!empty($rules[$ruleId]['keywords'])) {
foreach ($rules[$ruleId]['keywords'] as $key => $value) {
if (isset($value['function'])) {
$shortUrl['functions'][$key] = $value['function'];
}
}
}
/* Save the onLoad handler for this rule */
if (isset($rules[$ruleId]['onLoad'])) {
$shortUrl['onLoad'] = $rules[$ruleId]['onLoad'];
}
$shortUrls[] = $shortUrl;
}
/* Parse the pattern and create regular expressions with conditions */
if (empty($rules[$ruleId]['keywords'])) {
$rules[$ruleId]['keywords'] = array();
}
/* Add custom keywords to the list of allowed keywords */
if (!isset($rules[$ruleId]['keywords']['itemId'])) {
$rules[$ruleId]['keywords']['itemId'] = array('pattern' => '([0-9]+)');
}
/* Restrict this rule to given query string conditions */
if (!empty($rules[$ruleId]['restrict'])) {
foreach ($rules[$ruleId]['restrict'] as $key => $value) {
$rules[$ruleId]['conditions'][] = array(
'test' => 'QUERY_STRING',
'pattern' => $key . '=' . $value);
}
}
/* Exempt requests from the following hosts */
if (!empty($rules[$ruleId]['exemptReferer'])) {
foreach ($accessList as $host) {
$rules[$ruleId]['conditions'][] = array(
'test' => 'HTTP:Referer',
'pattern' => '!^[a-zA-Z0-9\\+\\.\\-]+://' . $host . '/',
'flags' => array('NC'));
}
/* Exempt requests with empty referer */
if (!empty($allowEmptyReferer)) {
$rules[$ruleId]['conditions'][] = array(
'test' => 'HTTP:Referer',
'pattern' => '!^$');
}
}
/* Build the query string to map the request on to */
if (empty($rules[$ruleId]['queryString'])) {
$rules[$ruleId]['queryString'] = array();
}
if (!empty($rules[$ruleId]['match'])) {
$rules[$ruleId]['queryString'] = array_merge(
$rules[$ruleId]['match'], $rules[$ruleId]['queryString']);
}
/* Options */
if (empty($rules[$ruleId]['options'])) {
$rules[$ruleId]['options'] = array();
}
/* Merge with default options. Later values override defaults. */
$rules[$ruleId]['options'] = array_merge(
array('forceDirect' => isset($rules[$ruleId]['queryString']['view'])
&& $rules[$ruleId]['queryString']['view'] == 'watermark.DownloadItem',
'forceServerRelativeUrl' => true,
'forceSessionId' => false,
'htmlEntities' => false,
'urlEncode' => false,
'useAuthToken' => false), $rules[$ruleId]['options']);
/* Build the list of flags to apply to this rule */
if (isset($rules[$ruleId]['flags']) && isset($flags)) {
$rules[$ruleId]['flags'] = array_merge(
$rules[$ruleId]['flags'], $flags['mandatory']);
} else if (isset($flags)){
$rules[$ruleId]['flags'] = $flags['default'];
} else {
$rules[$ruleId]['flags'] = array();
}
/* Make sure that there's no subrequest made when we match by the query string */
if (!empty($rules[$ruleId]['restrict'])) {
$rules[$ruleId]['flags'][] = 'L';
}
/* Ignore duplicate flags */
$rules[$ruleId]['flags'] = array_unique($rules[$ruleId]['flags']);
/* Parse the rule */
list ($ret, $code) = RewriteHelper::_parseRule(
$regexRules, $rules[$ruleId], $activeRule);
if ($ret) {
return array($ret, null, null, null, null);
}
if ($code != REWRITE_STATUS_OK) {
return array(null, $code, null, null, array($moduleId, $ruleId));
}
}
}
usort($regexRules, array('RewriteHelper', '_sortRules'));
return array(null, REWRITE_STATUS_OK, $regexRules, $shortUrls, null);
}
/**
* Replace keywords with appropriate pattern and append to $regexRules.
* @param array $regexRules of parsed rules
* @param array $rule rewrite rule
* @param array $activeRule array ('pattern' => string pattern)
* @return array object GalleryStatus a status code
* int rewrite status code (REWRITE_STATUS_OK on success)
* @access private
*/
function _parseRule(&$regexRules, $rule, $activeRule) {
$regexRule = array();
$regexRule['keywords'] = array();
$regexRule['queryString'] = $rule['queryString'];
$regexRule['options'] = $rule['options'];
$regexRule['flags'] = $rule['flags'];
/*
* Backreference 0 contains the text that matched the full pattern, backreference 1
* contains the text that matched the first parenthesized subpattern, and so on
*/
$regexRule['keywords'][] = null;
if (!empty($rule['conditions'])) {
$regexRule['conditions'] = array();
foreach ($rule['conditions'] as $condition) {
$code = RewriteHelper::_parseKeywords(
$regexRule, $condition['pattern'], $rule['keywords']);
if ($code != REWRITE_STATUS_OK) {
return array(null, $code);
}
$regexRule['conditions'][] = $condition;
}
}
if (!empty($activeRule['pattern'])) {
$regexRule['pattern'] = preg_quote($activeRule['pattern']);
$code = RewriteHelper::_parseKeywords(
$regexRule, $regexRule['pattern'], $rule['keywords']);
if ($code != REWRITE_STATUS_OK) {
return array(null, $code);
}
}
$regexRules[] = $regexRule;
return array(null, REWRITE_STATUS_OK);
}
/**
* Replace keywords with appropriate pattern and add backreference to $regexRule['keywords'].
* @param array $regexRule parsed rule
* @param array $pattern
* @param array $keywords of keywords => regular expresion for the htaccess file
* @return int rewrite status code (REWRITE_STATUS_OK on success)
* @access private
*/
function _parseKeywords(&$regexRule, &$pattern, $keywords) {
preg_match_all('/\%([^%]+)\%/', $pattern, $matches);
foreach ($matches[1] as $keyword) {
if (!isset($keywords[$keyword]['pattern'])) {
return REWRITE_STATUS_BAD_KEYWORD;
}
/* TODO: What if $pattern contains more than one instance of "%$keyword%"? */
$pattern = str_replace('%' . $keyword . '%', $keywords[$keyword]['pattern'], $pattern);
if (empty($keywords[$keyword]['ignore'])) {
$regexRule['keywords'][] = $keyword;
} else {
$regexRule['keywords'][] = null;
}
}
return REWRITE_STATUS_OK;
}
/**
* Comparison function used to order regex rules. Order rules from most specific to least
* specific.
* @param array $a first rule to compare
* @param array $b second rule to compare
* @return int an integer less than, equal to, or greater than zero if the first rule is
* considered to be respectively less than, equal to, or greater than the second
* @access private
*/
function _sortRules($a, $b) {
/* Flags: rules which don't allow subrequests come last */
if (in_array('L', $a['flags']) xor in_array('L', $b['flags'])) {
if (in_array('L', $b['flags'])) {
return -1;
}
return 1;
}
/* Conditions */
if (!empty($a['conditions']) || !empty($b['conditions'])) {
if (!empty($a['conditions']) && !empty($b['conditions'])) {
return count($a['conditions']) - count($b['conditions']);
}
if (!empty($a['conditions'])) {
return -1;
}
return 1;
}
/*
* Pattern: static patterns come before regex patterns, long patterns come before short
* patterns, empty patterns come last.
*/
if (!empty($a['pattern']) || !empty($b['pattern'])) {
if (!empty($a['pattern']) && !empty($b['pattern'])) {
if (count($a['keywords']) < 2 xor count($b['keywords']) < 2) {
if (count($a['keywords']) < 2) {
return -1;
}
return 1;
}
return strlen($b['pattern']) - strlen($a['pattern']);
}
if (!empty($a['pattern'])) {
return -1;
}
return 1;
}
return 0;
}
/**
* Get the rewrite rule history for a specific module.
* @param string $moduleId id of the module
* @return array object GalleryStatus a status code
* array (mixed ruleId => array ('pattern' => string pattern))
*/
function getHistoryForModule($moduleId) {
list ($ret, $history) = GalleryCoreApi::getPluginParameter(
'module', 'rewrite', 'history.' . $moduleId);
if ($ret) {
return array($ret, null);
}
$history = empty($history) ? array() : unserialize($history);
return array(null, $history);
}
/**
* Store the rewrite rule history for a specific module.
* @param string $moduleId id of the module
* @param array $history array (mixed ruleId => array ('pattern' => string pattern))
* @return object GalleryStatus a status code
*/
function setHistoryForModule($moduleId, $history) {
if (!empty($history)) {
$ret = GalleryCoreApi::setPluginParameter(
'module', 'rewrite', 'history.' . $moduleId, serialize($history));
} else {
$ret = GalleryCoreApi::removePluginParameter(
'module', 'rewrite', 'history.' . $moduleId);
}
if ($ret) {
return $ret;
}
return null;
}
}
?>