0byt3m1n1
Path:
/
data
/
applications
/
aps
/
gallery
/
2.2-08
/
standard
/
htdocs
/
modules
/
rewrite
/
classes
/
[
Home
]
File: RewriteHelper.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. */ /** * 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; } } ?>