From a878cdfc00ec4fdc501082cc353eb481a79550c7 Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Mon, 18 Jan 2016 11:33:47 +0900 Subject: [PATCH 01/12] Added simple URL routing feature to public_html/index.php --- public_html/index.php | 6 ++ system/classes/router.class.php | 167 ++++++++++++++++++++++++++++++++ system/lib-database.php | 1 + 3 files changed, 174 insertions(+) create mode 100644 system/classes/router.class.php diff --git a/public_html/index.php b/public_html/index.php index 0608aee55..ef5d883e9 100644 --- a/public_html/index.php +++ b/public_html/index.php @@ -83,6 +83,12 @@ function fixTopic(&$A, $tid_list) } } +// If URL routing is enabled, then let the router handle the request +if (isset($_CONF['url_routing']) && !empty($_CONF['url_routing'])) { + require_once $_CONF['path_system'] . 'classes/router.class.php'; + Router::dispatch(); +} + // See if user has access to view topic else display message. // This check has already been done in lib-common so re check to figure out if // 404 message needs to be displayed. diff --git a/system/classes/router.class.php b/system/classes/router.class.php new file mode 100644 index 000000000..2bbe336ba --- /dev/null +++ b/system/classes/router.class.php @@ -0,0 +1,167 @@ + Date: Wed, 20 Jan 2016 12:31:09 +0900 Subject: [PATCH 02/12] Added convertUrl method to Router class --- system/classes/router.class.php | 150 +++++++++++++++++++++++++++++--- 1 file changed, 136 insertions(+), 14 deletions(-) diff --git a/system/classes/router.class.php b/system/classes/router.class.php index 2bbe336ba..8c53c5888 100644 --- a/system/classes/router.class.php +++ b/system/classes/router.class.php @@ -17,6 +17,9 @@ class Router const ROUTING_WITH_INDEX_PHP = 1; const ROUTING_WITHOUT_INDEX_PHP = 2; + // Placeholder pattern + const PATTERN_PLACEHOLDER = '|(@[a-zA-Z][0-9a-zA-Z_-]*)|'; + /** * @var bool */ @@ -90,15 +93,17 @@ public static function dispatch() default: // Unsupported method COM_errorLog(__METHOD__ . ': unknown HTTP request method "' . $_SERVER['REQUEST_METHOD'] . '" was supplied'); + return false; } // Get routing rules and routes from database - $sql = "SELECT * FROM {$_TABLES['routes']} WHERE method = {$method} ORDER BY priority "; + $sql = "SELECT * FROM {$_TABLES['routes']} WHERE method = " . DB_escapeString($method) . " ORDER BY priority "; $result = DB_query($sql); if (DB_error()) { COM_errorLog(__METHOD__ . ': ' . DB_error()); + return false; } @@ -111,7 +116,21 @@ public static function dispatch() COM_errorLog(__METHOD__ . ': route = ' . $route); } - if (preg_match_all('|/(@[a-z][0-9a-z_.-]*)|i', $rule, $matches, PREG_SET_ORDER)) { + // Try simple comparison without placeholders + if (strcasecmp($rule, $pathInfo) === 0) { + if ($routingType === self::ROUTING_WITH_INDEX_PHP) { + $route = $_CONF['site_url'] . $route; + } + + if (self::$debug) { + COM_errorLog(__METHOD__ . ': matched with simple comparison rule "' . $A['rule'] . '"'); + } + + header('Location: ' . $route); + } + + // Try comparison with placeholders + if (preg_match_all(self::PATTERN_PLACEHOLDER, $rule, $matches, PREG_SET_ORDER)) { $placeHolders = array(); // Replace placeholders in a rule with ones for regular expressions @@ -139,29 +158,132 @@ public static function dispatch() } if ($routingType === self::ROUTING_WITH_INDEX_PHP) { - $route = $_CONF['site_url'] . $route; + $route = $_CONF['site_url'] . $route; } if (self::$debug) { - COM_errorLog(__METHOD__ . ': matched with regx "' . $rule . '"'); + COM_errorLog(__METHOD__ . ': matched with regular expression rule "' . $A['rule'] . '"'); } header('Location: ' . $route); - } else { - if (strcasecmp($rule, $pathInfo) === 0) { - if ($routingType === self::ROUTING_WITH_INDEX_PHP) { - $route = $_CONF['site_url'] . $route; - } + } + } + + return false; + } + + /** + * Convert a URL + * e.g. [SITE_URL]/article.php?story=welcome -> [SITE_URL]/index.php/article/welcome or [SITE_URL]/article/welcome + * + * @param string $url + * @param int $requestMethod + * @return string + */ + public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) + { + global $_CONF, $_TABLES; + + // URL routing is not supported + if (!isset($_CONF['url_routing'])) { + return $url; + } + + $routingType = intval($_CONF['url_routing'], 10); + + // URL routing is disabled + if ($routingType === self::ROUTING_DISABLED) { + return $url; + } elseif (self::$debug) { + COM_errorLog(__METHOD__ . ': routing type = ' . $routingType); + } + + // Strip $url of $_CONF['site_url'] + $url = str_ireplace($_CONF['site_url'], '', $url); + + // Check for $requestMethod + $requestMethod = intval($requestMethod, 10); + + if (($requestMethod < self::HTTP_REQUEST_GET) || ($requestMethod > self::HTTP_REQUEST_HEAD)) { + COM_errorLog(__METHOD__ . ': unknown request method "' . $requestMethod . '" was given'); + + return $url; + } + + // Get routing rules and routes from database + $sql = "SELECT * FROM {$_TABLES['routes']} WHERE method = " . DB_escapeString($requestMethod) . " ORDER BY priority "; + $result = DB_query($sql); + + if (DB_error()) { + COM_errorLog(__METHOD__ . ': ' . DB_error()); - if (self::$debug) { - COM_errorLog(__METHOD__ . ': matched with simple comparison "' . $rule . '"'); - } + return $url; + } + + while (($A = DB_fetchArray($result, false)) !== false) { + $rule = $A['rule']; + $route = $A['route']; + + if (self::$debug) { + COM_errorLog(__METHOD__ . ': rule = ' . $rule); + COM_errorLog(__METHOD__ . ': route = ' . $route); + } + + // Try simple comparison without placeholders + if (strcasecmp($route, $url) === 0) { + if ($routingType === self::ROUTING_WITH_INDEX_PHP) { + $rule = $_CONF['site_url'] . $rule; + } + + if (self::$debug) { + COM_errorLog(__METHOD__ . ': matched with simple comparison rule "' . $A['route'] . '"'); + } + + return $rule; + } + + // Try comparison with placeholders + if (preg_match_all(self::PATTERN_PLACEHOLDER, $route, $matches, PREG_SET_ORDER)) { + $placeHolders = array(); + + // Replace placeholders in a rule with ones for regular expressions + foreach ($matches as $match) { + $placeHolders[] = $match[1]; + $route = str_ireplace($match[1], '([^/]+)', $route); + } + + // Escape a period and a question mark so that they can safely be used in a regular expression + $route = str_replace(array('.', '?'), array('\.', '\?'), $route); + $route = '|' . $route . '|'; + + if (!preg_match($route, $url, $matches)) { + continue; + } - header('Location: ' . $route); + array_shift($matches); + + if (count($placeHolders) !== count($matches)) { + continue; } + + foreach ($matches as $match) { + $match = urlencode($match); + $placeHolder = array_shift($placeHolders); + $url = str_ireplace($placeHolder, $match, $url); + } + + if ($routingType === self::ROUTING_WITH_INDEX_PHP) { + $url = $_CONF['site_url'] . $url; + } + + if (self::$debug) { + COM_errorLog(__METHOD__ . ': matched with regular expression rule "' . $A['route'] . '"'); + } + + return $url; } } - return false; + return $url; } } From 7239b33623b9df04d69c8087d6d285d50952bfd7 Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Wed, 20 Jan 2016 14:07:29 +0900 Subject: [PATCH 03/12] COM_buildURL now builds a URL based on $_CONF['url_routing'] --- public_html/index.php | 3 +- public_html/lib-common.php | 5 +- system/classes/router.class.php | 32 +++- system/classes/url.class.php | 257 +++++++++++++++----------------- 4 files changed, 153 insertions(+), 144 deletions(-) diff --git a/public_html/index.php b/public_html/index.php index ef5d883e9..0b3d3a116 100644 --- a/public_html/index.php +++ b/public_html/index.php @@ -84,8 +84,7 @@ function fixTopic(&$A, $tid_list) } // If URL routing is enabled, then let the router handle the request -if (isset($_CONF['url_routing']) && !empty($_CONF['url_routing'])) { - require_once $_CONF['path_system'] . 'classes/router.class.php'; +if ($_CONF['url_rewrite'] && isset($_CONF['url_routing']) && !empty($_CONF['url_routing'])) { Router::dispatch(); } diff --git a/public_html/lib-common.php b/public_html/lib-common.php index 7aff2c940..ce5f6613e 100755 --- a/public_html/lib-common.php +++ b/public_html/lib-common.php @@ -199,8 +199,9 @@ * This provides optional URL rewriting functionality. */ -require_once( $_CONF['path_system'] . 'classes/url.class.php' ); -$_URL = new url( $_CONF['url_rewrite'] ); +require_once $_CONF['path_system'] . 'classes/router.class.php'; +require_once $_CONF['path_system'] . 'classes/url.class.php'; +$_URL = new Url($_CONF['url_rewrite'], $_CONF['url_routing']); /** * This is our HTML template class. It is the same one found in PHPLib and is diff --git a/system/classes/router.class.php b/system/classes/router.class.php index 8c53c5888..7d29d0ab8 100644 --- a/system/classes/router.class.php +++ b/system/classes/router.class.php @@ -44,6 +44,11 @@ public static function dispatch() { global $_CONF, $_TABLES; + // URL rewrite is disabled + if (!$_CONF['url_rewrite']) { + return false; + } + // URL routing is not supported if (!isset($_CONF['url_routing'])) { return false; @@ -184,6 +189,11 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) { global $_CONF, $_TABLES; + // URL rewrite is disabled + if (!$_CONF['url_rewrite']) { + return $url; + } + // URL routing is not supported if (!isset($_CONF['url_routing'])) { return $url; @@ -231,22 +241,26 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) // Try simple comparison without placeholders if (strcasecmp($route, $url) === 0) { + $retval = $rule; + if ($routingType === self::ROUTING_WITH_INDEX_PHP) { - $rule = $_CONF['site_url'] . $rule; + $retval = '/index.php' . $retval; } + $retval = $_CONF['site_url'] . $retval; + if (self::$debug) { - COM_errorLog(__METHOD__ . ': matched with simple comparison rule "' . $A['route'] . '"'); + COM_errorLog(__METHOD__ . ': matched with simple comparison route "' . $A['route'] . '"'); } - return $rule; + return $retval; } // Try comparison with placeholders if (preg_match_all(self::PATTERN_PLACEHOLDER, $route, $matches, PREG_SET_ORDER)) { $placeHolders = array(); - // Replace placeholders in a rule with ones for regular expressions + // Replace placeholders in a route with ones for regular expressions foreach ($matches as $match) { $placeHolders[] = $match[1]; $route = str_ireplace($match[1], '([^/]+)', $route); @@ -269,18 +283,22 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) foreach ($matches as $match) { $match = urlencode($match); $placeHolder = array_shift($placeHolders); - $url = str_ireplace($placeHolder, $match, $url); + $rule = str_ireplace($placeHolder, $match, $rule); } + $retval = $rule; + if ($routingType === self::ROUTING_WITH_INDEX_PHP) { - $url = $_CONF['site_url'] . $url; + $retval = '/index.php' . $retval; } + $retval = $_CONF['site_url'] . $retval; + if (self::$debug) { COM_errorLog(__METHOD__ . ': matched with regular expression rule "' . $A['route'] . '"'); } - return $url; + return $retval; } } diff --git a/system/classes/url.class.php b/system/classes/url.class.php index 482ce5b09..d858eb3c6 100644 --- a/system/classes/url.class.php +++ b/system/classes/url.class.php @@ -2,7 +2,7 @@ /* Reminder: always indent with 4 spaces (no tabs). */ // +---------------------------------------------------------------------------+ -// | Geeklog 1.8 | +// | Geeklog 2.1 | // +---------------------------------------------------------------------------+ // | url.class.php | // | | @@ -30,152 +30,103 @@ // +---------------------------------------------------------------------------+ /** -* This class will allow you to use friendlier URL's, like: -* http://www.example.com/index.php/arg_value_1/arg_value_2/ instead of -* uglier http://www.example.com?arg1=value1&arg2=value2. -* NOTE: this does not currently work under windows as there is a well documented -* bug with IIS and PATH_INFO. Not sure yet if this will work with windows under -* apache. This was built so you could use this class and just disable it -* if you are an IIS user. -* -* @author Tony Bibbs -* -*/ -class url { + * This class will allow you to use friendlier URL's, like: + * http://www.example.com/index.php/arg_value_1/arg_value_2/ instead of + * uglier http://www.example.com?arg1=value1&arg2=value2. + * NOTE: this does not currently work under windows as there is a well documented + * bug with IIS and PATH_INFO. Not sure yet if this will work with windows under + * apache. This was built so you could use this class and just disable it + * if you are an IIS user. + * + * @author Tony Bibbs + */ +class Url +{ /** - * @access private - */ - private $_arguments = array(); // Array of argument names + * @var array + */ + private $arguments = array(); // Array of argument names + /** - * @access private - */ - private $_enabled = true; + * @var bool + */ + private $urlRewrite = true; /** - * Constructor - * - * @param boolean $enabled whether rewriting is enabled - * - */ - function url($enabled=true) - { - $this->setEnabled($enabled); - $this->_arguments = array(); - if ($this->_enabled) { - $this->_getArguments(); - } - } + * @var int + */ + private $urlRouting; /** - * Grabs any variables from the query string - * - * @access private - */ - function _getArguments() + * Constructor + * + * @param bool $urlRewrite whether rewriting is enabled + * @param int $urlRouting URL routing mode, see Router class + */ + public function __construct($urlRewrite = true, $urlRouting = Router::ROUTING_DISABLED) { - if (isset($_SERVER['PATH_INFO'])) { - if ($_SERVER['PATH_INFO'] == '') { - if (isset($_ENV['ORIG_PATH_INFO'])) { - $this->_arguments = explode('/', $_ENV['ORIG_PATH_INFO']); - } else { - $this->_arguments = array(); - } - } else { - $this->_arguments = explode('/', $_SERVER['PATH_INFO']); - } - array_shift($this->_arguments); - } elseif (isset($_ENV['ORIG_PATH_INFO'])) { - $this->_arguments = explode('/', substr($_ENV['ORIG_PATH_INFO'], 1)); - } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { - $this->_arguments = explode('/', substr($_SERVER['ORIG_PATH_INFO'], 1)); - - // Added for IIS 7 to work in FastCGI mode - array_shift ($this->_arguments); - if ( $this->_arguments[0] == substr($_SERVER['SCRIPT_NAME'],1) ) { - array_shift($this->_arguments); - } - // end of add + $this->urlRewrite = (bool) $urlRewrite; + $urlRouting = intval($urlRouting, 10); + if (($urlRouting >= Router::ROUTING_DISABLED) && ($urlRouting <= Router::ROUTING_WITHOUT_INDEX_PHP)) { + $this->urlRouting = $urlRouting; } else { - $this->_arguments = array(); + $this->urlRouting = Router::ROUTING_DISABLED; } - } - /** - * Enables url rewriting, otherwise URL's are passed back - * - * @param boolean $switch turns URL rewriting on/off - * - */ - function setEnabled($switch) - { - if ($switch) { - $this->_enabled = true; - } else { - $this->_enabled = false; - } - } + $this->arguments = array(); - /** - * Returns whether or not URL rewriting is enabled - * - * @return boolean true if URl rewriting is enabled, otherwise false - * - */ - function isEnabled() - { - return $this->_enabled; + if ($this->urlRewrite) { + $this->getArguments(); + } } /** - * Returns the number of variables found in query string - * - * This is particularly useful just before calling setArgNames() method - * - * @return int Number of arguments found in URL - * - */ - function numArguments() + * Returns the number of variables found in query string + * This is particularly useful just before calling setArgNames() method + * + * @return int Number of arguments found in URL + */ + public function numArguments() { - return count($this->_arguments); + return count($this->arguments); } /** - * Assigns logical names to query string variables - * - * @param array $names String array of names to assign to variables pulled from query string - * @return boolean true on success otherwise false - * - */ - function setArgNames($names) + * Assigns logical names to query string variables + * + * @param array $names String array of names to assign to variables pulled from query string + * @return boolean true on success otherwise false + */ + public function setArgNames($names) { - if (count($names) < count($this->_arguments)) { + if (count($names) < count($this->arguments)) { print "URL Class: number of names passed to setArgNames must be equal or greater than number of arguments found in URL"; exit; } if (is_array($names)) { $newArray = array(); - for ($i = 1; $i <= count($this->_arguments); $i++) { - $newArray[current($names)] = current($this->_arguments); + for ($i = 1; $i <= count($this->arguments); $i++) { + $newArray[current($names)] = current($this->arguments); next($names); - next($this->_arguments); + next($this->arguments); } - $this->_arguments = $newArray; - reset($this->_arguments); + $this->arguments = $newArray; + reset($this->arguments); } else { return false; } + return true; } /** - * Gets the value for an argument - * - * @param string $name Name of argument to fetch value for - * @return mixed returns value for a given argument - * - */ - function getArgument($name) + * Gets the value for an argument + * + * @param string $name Name of argument to fetch value for + * @return mixed returns value for a given argument + */ + public function getArgument($name) { // if in GET VARS array return it if (!empty($_GET[$name])) { @@ -190,35 +141,43 @@ function getArgument($name) // end of add // ok, pull from query string - if (in_array($name,array_keys($this->_arguments))) { - return $this->_arguments[$name]; + if (in_array($name, array_keys($this->arguments))) { + return $this->arguments[$name]; } return ''; } /** - * Builds crawler friendly URL if URL rewriting is enabled - * - * This function will attempt to build a crawler friendly URL. If this feature is - * disabled because of platform issue it just returns original $url value - * - * @param string $url URL to try and convert - * @return string rewritten if _isenabled is true otherwise original url - * - */ - function buildURL($url) + * Builds crawler friendly URL if URL rewriting is enabled + * This function will attempt to build a crawler friendly URL. If this feature is + * disabled because of platform issue it just returns original $url value + * + * @param string $url URL to try and convert + * @return string rewritten if $this->urlRewrite is true otherwise original url + */ + public function buildURL($url) { - if (!$this->isEnabled()) { + if (!$this->urlRewrite) { return $url; } - $pos = strpos($url,'?'); - $query_string = substr($url,$pos+1); + if (($this->urlRouting === Router::ROUTING_WITH_INDEX_PHP) || + ($this->urlRouting === Router::ROUTING_WITHOUT_INDEX_PHP)) { + $newUrl = Router::convertUrl($url); + + if ($newUrl !== $url) { + return $newUrl; + } + } + + $pos = strpos($url, '?'); + $query_string = substr($url, $pos + 1); $finalList = array(); - $paramList = explode('&',$query_string); + $paramList = explode('&', $query_string); + for ($i = 1; $i <= count($paramList); $i++) { - $keyValuePairs = explode('=',current($paramList)); + $keyValuePairs = explode('=', current($paramList)); if (is_array($keyValuePairs)) { $argName = current($keyValuePairs); next($keyValuePairs); @@ -226,6 +185,7 @@ function buildURL($url) } next($paramList); } + $newArgs = '/'; for ($i = 1; $i <= count($finalList); $i++) { $newArgs .= current($finalList); @@ -234,8 +194,39 @@ function buildURL($url) } next($finalList); } - return str_replace('?' . $query_string,$newArgs,$url); + + return str_replace('?' . $query_string, $newArgs, $url); } -} -?> + /** + * Grabs any variables from the query string + */ + private function getArguments() + { + if (isset($_SERVER['PATH_INFO'])) { + if ($_SERVER['PATH_INFO'] == '') { + if (isset($_ENV['ORIG_PATH_INFO'])) { + $this->arguments = explode('/', $_ENV['ORIG_PATH_INFO']); + } else { + $this->arguments = array(); + } + } else { + $this->arguments = explode('/', $_SERVER['PATH_INFO']); + } + array_shift($this->arguments); + } elseif (isset($_ENV['ORIG_PATH_INFO'])) { + $this->arguments = explode('/', substr($_ENV['ORIG_PATH_INFO'], 1)); + } elseif (isset($_SERVER['ORIG_PATH_INFO'])) { + $this->arguments = explode('/', substr($_SERVER['ORIG_PATH_INFO'], 1)); + + // Added for IIS 7 to work in FastCGI mode + array_shift($this->arguments); + if ($this->arguments[0] == substr($_SERVER['SCRIPT_NAME'], 1)) { + array_shift($this->arguments); + } + // end of add + } else { + $this->arguments = array(); + } + } +} From 14d5cbbe96ebd8cc168be8a31049b2fbe75ae85a Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Wed, 20 Jan 2016 15:14:00 +0900 Subject: [PATCH 04/12] Added upgrading code --- language/english.php | 2 + language/english_utf-8.php | 2 + language/japanese_utf-8.php | 4 +- public_html/admin/install/config-install.php | 1 + public_html/admin/install/lib-upgrade.php | 9 +++++ sql/mssql_tableanddata.php | 21 ++++++++++ sql/mysql_tableanddata.php | 14 +++++++ sql/pgsql_tableanddata.php | 14 +++++++ sql/updates/mssql_2.1.0_to_2.1.2.php | 41 ++++++++++++++++++++ sql/updates/mysql_2.1.0_to_2.1.2.php | 34 ++++++++++++++++ sql/updates/pgsql_2.1.0_to_2.1.2.php | 34 ++++++++++++++++ 11 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 sql/updates/mssql_2.1.0_to_2.1.2.php create mode 100644 sql/updates/mysql_2.1.0_to_2.1.2.php create mode 100644 sql/updates/pgsql_2.1.0_to_2.1.2.php diff --git a/language/english.php b/language/english.php index 80ee576dd..5e7dffd63 100644 --- a/language/english.php +++ b/language/english.php @@ -2143,6 +2143,7 @@ 'censorlist' => "Censor List", 'ip_lookup' => "IP Lookup", 'url_rewrite' => "Enable URL Rewrite", + 'url_routing' => 'Enable URL routing', 'cdn_hosted' => "Use CDN-hosted copy of jQuery", 'meta_tags' => "Meta Tags", 'meta_description' => "Default Meta Description", @@ -2364,6 +2365,7 @@ 33 => array('Disabled' => 0, 'Enabled' => 1, 'Enabled (No Links)' => 2, 'Enabled (No Outbound Links)' => 3), 34 => array('grid' => 'grid', 'list' => 'list'), 35 => array('default' => 'default', 'Name (asc)' => 'NAME_ASC', 'Name (desc)' => 'NAME_DESC', 'Type (asc)' => 'TYPE_ASC', 'Type (desc)' => 'TYPE_DESC', 'Modified (asc)' => 'MODIFIED_ASC', 'Modified (desc)' => 'MODIFIED_DESC'), + 36 => array('Disabled' => 0, 'Enabled (with index.php)' => 1, 'Enabled (without index.php)' => 2), ); ################################################################################ diff --git a/language/english_utf-8.php b/language/english_utf-8.php index 27c414c06..f49480442 100644 --- a/language/english_utf-8.php +++ b/language/english_utf-8.php @@ -2143,6 +2143,7 @@ 'censorlist' => "Censor List", 'ip_lookup' => "IP Lookup", 'url_rewrite' => "Enable URL Rewrite", + 'url_routing' => 'Enable URL routing', 'cdn_hosted' => "Use CDN-hosted copy of jQuery", 'meta_tags' => "Meta Tags", 'meta_description' => "Default Meta Description", @@ -2364,6 +2365,7 @@ 33 => array('Disabled' => 0, 'Enabled' => 1, 'Enabled (No Links)' => 2, 'Enabled (No Outbound Links)' => 3), 34 => array('grid' => 'grid', 'list' => 'list'), 35 => array('default' => 'default', 'Name (asc)' => 'NAME_ASC', 'Name (desc)' => 'NAME_DESC', 'Type (asc)' => 'TYPE_ASC', 'Type (desc)' => 'TYPE_DESC', 'Modified (asc)' => 'MODIFIED_ASC', 'Modified (desc)' => 'MODIFIED_DESC'), + 36 => array('Disabled' => 0, 'Enabled (with index.php)' => 1, 'Enabled (without index.php)' => 2), ); ################################################################################ diff --git a/language/japanese_utf-8.php b/language/japanese_utf-8.php index 94a146111..a308caed2 100644 --- a/language/japanese_utf-8.php +++ b/language/japanese_utf-8.php @@ -2144,6 +2144,7 @@ 'censorlist' => 'バッドワード', 'ip_lookup' => 'IPアドレス検索', 'url_rewrite' => 'URLリライト', + 'url_routing' => 'URLルーティング', 'cdn_hosted' => 'CDNのjQueryを使用する', 'meta_tags' => 'メタタグ', 'meta_description' => 'サイトの説明文のメタタグ', @@ -2357,7 +2358,8 @@ 32 => array('表示しない' => 0, '記事のページにのみ表示する' => 1, '記事と話題の両方で表示する' => 2), 33 => array('無効にする' => 0, '有効にする' => 1, '有効にする(リンクなし)' => 2, '有効にする(外部リンクなし)' => 3), 34 => array('グリッド' => 'grid', 'リスト' => 'list'), - 35 => array('デフォルト' => 'default', '名前(昇順)' => 'NAME_ASC', '名前(降順)' => 'NAME_DESC', '種類(昇順)' => 'TYPE_ASC', '種類(降順)' => 'TYPE_DESC', '変更日時(昇順)' => 'MODIFIED_ASC', '変更日時(降順)' => 'MODIFIED_DESC') + 35 => array('デフォルト' => 'default', '名前(昇順)' => 'NAME_ASC', '名前(降順)' => 'NAME_DESC', '種類(昇順)' => 'TYPE_ASC', '種類(降順)' => 'TYPE_DESC', '変更日時(昇順)' => 'MODIFIED_ASC', '変更日時(降順)' => 'MODIFIED_DESC'), + 36 => array('無効にする' => 0, '有効にする(index.phpあり)' => 1, '有効にする(index.phpなし)' => 2), ); ############################################################################### diff --git a/public_html/admin/install/config-install.php b/public_html/admin/install/config-install.php index 4711168b1..82d4eda8e 100644 --- a/public_html/admin/install/config-install.php +++ b/public_html/admin/install/config-install.php @@ -57,6 +57,7 @@ function install_config() $c->add('owner_name','','text',0,0,NULL,1000,TRUE, $me, 0); $c->add('copyrightyear',date('Y'),'text',0,0,NULL,1440,FALSE, $me, 0); $c->add('url_rewrite',FALSE,'select',0,0,1,1800,TRUE, $me, 0); + $c->add('url_routing',FALSE,'select',0,0,36,1850,TRUE, $me, 0); $c->add('cdn_hosted',FALSE,'select',0,0,1,1900,TRUE, $me, 0); $c->add('meta_tags',0,'select',0,0,23,2000,TRUE, $me, 0); $c->add('meta_description','Geeklog - The secure Content Management System.','textarea',0,0,NULL,2010,TRUE, $me, 0); diff --git a/public_html/admin/install/lib-upgrade.php b/public_html/admin/install/lib-upgrade.php index 69b32e093..6accf9209 100644 --- a/public_html/admin/install/lib-upgrade.php +++ b/public_html/admin/install/lib-upgrade.php @@ -508,6 +508,15 @@ function INST_doDatabaseUpgrades($current_gl_version) $_SQL = ''; break; + case '2.1.0': + require_once $_CONF['path'] . 'sql/updates/' . $_DB_dbms . '_2.1.0_to_2.1.2.php'; + INST_updateDB($_SQL); + + update_ConfValuesFor212(); + $current_gl_version = '2.1.2'; + $_SQL = ''; + break; + default: $done = true; } diff --git a/sql/mssql_tableanddata.php b/sql/mssql_tableanddata.php index 18451b15c..de0dc6056 100644 --- a/sql/mssql_tableanddata.php +++ b/sql/mssql_tableanddata.php @@ -253,6 +253,15 @@ ) ON [PRIMARY] "; +$_SQL[] = "CREATE TABLE [dbo].[{$_TABLES['routes']}] ( + [rid] [int] NOT NULL IDENTITY (1, 1), + [method] [int] NOT NULL DEFAULT 1, + [rule] [varchar] (255) NOT NULL DEFAULT '', + [route] [varchar] (255) NOT NULL DEFAULT '', + [priority] [int] NOT NULL DEFAULT 100 +) ON [PRIMARY] +"; + $_SQL[] = " CREATE TABLE [dbo].[{$_TABLES['sessions']}] ( [sess_id] [numeric](10, 0) NOT NULL , @@ -654,6 +663,13 @@ ) ON [PRIMARY] "; +$_SQL[] = "ALTER TABLE [dbo].[{$_TABLES['routes']}] ADD + CONSTRAINT [PK_{$_TABLES['routes']}] PRIMARY KEY CLUSTERED + ( + [rid] + ) ON [PRIMARY] +"; + $_SQL[] = "ALTER TABLE [dbo].[{$_TABLES['sessions']}] ADD CONSTRAINT [PK_{$_TABLES['sessions']}] PRIMARY KEY CLUSTERED ( @@ -1521,6 +1537,11 @@ $_SQL[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text')"; $_SQL[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; + $_SQL[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First')"; $_SQL[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First')"; diff --git a/sql/mysql_tableanddata.php b/sql/mysql_tableanddata.php index ab289da99..b2c56caf8 100644 --- a/sql/mysql_tableanddata.php +++ b/sql/mysql_tableanddata.php @@ -250,6 +250,15 @@ ) ENGINE=MyISAM "; +$_SQL[] = "CREATE TABLE {$_TABLES['routes']} ( + `rid` int(11) NOT NULL AUTO_INCREMENT, + `method` int(11) NOT NULL DEFAULT '1', + `rule` varchar(255) NOT NULL DEFAULT '', + `route` varchar(255) NOT NULL DEFAULT '', + `priority` int(11) NOT NULL DEFAULT '100', + PRIMARY KEY (`rid`) +)"; + $_SQL[] = " CREATE TABLE {$_TABLES['sessions']} ( sess_id int(10) unsigned NOT NULL default '0', @@ -799,6 +808,11 @@ $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text') "; $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted') "; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; + $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First') "; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First') "; diff --git a/sql/pgsql_tableanddata.php b/sql/pgsql_tableanddata.php index a1c323429..2845ca5ab 100644 --- a/sql/pgsql_tableanddata.php +++ b/sql/pgsql_tableanddata.php @@ -249,6 +249,15 @@ ) "; +$_SQL[] = "CREATE TABLE {$_TABLES['routes']} ( + rid SERIAL, + method int NOT NULL DEFAULT 1, + rule varchar(255) NOT NULL DEFAULT '', + route varchar(255) NOT NULL DEFAULT '', + priority int NOT NULL DEFAULT 100, + PRIMARY KEY (rid) +)"; + $_SQL[] = " CREATE TABLE {$_TABLES['sessions']} ( sess_id int NOT NULL default '0', @@ -817,6 +826,11 @@ $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text') "; $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted') "; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; + $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First') "; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First') "; diff --git a/sql/updates/mssql_2.1.0_to_2.1.2.php b/sql/updates/mssql_2.1.0_to_2.1.2.php new file mode 100644 index 000000000..3dc2901d4 --- /dev/null +++ b/sql/updates/mssql_2.1.0_to_2.1.2.php @@ -0,0 +1,41 @@ +add('url_routing',FALSE,'select',0,0,36,1850,TRUE, $me, 0); + + return true; +} diff --git a/sql/updates/mysql_2.1.0_to_2.1.2.php b/sql/updates/mysql_2.1.0_to_2.1.2.php new file mode 100644 index 000000000..eb08b3ee3 --- /dev/null +++ b/sql/updates/mysql_2.1.0_to_2.1.2.php @@ -0,0 +1,34 @@ +add('url_routing',FALSE,'select',0,0,36,1850,TRUE, $me, 0); + + return true; +} diff --git a/sql/updates/pgsql_2.1.0_to_2.1.2.php b/sql/updates/pgsql_2.1.0_to_2.1.2.php new file mode 100644 index 000000000..06402dbbb --- /dev/null +++ b/sql/updates/pgsql_2.1.0_to_2.1.2.php @@ -0,0 +1,34 @@ +add('url_routing',FALSE,'select',0,0,36,1850,TRUE, $me, 0); + + return true; +} From d2cdb0267addbb4ed5cc4834c3a1e2c6a296d564 Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Wed, 20 Jan 2016 20:47:48 +0900 Subject: [PATCH 05/12] Added admin/router.php --- public_html/admin/router.php | 54 ++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 public_html/admin/router.php diff --git a/public_html/admin/router.php b/public_html/admin/router.php new file mode 100644 index 000000000..44f82fd2a --- /dev/null +++ b/public_html/admin/router.php @@ -0,0 +1,54 @@ + $MESSAGE[30]) + ); + COM_accessLog("User {$_USER['username']} tried to illegally access the URL routing administration screen"); + COM_output($display); + exit; +} + From 1d01e545e08c3912a4065546e0c03e666d65c09d Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Fri, 22 Jan 2016 15:01:55 +0900 Subject: [PATCH 06/12] Almost finished without documents --- language/english.php | 28 + language/english_utf-8.php | 28 + language/japanese_utf-8.php | 28 + public_html/admin/router.php | 510 +++++++++++++++++- .../modern_curve/admin/router/index.html | 0 .../admin/router/routereditor.thtml | 48 ++ .../modern_curve/images/icons/router.png | Bin 0 -> 2165 bytes public_html/lib-common.php | 19 +- system/classes/router.class.php | 121 +++-- 9 files changed, 722 insertions(+), 60 deletions(-) create mode 100644 public_html/layout/modern_curve/admin/router/index.html create mode 100644 public_html/layout/modern_curve/admin/router/routereditor.thtml create mode 100644 public_html/layout/modern_curve/images/icons/router.png diff --git a/language/english.php b/language/english.php index 5e7dffd63..0d7f06ef0 100644 --- a/language/english.php +++ b/language/english.php @@ -1336,6 +1336,31 @@ 55 => 'Articles' ); +############################################################################### +# admin/router.php + +$LANG_ROUTER = array( + 1 => 'URL routing', + 2 => 'Routing Manager', + 3 => 'ID', + 4 => 'method', + 5 => 'rule', + 6 => 'route', + 7 => 'priority', + 8 => 'Increase priority', + 9 => 'Decrease priority', + 10 => 'Edit routing', + 11 => 'To modify or delete a route, click on the route\'s edit icon below. To create a new route, click on "Create New" above. When you use placeholders (@), you must define the same placeholders in a rule and its route.', + 12 => 'Bad request method', + 13 => 'Rule is a mandatory item.', + 14 => 'Route is a mandatory item.', + 15 => 'Placeholders (@) in a rule and those in a route must be the same.', + 16 => 'Route must not start with "index.php".', + 17 => 'Database error occurred.', + 18 => 'To enable URL routing, you have to enable URL rewrite.', + 19 => '
  • Placeholders (@) must be the same both in a rule and its route.
  • A placeholder starts with "@", followed by an alphabet, optionally followed by any length of alphabet or digit.
  • Placeholders are case-sensitive.
', +); + ############################################################################### # confirmation and error messages @@ -1452,6 +1477,9 @@ 118 => 'Click to select a date', 119 => 'More..', 120 => 'Send this?', + 121 => 'Saved a URL routing item.', + 122 => 'Could not save a URL routing item.', + 123 => 'Deleted a URL routing item.', 400 => 'Not all required fields have been passed validation', // Error codes in the 400 range reserved for CUSTOM membership 401 => 'Please enter Fullname', 500 => 'The Template Cache has been successfully cleared.' diff --git a/language/english_utf-8.php b/language/english_utf-8.php index f49480442..d5e70af6d 100644 --- a/language/english_utf-8.php +++ b/language/english_utf-8.php @@ -1336,6 +1336,31 @@ 55 => 'Articles' ); +############################################################################### +# admin/router.php + +$LANG_ROUTER = array( + 1 => 'URL routing', + 2 => 'Routing Manager', + 3 => 'ID', + 4 => 'method', + 5 => 'rule', + 6 => 'route', + 7 => 'priority', + 8 => 'Increase priority', + 9 => 'Decrease priority', + 10 => 'Edit routing', + 11 => 'To modify or delete a route, click on the route\'s edit icon below. To create a new route, click on "Create New" above. When you use placeholders (@), you must define the same placeholders in a rule and its route.', + 12 => 'Bad request method', + 13 => 'Rule is a mandatory item.', + 14 => 'Route is a mandatory item.', + 15 => 'Placeholders (@) in a rule and those in a route must be the same.', + 16 => 'Route must not start with "index.php".', + 17 => 'Database error occurred.', + 18 => 'To enable URL routing, you have to enable URL rewrite.', + 19 => '
  • Placeholders (@) must be the same both in a rule and its route.
  • A placeholder starts with "@", followed by an alphabet, optionally followed by any length of alphabet or digit.
  • Placeholders are case-sensitive.
', +); + ############################################################################### # confirmation and error messages @@ -1452,6 +1477,9 @@ 118 => 'Click to select a date', 119 => 'More..', 120 => 'Send this?', + 121 => 'Saved a URL routing item.', + 122 => 'Could not save a URL routing item.', + 123 => 'Deleted a URL routing item.', 400 => 'Not all required fields have been passed validation', // Error codes in the 400 range reserved for CUSTOM membership 401 => 'Please enter Fullname', 500 => 'The Template Cache has been successfully cleared.' diff --git a/language/japanese_utf-8.php b/language/japanese_utf-8.php index a308caed2..285c3a132 100644 --- a/language/japanese_utf-8.php +++ b/language/japanese_utf-8.php @@ -1335,6 +1335,31 @@ 55 => '記事' ); +############################################################################### +# admin/router.php + +$LANG_ROUTER = array( + 1 => 'URLルーティング', + 2 => 'ルーティング管理', + 3 => 'ID', + 4 => 'メソッド', + 5 => 'ルール', + 6 => 'ルート', + 7 => '優先順位', + 8 => '優先順位を上げる', + 9 => '優先順位を下げる', + 10 => 'ルーティングの編集', + 11 => '

ルーティングの編集・削除は編集アイコンを、作成は上の「新規作成」をクリックしてください。優先順位の変更は、[↑][↓]をクリックしてください。

', + 12 => 'リクエストメソッドが不正です。', + 13 => 'ルールは必須項目です。', + 14 => 'ルートは必須項目です。', + 15 => 'ルールとルートで同じプレースホルダー(@)を定義しなければなりません。', + 16 => 'ルートの先頭にindex.phpを含むことはできません。', + 17 => 'データベース操作でエラーが発生しました。', + 18 => 'URLルーティングを有効にするには、URLリライトを有効にしてください。', + 19 => '
  • プレースホルダー(@)はルールとルートで同じものを定義してください。
  • プレースホルダーは@で始まり、1文字目は英字、2文字目以降は英数字を使えます。
  • プレースホルダーは大文字・小文字を区別します。
', +); + ############################################################################### # confirmation and error messages @@ -1451,6 +1476,9 @@ 118 => 'クリックして日付を選択してください', 119 => 'More..', 120 => 'この項目を送信しますか?', + 121 => 'URLルーティングのデータを保存しました。', + 122 => 'URLルーティングのデータを保存できませんでした。', + 123 => 'URLルーティングのデータを削除しました。', 400 => '検証に通っていない必須のフィールドがあります。', 401 => '氏名を入力してください。', 500 => 'テンプレートのキャッシュを削除しました。' diff --git a/public_html/admin/router.php b/public_html/admin/router.php index 44f82fd2a..b8786e9c1 100644 --- a/public_html/admin/router.php +++ b/public_html/admin/router.php @@ -33,16 +33,13 @@ * URL routing administration page: Create, edit, delete routing rules * for your Geeklog site. */ - // Geeklog common function library require_once '../lib-common.php'; // Security check to ensure user even belongs on this page require_once './auth.inc.php'; -$display = ''; - -if (!SEC_hasRights('url_routing.edit')) { +if (!SEC_inGroup('Root')) { $display = COM_createHTMLDocument( COM_showMessageText($MESSAGE[29], $MESSAGE[30]), array('pagetitle' => $MESSAGE[30]) @@ -52,3 +49,508 @@ exit; } +/** + * Shows the URL routing editor + * This will show a URL routing edit form. + * + * @param int $rid ID of URL routing rule to edit + * @return string HTML for URL routing editor + */ +function getRouteEditor($rid = 0) +{ + global $_CONF, $_TABLES, $LANG01, $LANG21, $LANG_ACCESS, $LANG_ROUTER, + $LANG_ADMIN, $MESSAGE, $_FINPUT, $securityToken; + + $retval = ''; + + $A = array( + 'rid' => $rid, + 'method' => Router::HTTP_REQUEST_GET, + 'rule' => '', + 'route' => '', + 'priority' => Router::DEFAULT_PRIORITY, + ); + $rid = intval($rid, 10); + + if ($rid > 0) { + if (DB_count($_TABLES['routes'], 'rid', $rid) == 1) { + $sql = "SELECT * FROM {$_TABLES['routes']} WHERE rid =" . DB_escapeString($rid); + $result = DB_query($sql); + $A = DB_fetchArray($result); + } else { + // Non-existent route + $rid = 0; + $A['rid'] = $rid; + } + } + + $T = COM_newTemplate($_CONF['path_layout'] . 'admin/router'); + $T->set_file('editor', 'routereditor.thtml'); + $routerStart = COM_startBlock($LANG_ROUTER[10], '', COM_getBlockTemplate('_admin_block', 'header')) + . LB . SEC_getTokenExpiryNotice($securityToken); + $T->set_var('start_router_editor', $routerStart); + + if ($rid > 0) { + $deleteButton = ''; + $jsConfirm = ' onclick="return confirm(\'' . $MESSAGE[76] . '\');"'; + $T->set_var(array( + 'delete_option' => sprintf($deleteButton, $jsConfirm), + 'delete_option_no_confirmation' => sprintf($deleteButton, ''), + )); + } + + $T->set_var(array( + 'rid' => $A['rid'], + 'method' => $A['method'], + 'rule' => $A['rule'], + 'route' => $A['route'], + 'priority' => $A['priority'], + 'gltoken_name' => CSRF_TOKEN, + 'gltoken' => $securityToken, + )); + $T->set_var(array( + 'lang_router_rid' => $LANG_ROUTER[3], + 'lang_router_method' => $LANG_ROUTER[4], + 'lang_router_rule' => $LANG_ROUTER[5], + 'lang_router_route' => $LANG_ROUTER[6], + 'lang_router_priority' => $LANG_ROUTER[7], + 'lang_router_notice' => $LANG_ROUTER[19], + 'lang_save' => $LANG_ADMIN['save'], + 'lang_cancel' => $LANG_ADMIN['cancel'], + )); + + $T->set_var( + 'end_block', + COM_endBlock(COM_getBlockTemplate('_admin_block', 'footer')) + ); + $T->parse('output', 'editor'); + $retval .= $T->finish($T->get_var('output')); + + return $retval; +} + +/** + * Field function + * + * @param string $fieldName + * @param string $fieldValue + * @param array $A + * @param array $iconArray + * @param string $extra + * @return string + * @throws InvalidArgumentException + */ +function ADMIN_getListFieldRoutes($fieldName, $fieldValue, $A, $iconArray, $extra = '') +{ + global $_CONF, $LANG_ROUTER, $_IMAGE_TYPE, $securityToken; + + switch ($fieldName) { + case 'rid': + $fieldValue = '' + . $iconArray['edit'] . ''; + break; + + case 'method': + switch (intval($fieldValue, 10)) { + case Router::HTTP_REQUEST_GET: + $fieldValue = 'GET'; + break; + + case Router::HTTP_REQUEST_POST: + $fieldValue = 'POST'; + break; + + case Router::HTTP_REQUEST_PUT: + $fieldValue = 'PUT'; + break; + + case Router::HTTP_REQUEST_DELETE: + $fieldValue = 'DELETE'; + break; + + case Router::HTTP_REQUEST_HEAD: + $fieldValue = 'HEAD'; + break; + + default: + throw new InvalidArgumentException(__FUNCTION__ . ': unknown method "' . $fieldValue . '" was given'); + } + + break; + + case 'rule': + break; + + case 'route': + break; + + case 'priority': + $rid = $A['rid']; + $baseUrl = $_CONF['site_admin_url'] . '/router.php?mode=move&rid=' . $rid . '&' + . CSRF_TOKEN . '=' . $securityToken; + $fieldValue = '' + . '' . $LANG_ROUTER[8] . '' + . $fieldValue + . '' + . '' . $LANG_ROUTER[9] . ''; + break; + + default: + throw new InvalidArgumentException(__FUNCTION__ . ': unknown field name "' . $fieldName . '" was given'); + } + + return $fieldValue; +} + +/** + * Display a list of routes + * + * @return string HTML for the list + */ +function listRoutes() +{ + global $_CONF, $_TABLES, $LANG_ADMIN, $LANG21, $LANG_ROUTER, $_IMAGE_TYPE, $securityToken; + + require_once $_CONF['path_system'] . 'lib-admin.php'; + + // Writing the menu on top + $menu_arr = array( + array( + 'url' => $_CONF['site_admin_url'] . '/router.php?mode=edit&rid=0', + 'text' => $LANG_ADMIN['create_new'], + ), + array( + 'url' => $_CONF['site_admin_url'], + 'text' => $LANG_ADMIN['admin_home'], + ), + ); + + $notice = $LANG_ROUTER[11]; + + if (!isset($_CONF['url_rewrite']) || empty($_CONF['url_rewrite'])) { + $notice .= ' ' . $LANG_ROUTER[18]; + } + + $retval = COM_startBlock($LANG_ROUTER[2], '', COM_getBlockTemplate('_admin_block', 'header')) + . ADMIN_createMenu( + $menu_arr, + $notice, + $_CONF['layout_url'] . '/images/icons/router.' . $_IMAGE_TYPE + ); + + $headerArray = array( # display 'text' and use table field 'field' + array( + 'text' => $LANG_ADMIN['edit'], + 'field' => 'rid', + 'sort' => false, + ), + array( + 'text' => $LANG_ROUTER[4], + 'field' => 'method', + 'sort' => true, + ), + array( + 'text' => $LANG_ROUTER[5], + 'field' => 'rule', + 'sort' => true, + ), + array( + 'text' => $LANG_ROUTER[6], + 'field' => 'route', + 'sort' => true, + ), + array( + 'text' => $LANG_ROUTER[7], + 'field' => 'priority', + 'sort' => true, + ), + ); + + $defaultSortArray = array( + 'field' => 'priority', + 'direction' => 'asc', + ); + + $textArray = array( + 'has_extras' => false, + 'title' => $LANG_ROUTER[1], + 'form_url' => $_CONF['site_admin_url'] . '/router.php', + ); + + $queryArray = array( + 'table' => 'routes', + 'sql' => "SELECT * FROM {$_TABLES['routes']} WHERE (1 = 1) ", + 'query_fields' => array('rule', 'route', 'priority'), + 'default_filter' => COM_getPermSql('AND'), + ); + + $retval .= ADMIN_list( + 'routes', 'ADMIN_getListFieldRoutes', $headerArray, $textArray, + $queryArray, $defaultSortArray, '', $securityToken, '' + ); + + $retval .= COM_endBlock(COM_getBlockTemplate('_admin_block', 'footer')); + + return $retval; +} + +/** + * Save a route into database + * + * @param int $rid + * @param int $method + * @param string $rule + * @param string $route + * @param int $priority + * @return string + */ +function saveRoute($rid, $method, $rule, $route, $priority) +{ + global $_CONF, $_TABLES, $MESSAGE, $LANG_ROUTER; + + $messageText = ''; + + $rid = intval($rid, 10); + $method = intval($method, 10); + $rule = trim($rule); + $route = trim($route); + $priority = intval($priority, 10); + + if (($method < Router::HTTP_REQUEST_GET) || ($method > Router::HTTP_REQUEST_HEAD)) { + $messageText = $LANG_ROUTER[12]; + } elseif ($rule === '') { + $messageText = $LANG_ROUTER[13]; + } elseif ($route === '') { + $messageText = $LANG_ROUTER[14]; + } elseif (substr_count($rule, '@') !== substr_count($route, '@')) { + $messageText = $LANG_ROUTER[15]; + } elseif (stripos($route, '/index.php') === 0) { + $messageText = $LANG_ROUTER[16]; + } + + // If rule doesn't begin with a slash, then fix it silently + if (strpos($rule, '/') !== 0) { + $rule = '/' . $rule; + } + + // If route doesn't begin with a slash, then fix it silently + if (strpos($route, '/') !== 0) { + $route = '/' . $route; + } + + // Replace & with & silently + $rule = str_ireplace('&', '&', $rule); + $route = str_ireplace('&', '&', $route); + + // Check if placeholders are the same + $numPlaceHoldersInRule = preg_match_all(Router::PATTERN_PLACEHOLDER, $rule, $matchesRule, PREG_SET_ORDER); + $numPlaceHoldersInRoute = preg_match_all(Router::PATTERN_PLACEHOLDER, $route, $matchesRoute, PREG_SET_ORDER); + + if ($numPlaceHoldersInRule === $numPlaceHoldersInRoute) { + if ($numPlaceHoldersInRule > 0) { + array_shift($matchesRule); + array_shift($matchesRoute); + + foreach ($matchesRule as $r) { + if (!in_array($r, $matchesRoute)) { + $messageText = $LANG_ROUTER[15]; + break; + } + } + } + } else { + $messageText = $LANG_ROUTER[15]; + } + + // If priority is out of range, then fix it silently + if (($priority < 1) || ($priority > 65535)) { + $priority = Router::DEFAULT_PRIORITY; + } + + if ($messageText !== '') { + $content = COM_showMessageText($messageText, $MESSAGE[122]) . getRouteEditor($rid); + $retval = COM_createHTMLDocument( + $content, + array( + 'pagetitle' => $MESSAGE[122], + ) + ); + + return $retval; + } + + // Save data into database + $rid = DB_escapeString($rid); + $method = DB_escapeString($method); + $rule = DB_escapeString($rule); + $route = DB_escapeString($route); + $priority = DB_escapeString($priority); + + $count = intval(DB_count($_TABLES['routes'], 'rid', $rid), 10); + + if ($count === 0) { + $sql = "INSERT INTO {$_TABLES['routes']} (rid, method, rule, route, priority) " + . "VALUES (NULL, {$method}, '{$rule}', '{$route}', {$priority})"; + } else { + $sql = "UPDATE {$_TABLES['routes']} " + . "SET method = {$method}, rule = '{$rule}', route = '{$route}', priority = {$priority} " + . "WHERE rid = {$rid} "; + } + + for ($i = 0; $i < 5; $i++) { + DB_query($sql); + + if (!DB_error()) { + reorderRoutes(); + + return COM_refresh($_CONF['site_admin_url'] . '/router.php?msg=121'); + } + + // Retry + } + + $content = COM_showMessageText($LANG_ROUTER[17], DB_error()) . getRouteEditor($rid); + $retval = COM_createHTMLDocument( + $content, + array( + 'pagetitle' => $MESSAGE[122], + ) + ); + + return $retval; +} + +/** + * Re-orders all routes in increments of 10 + */ +function reorderRoutes() +{ + global $_TABLES; + + $sql = "SELECT rid FROM {$_TABLES['routes']} ORDER BY priority"; + $result = DB_query($sql); + $rids = array(); + + while (($A = DB_fetchArray($result, false)) !== false) { + $rids[] = intval($A['rid'], 10); + } + + $priority = 100; + $step = 10; + + foreach ($rids as $rid) { + $sql = "UPDATE {$_TABLES['routes']} SET priority = " . DB_escapeString($priority) + . " WHERE rid = " . DB_escapeString($rid); + DB_query($sql); + $priority += $step; + } +} + +/** + * Move a route UP or Down + * + * @param int $rid + */ +function moveRoute($rid) +{ + global $_CONF, $_TABLES, $LANG_ROUTER, $_FINPUT; + + $rid = intval($rid, 10); + $direction = $_FINPUT->get('dir', ''); + + // if the router id exists + if (DB_count($_TABLES['routes'], 'rid', $rid)) { + $rid = DB_escapeString($rid); + + if ($direction === 'up') { + $sql = "UPDATE {$_TABLES['routes']} SET priority = priority - 11 WHERE rid = " . $rid; + DB_query($sql); + reorderRoutes(); + } elseif ($direction === 'down') { + $sql = "UPDATE {$_TABLES['routes']} SET priority = priority + 11 WHERE rid = " . $rid; + DB_query($sql); + reorderRoutes(); + } + } else { + COM_errorLog("block admin error: Attempt to move an non-existing route id: {$rid}"); + } +} + +/** + * Delete a route + * + * @param int $rid id of block to delete + * @return string HTML redirect or error message + */ +function deleteRoute($rid) +{ + global $_CONF, $_TABLES; + + $rid = intval($rid, 10); + DB_delete($_TABLES['routes'], 'rid', $rid); + reorderRoutes(); + + return COM_refresh($_CONF['site_admin_url'] . '/router.php?msg=123'); +} + +// MAIN +$display = ''; + +$mode = $_FINPUT->get('mode', $_FINPUT->post('mode', '')); +$rid = $_FINPUT->get('rid', $_FINPUT->post('rid', 0)); +$rid = intval($rid, 10); +$securityToken = SEC_createToken(); + +switch ($mode) { + case $LANG_ADMIN['delete']: + if ($rid === 0) { + COM_errorLog('Attempted to delete route, rid empty or null, value =' . $rid); + $display = COM_refresh($_CONF['site_admin_url'] . '/router.php'); + } elseif (SEC_checkToken()) { + $display = deleteRoute($rid); + } else { + COM_accessLog("User {$_USER['username']} tried to illegally delete route {$rid} and failed CSRF checks."); + $display = COM_refresh($_CONF['site_admin_url'] . '/index.php'); + } + + echo $display; + die(); + break; + + case $LANG_ADMIN['save']: + if (!SEC_checkToken()) { + COM_accessLog("User {$_USER['username']} tried to illegally save route {$rid} and failed CSRF checks."); + echo COM_refresh($_CONF['site_admin_url'] . '/index.php'); + die(); + } + + $method = $_FINPUT->post('method', ''); + $rule = $_INPUT->post('rule', ''); + $route = $_INPUT->post('route', ''); + $priority = $_FINPUT->post('priority', Router::DEFAULT_PRIORITY); + $display = saveRoute($rid, $method, $rule, $route, $priority); + break; + + case 'edit': + $content = getRouteEditor($rid); + $display = COM_createHTMLDocument($content, array('pagetitle' => $LANG_ROUTER[2])); + break; + + case 'move': + if (SEC_checkToken()) { + moveRoute($rid); + } + + $content = listRoutes(); + $display = COM_createHTMLDocument($content, array('pagetitle' => $LANG_ROUTER[2])); + break; + + default: // 'cancel' or no mode at all + $content = COM_showMessageFromParameter() . listRoutes(); + $display = COM_createHTMLDocument($content, array('pagetitle' => $LANG_ROUTER[2])); +} + +COM_output($display); diff --git a/public_html/layout/modern_curve/admin/router/index.html b/public_html/layout/modern_curve/admin/router/index.html new file mode 100644 index 000000000..e69de29bb diff --git a/public_html/layout/modern_curve/admin/router/routereditor.thtml b/public_html/layout/modern_curve/admin/router/routereditor.thtml new file mode 100644 index 000000000..59f0fe6b9 --- /dev/null +++ b/public_html/layout/modern_curve/admin/router/routereditor.thtml @@ -0,0 +1,48 @@ +{# begin {templatelocation} #} + +{start_router_editor} +
+
+
+
+
{rid}
+ +
+
+ +
+ +
+
+ +
+
+ +
+
+
+
+ +
+ {lang_router_notice} +
+ +
    +
  • +
  • +
  • + + + {delete_option} +
  • +
+
+{end_block} + +{# end {templatelocation} #} diff --git a/public_html/layout/modern_curve/images/icons/router.png b/public_html/layout/modern_curve/images/icons/router.png new file mode 100644 index 0000000000000000000000000000000000000000..d2647eee5127f7aebb368dbb1768897852b47dc9 GIT binary patch literal 2165 zcmV-*2#WWKP)Yx(&D1tptWIK#fHO%W zf(Bn0jR7t4SQeJ&t}M&GzS}=`B_;t{r}Z~;=YHQe=bZby=iKl94v)u=2>@gOJmVSh zkDJ88MNj`cdSXm;OLL0_fD?c;nj!a?iSRO+VrsZP?C5hVa!WNDO$>Y)`VIvDta|8q zG$|iJMx>w2MvbjxP-Thg8ef;`lXbg`v#Lkw>#Rvk40H9PU*9p9UtgN}> z(o2k(MW8y6Pf1M`SN&wQEG#T6#nRomQsBi}yWLJppIuU#oSal#R9G}|>5`>FNJy}t zRLDuLP(Z0vLa9`sufG?PB*Eo!!EPT!)|`35^y$+l{_EbIb-|$_4K2+r%|b~@iT>)< z%aH(qh(H{N2Rk8uW~{aWbXhvlBnU`MoF=~c#{P)>{Jf9TW z--ZZ?GsMGWYR7~C6?EDly!+m}?v{Hkt@#^X{(E?M_(uRfBgWX24^Mwsbg`~BVXVVy zwb^u?oo3_4jfFy(K8#MCItiQYJ_-w7fyL4Z#(8hKXn=mhTDQ539#O)X9qKzO>Agrh;80dMK{T zu*#~lo^`)m+tbj{@H%7cS;m-rtc{Ng##n;cY})g}4_CN078WqO-Ok$DTAAHG$POJT zcOO1-=mW;sYQ|XLLp~Y1%XZbiuyO_4^SiP-hr_XzF*a?q_~Tt--vANaVT?5hqBt-o zD=Tz(co-Zv9acq^K&MnHgVh=hyj}@B&!e}u2a-oJ00)LuYJYI0zDdfH0>Lh#MjLJ(xK zsbTt%qw^MIm1;DK82AMCJ9yxvf={^QqYMRrz=VW^_*v;Q-`iZYIYK6iBuNZ{D59d` zI0_4j_@<`Dr<6(sb#+;qJRT1RKm?$OiH@4FfB%7uq!~$xt!<`df*@Y*>FK!-pV*C* zivXxHGt;v*TJ5OnOGJu5wR)05A)lL{_p-uZh~xVEd!f?>;q*tR(bZ!{R^}WSo=8AN zMTPVI_y1;hx!q?Sj-eI+P{`%K*thSGYNOGJ-rioeX;YE2wWXz`rl#%)fFAf;3j&~i zX33&0PcO(W%FfP)BuPHaflm_zo`+hkfmW-9)9HZSZiiB-g3V^bp1ozPu&|K&t$pBm z4&nMJsFW&nn$57=hekx)U@)N7)C`p}0Q%5y9C+)1v#PSH?$*sO^GqgFGXNXy*s&v_ zrL}o`K|$f_sK`h-ox|Wb9>fti;s639uLQT-4I&^QAP_d2jcqU9HrQ?HZdQ{J z8;?p6fcPhj2-bx_CW=0PNRSvCiTCvwITl#9Y*}1!aj|yfcdD%V7&!}n0EtN;0yy%O zMv@q;R;%}mFK&42>T0EF(-JT2E&Kg(jYe}60Nb@|x8>ZqsvA3Z?#%H@o~WFhMTm}y z=GAKTgI)r$F|oMUeisu|0SFI`#KE@@dcJDB-CX|m;bT!zQD=zg7BR-YS6N+IaOKKn z<7kIfCdxcooz9vN7jMbP$h^*R+ywyFA6!t3F#<3NK)T6fN~o@`j_c~`)L5<7005}1 zyO6nW-ydL1Frufo2ivx7b zX#jvo02=sy-`LX9-9KIa-12Ob$t0DRm-lTfDEv!GO3FC^XNhQ}85jIJ`*OSm{#y{y zAb`e)h>_JcFk!=nJR~QlTs(Z}&?%*I!Usfj>)XDMDteC!YkXY1Ic-+@JGr^Jp8z;X rM7GfkX|#|3FZjzo)&F{PJmLE{mE3gB8B_p?00000NkvXXu0mjfiPZ`3 literal 0 HcmV?d00001 diff --git a/public_html/lib-common.php b/public_html/lib-common.php index ce5f6613e..5c7fe2138 100755 --- a/public_html/lib-common.php +++ b/public_html/lib-common.php @@ -3371,7 +3371,7 @@ function COM_userMenu( $help='', $title='', $position='' ) function COM_commandControl($adminMenu = false, $help = '', $title = '', $position = '') { global $_CONF, $_CONF_FT, $_TABLES, $LANG01, $LANG29, $LANG_LOGVIEW, - $LANG_ENVCHECK, $LANG_ADMIN, $_IMAGE_TYPE, $_DB_dbms, $config;; + $LANG_ENVCHECK, $LANG_ADMIN, $_IMAGE_TYPE, $LANG_ROUTER, $_DB_dbms, $config;; $retval = ''; @@ -3645,6 +3645,18 @@ function COM_commandControl($adminMenu = false, $help = '', $title = '', $positi } } + $routeCount = '0'; + if ($adminMenu && SEC_inGroup('Root')) { + // Find num of URL routes + $sql = "SELECT COUNT(rid) AS cnt FROM {$_TABLES['routes']}"; + $result = DB_query($sql); + + if (!DB_error()) { + $temp = DB_fetchArray($result, false); + $routeCount = COM_numberFormat($temp['cnt']); + } + } + $cc_arr = array( array('condition' => SEC_hasRights($_CONF_FT, 'OR'), 'url' => $_CONF['site_admin_url'] . '/configuration.php', @@ -3690,6 +3702,11 @@ function COM_commandControl($adminMenu = false, $help = '', $title = '', $positi 'num' => '', 'image' => $_CONF['layout_url'] . '/images/icons/filemanager.' . $_IMAGE_TYPE, 'target' => '_blank'), + array('condition' => SEC_inGroup('Root'), + 'url' => $_CONF['site_admin_url'] . '/router.php', + 'lang' => $LANG_ROUTER[1], + 'num' => $routeCount, + 'image' => $_CONF['layout_url'] . '/images/icons/router.' . $_IMAGE_TYPE), array('condition' => true, 'url' =>$_CONF['site_url'] . '/users.php?mode=logout', 'lang' => $LANG01[35], diff --git a/system/classes/router.class.php b/system/classes/router.class.php index 7d29d0ab8..67c06a47e 100644 --- a/system/classes/router.class.php +++ b/system/classes/router.class.php @@ -18,12 +18,15 @@ class Router const ROUTING_WITHOUT_INDEX_PHP = 2; // Placeholder pattern - const PATTERN_PLACEHOLDER = '|(@[a-zA-Z][0-9a-zA-Z_-]*)|'; + const PATTERN_PLACEHOLDER = '|(@[a-zA-Z][0-9a-zA-Z_]*)|'; + + // Default priority + const DEFAULT_PRIORITY = 100; /** * @var bool */ - private static $debug = false; + private static $debug = true; /** * Set debug mode @@ -42,7 +45,7 @@ public static function setDebug($switch) */ public static function dispatch() { - global $_CONF, $_TABLES; + global $_CONF, $_TABLES, $LANG_ROUTER; // URL rewrite is disabled if (!$_CONF['url_rewrite']) { @@ -59,8 +62,6 @@ public static function dispatch() // URL routing is disabled if ($routingType === self::ROUTING_DISABLED) { return false; - } elseif (self::$debug) { - COM_errorLog(__METHOD__ . ': routing type = ' . $routingType); } // $_SERVER['PATH_INFO'] is unavailable @@ -116,58 +117,60 @@ public static function dispatch() $rule = $A['rule']; $route = $A['route']; - if (self::$debug) { - COM_errorLog(__METHOD__ . ': rule = ' . $rule); - COM_errorLog(__METHOD__ . ': route = ' . $route); - } - // Try simple comparison without placeholders if (strcasecmp($rule, $pathInfo) === 0) { - if ($routingType === self::ROUTING_WITH_INDEX_PHP) { - $route = $_CONF['site_url'] . $route; - } + $route = $_CONF['site_url'] . $route; if (self::$debug) { - COM_errorLog(__METHOD__ . ': matched with simple comparison rule "' . $A['rule'] . '"'); + COM_errorLog(__METHOD__ . ': "' . $pathInfo . '"matched with simple comparison rule "' . $A['rule'] . '", converted into "' . $route . '"'); } header('Location: ' . $route); + + COM_errorLog(__METHOD__ . ': somehow could not redirect'); + return false; } // Try comparison with placeholders if (preg_match_all(self::PATTERN_PLACEHOLDER, $rule, $matches, PREG_SET_ORDER)) { + // Escape a period and a question mark so that they can safely be used in a regular expression + $rule = str_replace(array('.', '?'), array('\.', '\?'), $rule); $placeHolders = array(); // Replace placeholders in a rule with ones for regular expressions foreach ($matches as $match) { $placeHolders[] = $match[1]; - $rule = str_ireplace($match[1], '([^/]+)', $rule); + $rule = str_replace($match[1], '([^/&=?#]+)', $rule); } - $rule = '|' . $rule . '|i'; + $rule = '|\A' . $rule . '\z|i'; - if (!preg_match($rule, $pathInfo, $matches)) { + if (!preg_match($rule, $pathInfo, $values)) { continue; } - array_shift($matches); - - if (count($placeHolders) !== count($matches)) { - continue; - } + array_shift($values); - foreach ($matches as $match) { - $match = urlencode($match); + foreach ($values as $value) { + $value = urlencode($value); $placeHolder = array_shift($placeHolders); - $route = str_ireplace($placeHolder, $match, $route); + $route = str_replace($placeHolder, $value, $route); } - if ($routingType === self::ROUTING_WITH_INDEX_PHP) { - $route = $_CONF['site_url'] . $route; + if ((strpos($route, '@') !== false) && self::$debug) { + COM_errorLog( + sprintf( + '%s: %s. Rule (rid = %d) = %s, Route = %s', + __METHOD__, @$LANG_ROUTER[15], $A['rid'], $A['rule'], $A['route'] + ) + ); + continue; } + $route = $_CONF['site_url'] . $route; + if (self::$debug) { - COM_errorLog(__METHOD__ . ': matched with regular expression rule "' . $A['rule'] . '"'); + COM_errorLog(__METHOD__ . ': "' . $pathInfo . '" matched with regular expression rule "' . $A['rule'] . '", converted into "' . $route . '"'); } header('Location: ' . $route); @@ -179,6 +182,7 @@ public static function dispatch() /** * Convert a URL + * * e.g. [SITE_URL]/article.php?story=welcome -> [SITE_URL]/index.php/article/welcome or [SITE_URL]/article/welcome * * @param string $url @@ -187,29 +191,29 @@ public static function dispatch() */ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) { - global $_CONF, $_TABLES; + global $_CONF, $_TABLES, $LANG_ROUTER; + + $originalUrl = $url; // URL rewrite is disabled if (!$_CONF['url_rewrite']) { - return $url; + return $originalUrl; } // URL routing is not supported if (!isset($_CONF['url_routing'])) { - return $url; + return $originalUrl; } $routingType = intval($_CONF['url_routing'], 10); // URL routing is disabled if ($routingType === self::ROUTING_DISABLED) { - return $url; - } elseif (self::$debug) { - COM_errorLog(__METHOD__ . ': routing type = ' . $routingType); + return $originalUrl; } // Strip $url of $_CONF['site_url'] - $url = str_ireplace($_CONF['site_url'], '', $url); + $url = str_replace($_CONF['site_url'], '', $url); // Check for $requestMethod $requestMethod = intval($requestMethod, 10); @@ -217,7 +221,7 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) if (($requestMethod < self::HTTP_REQUEST_GET) || ($requestMethod > self::HTTP_REQUEST_HEAD)) { COM_errorLog(__METHOD__ . ': unknown request method "' . $requestMethod . '" was given'); - return $url; + return $originalUrl; } // Get routing rules and routes from database @@ -227,21 +231,21 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) if (DB_error()) { COM_errorLog(__METHOD__ . ': ' . DB_error()); - return $url; + return $originalUrl; } + $url = str_replace('&', '&', $url); + $path = $url; + while (($A = DB_fetchArray($result, false)) !== false) { + $url = $path; $rule = $A['rule']; $route = $A['route']; - if (self::$debug) { - COM_errorLog(__METHOD__ . ': rule = ' . $rule); - COM_errorLog(__METHOD__ . ': route = ' . $route); - } - // Try simple comparison without placeholders if (strcasecmp($route, $url) === 0) { $retval = $rule; + $retval = str_replace('&', '&', $retval); if ($routingType === self::ROUTING_WITH_INDEX_PHP) { $retval = '/index.php' . $retval; @@ -250,7 +254,7 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) $retval = $_CONF['site_url'] . $retval; if (self::$debug) { - COM_errorLog(__METHOD__ . ': matched with simple comparison route "' . $A['route'] . '"'); + COM_errorLog(__METHOD__ . ': "' . $originalUrl . '" matched with simple comparison route "' . $A['route'] . '"'); } return $retval; @@ -263,30 +267,37 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) // Replace placeholders in a route with ones for regular expressions foreach ($matches as $match) { $placeHolders[] = $match[1]; - $route = str_ireplace($match[1], '([^/]+)', $route); + $route = str_replace($match[1], '([^/&=?#]+)', $route); } // Escape a period and a question mark so that they can safely be used in a regular expression $route = str_replace(array('.', '?'), array('\.', '\?'), $route); - $route = '|' . $route . '|'; + $route = '|\A' . $route . '\z|i'; - if (!preg_match($route, $url, $matches)) { + if (!preg_match($route, $url, $values)) { continue; } - array_shift($matches); + array_shift($values); - if (count($placeHolders) !== count($matches)) { - continue; + foreach ($values as $value) { + $value = urlencode($value); + $placeHolder = array_shift($placeHolders); + $rule = str_replace($placeHolder, $value, $rule); } - foreach ($matches as $match) { - $match = urlencode($match); - $placeHolder = array_shift($placeHolders); - $rule = str_ireplace($placeHolder, $match, $rule); + if ((strpos($rule, '@') !== false) && self::$debug) { + COM_errorLog( + sprintf( + '%s: %s. Rule (rid = %d) = %s, Route = %s', + __METHOD__, @$LANG_ROUTER[15], $A['rid'], $A['rule'], $A['route'] + ) + ); + continue; } $retval = $rule; + $retval = str_replace('&', '&', $retval); if ($routingType === self::ROUTING_WITH_INDEX_PHP) { $retval = '/index.php' . $retval; @@ -295,13 +306,13 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) $retval = $_CONF['site_url'] . $retval; if (self::$debug) { - COM_errorLog(__METHOD__ . ': matched with regular expression rule "' . $A['route'] . '"'); + COM_errorLog(__METHOD__ . ': "' . $originalUrl . '" matched with regular expression rule "' . $A['route'] . '", converted into "' . $retval . '"'); } return $retval; } } - return $url; + return $originalUrl; } } From eda050eec30f2673a1422d817e6906d2534d7b9f Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Fri, 22 Jan 2016 18:31:17 +0900 Subject: [PATCH 07/12] Modified initial database entries --- sql/mssql_tableanddata.php | 3 +-- sql/mysql_tableanddata.php | 3 +-- sql/pgsql_tableanddata.php | 3 +-- sql/updates/mssql_2.1.0_to_2.1.2.php | 3 +-- sql/updates/mysql_2.1.0_to_2.1.2.php | 3 +-- sql/updates/pgsql_2.1.0_to_2.1.2.php | 3 +-- system/classes/router.class.php | 2 +- 7 files changed, 7 insertions(+), 13 deletions(-) diff --git a/sql/mssql_tableanddata.php b/sql/mssql_tableanddata.php index de0dc6056..55784377e 100644 --- a/sql/mssql_tableanddata.php +++ b/sql/mssql_tableanddata.php @@ -1537,10 +1537,9 @@ $_SQL[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text')"; $_SQL[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; $_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_SQL[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First')"; $_SQL[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First')"; diff --git a/sql/mysql_tableanddata.php b/sql/mysql_tableanddata.php index b2c56caf8..649ec00ae 100644 --- a/sql/mysql_tableanddata.php +++ b/sql/mysql_tableanddata.php @@ -808,10 +808,9 @@ $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text') "; $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted') "; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; $_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First') "; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First') "; diff --git a/sql/pgsql_tableanddata.php b/sql/pgsql_tableanddata.php index 2845ca5ab..0f7901e3e 100644 --- a/sql/pgsql_tableanddata.php +++ b/sql/pgsql_tableanddata.php @@ -826,10 +826,9 @@ $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text') "; $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted') "; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; $_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First') "; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First') "; diff --git a/sql/updates/mssql_2.1.0_to_2.1.2.php b/sql/updates/mssql_2.1.0_to_2.1.2.php index 3dc2901d4..e67149593 100644 --- a/sql/updates/mssql_2.1.0_to_2.1.2.php +++ b/sql/updates/mssql_2.1.0_to_2.1.2.php @@ -18,10 +18,9 @@ "; // Add sample routes to the table -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; $_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; /** * Add new config options diff --git a/sql/updates/mysql_2.1.0_to_2.1.2.php b/sql/updates/mysql_2.1.0_to_2.1.2.php index eb08b3ee3..ac18d1125 100644 --- a/sql/updates/mysql_2.1.0_to_2.1.2.php +++ b/sql/updates/mysql_2.1.0_to_2.1.2.php @@ -11,10 +11,9 @@ )"; // Add sample routes to the table -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; $_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; /** * Add new config options diff --git a/sql/updates/pgsql_2.1.0_to_2.1.2.php b/sql/updates/pgsql_2.1.0_to_2.1.2.php index 06402dbbb..436b4d4c4 100644 --- a/sql/updates/pgsql_2.1.0_to_2.1.2.php +++ b/sql/updates/pgsql_2.1.0_to_2.1.2.php @@ -11,10 +11,9 @@ )"; // Add sample routes to the table -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/stats', '/stats.php')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; $_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; $_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; /** * Add new config options diff --git a/system/classes/router.class.php b/system/classes/router.class.php index 67c06a47e..5016a5707 100644 --- a/system/classes/router.class.php +++ b/system/classes/router.class.php @@ -26,7 +26,7 @@ class Router /** * @var bool */ - private static $debug = true; + private static $debug = false; /** * Set debug mode From 10e19a355cd9dfaf2c9ec1bc04327a0a3da70ffd Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Sat, 23 Jan 2016 13:26:57 +0900 Subject: [PATCH 08/12] Added documents --- public_html/admin/router.php | 26 +++--- public_html/docs/english/config.html | 110 ++++++++++++++++++++++++++ public_html/docs/japanese/config.html | 109 +++++++++++++++++++++++++ sql/mssql_tableanddata.php | 10 ++- sql/mysql_tableanddata.php | 10 ++- sql/pgsql_tableanddata.php | 10 ++- sql/updates/mssql_2.1.0_to_2.1.2.php | 10 ++- sql/updates/mysql_2.1.0_to_2.1.2.php | 10 ++- sql/updates/pgsql_2.1.0_to_2.1.2.php | 10 ++- 9 files changed, 278 insertions(+), 27 deletions(-) diff --git a/public_html/admin/router.php b/public_html/admin/router.php index b8786e9c1..349ce1541 100644 --- a/public_html/admin/router.php +++ b/public_html/admin/router.php @@ -58,8 +58,7 @@ */ function getRouteEditor($rid = 0) { - global $_CONF, $_TABLES, $LANG01, $LANG21, $LANG_ACCESS, $LANG_ROUTER, - $LANG_ADMIN, $MESSAGE, $_FINPUT, $securityToken; + global $_CONF, $_TABLES, $LANG_ROUTER, $LANG_ADMIN, $MESSAGE, $securityToken; $retval = ''; @@ -212,7 +211,7 @@ function ADMIN_getListFieldRoutes($fieldName, $fieldValue, $A, $iconArray, $extr */ function listRoutes() { - global $_CONF, $_TABLES, $LANG_ADMIN, $LANG21, $LANG_ROUTER, $_IMAGE_TYPE, $securityToken; + global $_CONF, $_TABLES, $LANG_ADMIN, $LANG_ROUTER, $_IMAGE_TYPE, $securityToken; require_once $_CONF['path_system'] . 'lib-admin.php'; @@ -327,21 +326,30 @@ function saveRoute($rid, $method, $rule, $route, $priority) $messageText = $LANG_ROUTER[14]; } elseif (substr_count($rule, '@') !== substr_count($route, '@')) { $messageText = $LANG_ROUTER[15]; - } elseif (stripos($route, '/index.php') === 0) { - $messageText = $LANG_ROUTER[16]; } - // If rule doesn't begin with a slash, then fix it silently + // If a rule doesn't begin with a slash, then add one silently if (strpos($rule, '/') !== 0) { $rule = '/' . $rule; } - // If route doesn't begin with a slash, then fix it silently + // If a rule starts with "/index.php", then remove it silently + if (stripos($rule, '/index.php') === 0) { + $rule = preg_replace('|^/index\.php|i', '', $rule); + } + + // If a route doesn't begin with a slash, then add one silently if (strpos($route, '/') !== 0) { $route = '/' . $route; } - // Replace & with & silently + // If a route starts with "/index.php", then make it an error to prevent the script + // from going an infinite loop + if (stripos($route, '/index.php') === 0) { + $messageText = $LANG_ROUTER[16]; + } + + // Replace & with & $rule = str_ireplace('&', '&', $rule); $route = str_ireplace('&', '&', $route); @@ -456,7 +464,7 @@ function reorderRoutes() */ function moveRoute($rid) { - global $_CONF, $_TABLES, $LANG_ROUTER, $_FINPUT; + global $_TABLES, $_FINPUT; $rid = intval($rid, 10); $direction = $_FINPUT->get('dir', ''); diff --git a/public_html/docs/english/config.html b/public_html/docs/english/config.html index 402d401f5..6bbf2c67d 100644 --- a/public_html/docs/english/config.html +++ b/public_html/docs/english/config.html @@ -95,6 +95,11 @@

Site: Site

false Enable (true) or disable (false) URL rewriting.
Also see the section on URL Rewriting below. + + url_routing + disabled(0) + Enable (true) or disable (false) URL routing. Caution: This feature takes effect only when URL Rewriting is enabled.
+ Also see the section on URL Routing below. cdn_hosted false @@ -2088,6 +2093,111 @@

URL Rewriting

with your site.

+

URL Routing

+ +

This feature enhances the above URL Rewriting feature and makes + public_html/index.php work like a front controller. So, in order to use URL Routing feature, + you have to enable URL Rewriting beforehand. Currently, the following rules are predefined.

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
RuleRoutePriority
http://yourdomain/article/[sid]/printhttp://yourdomain/article.php?story=[sid]&mode=print100
http://yourdomain/article/[sid]http://yourdomain/article.php?story=[sid]110
http://yourdomain/archives/@topic/@year/@monthhttp://yourdomain/directory.php?topic=@topic&year=@year&month=@month120
http://yourdomain/page/@pagehttp://yourdomain/staticpages/index.php?page=@page130
http://yourdomain/links/portal/@itemhttp://yourdomain/links/portal.php?what=link&item=@item140
http://yourdomain/links/category/@cathttp://yourdomain/links/index.php?category=@cat150
http://yourdomain/topic/@topichttp://yourdomain/index.php?topic=@topic160
+ +

Look at the first row in the table. This means if you access "http://yourdomain/index.php/article/[sid]/print", + then you will be redirected to "http://yourdomain/article.php?story=[sid]&mode=print". + [sid] is a story ID.

+

Then, look at the third row. You will see an at mark (@), followed by alphabetical + letters. This is a placeholder. For instance, when you access + "http://yourdomain/index.php/archives/all/2016/1", @topic matches "all", @year matches "2016", + and @month matches "1" in the rule. Then, all placeholders in the route will be replaced with + the matched values. And you will be redirected to "http://yourdomain/directory.php?topic=all&year=2016&month=1".

+

You don't have to include "/index.php" in a rule.

+

You must not start a route with "/index.php", since this will cause an infinite loop.

+

A placeholder starts with @ and an alphabetical letter or letters follow it. + Placeholders are case-sensitive.

+

URL Routing works in the reverse way as well. When you output a URL in your plugin or custom + function, you can URL-route it by using COM_buildURL function and adding your own rule and + route in the URL Routing screen (admin/router.php).

+

Note: This feature may not work with all web servers. It uses PHP's + $_SERVER['PATH_INFO'] variable. Please try it out before you go public with your site.

+

Advanced feature: If you use Apache as a Web server and want to remove "index.php" + from URLs you access, you have to do the following things. Be warned! + Unless you are familiar with Web server configurations, you might as well not use this feature.

+
    +
  1. Enable the rewrite module of your web server. In "httpd.conf", look for
    + # LoadModule rewrite_module modules/mod_rewrite.so
    + and uncomment the line by removing # at the top of the line. Don't forget to + reboot your Web server.
  2. +
  3. Create a file named ".htaccess" in the top of the public directory of your + Geeklog installation (where lib-common.php is located) and add the following lines.
    +
    +        <IfModule mod_rewrite.c>
    +            RewriteEngine On
    +            # RewriteBase /
    +            # Directs all Geeklog requests through the site index file
    +            RewriteCond %{REQUEST_FILENAME} !-f
    +            RewriteCond %{REQUEST_FILENAME} !-d
    +            RewriteRule ^(.*)$ /index.php/$1 [L]
    +        </IfModule>
    +    

    + If you have installed Geeklog in a subdirectory of the document root, you will + have to change the line
    +
    +            RewriteRule ^(.*)$ /index.php/$1 [L]
    +    
    into
    +
    +            RewriteRule ^(.*)$ [sub_directory]/index.php/$1 [L]
    +        

    + or
    +
    +            RewriteRule ^(.*)$ /[sub_directory]/index.php/$1 [L]
    +        
    +
  4. +
  5. + Finally, log in as admin and go to the Configuration screen, and set URL Routing + to "Enabled (without index.php)". +
  6. +
+ +

Localization

Localizing Geeklog is fairly easy. All strings are contained in a diff --git a/public_html/docs/japanese/config.html b/public_html/docs/japanese/config.html index 108d5d6bb..d844a29c2 100644 --- a/public_html/docs/japanese/config.html +++ b/public_html/docs/japanese/config.html @@ -84,6 +84,11 @@

サイト: サイト

いいえ 「はい」でURLリライトを行い、「いいえ」で行わないようになります。
下記のURLリライトのセクションを参照してください。 + + URLルーティング(url_routing) + いいえ + 「はい」でURLルーティングを行い、「いいえ」で行わないようになります。注意: この機能を使うにはURLリライトを「はい」にしてください。
+ 夏期のURLルーティングのセクションを参照してください。 CDNのjQueryを使う(cdn_hosted) いいえ @@ -1785,6 +1790,110 @@

URLリライト

注意:この機能はすべてのWebサーバーで機能するとは限りません。Apache(全バージョン)では機能しますが、IIS(の少なくとも一部のバージョン)では動作しない ことが知られています。サイトを公開する前に検証してください。

+

URLルーティング

+ +

この機能は上述のURLリライトを拡張し、public_html/index.phpを + 疑似フロントコントローラーして使用します。したがって、URLルーティング機能を使うには、 + URLリライトを有効にする必要があります。現時点では以下のルールが定義されています。

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ルールルート優先順位
http://yourdomain/article/[sid]/printhttp://yourdomain/article.php?story=[sid]&mode=print100
http://yourdomain/article/[sid]http://yourdomain/article.php?story=[sid]110
http://yourdomain/archives/@topic/@year/@monthhttp://yourdomain/directory.php?topic=@topic&year=@year&month=@month120
http://yourdomain/page/@pagehttp://yourdomain/staticpages/index.php?page=@page130
http://yourdomain/links/portal/@itemhttp://yourdomain/links/portal.php?what=link&item=@item140
http://yourdomain/links/category/@cathttp://yourdomain/links/index.php?category=@cat150
http://yourdomain/topic/@topichttp://yourdomain/index.php?topic=@topic160
+ +

表の1行目をご覧ください。"http://yourdomain/index.php/article/[sid]/print"にアクセスすると、 + "http://yourdomain/article.php?story=[sid]&mode=print"にリダイレクトされることを意味しています。 + [sid]は記事のIDです。

+

次に3行目をご覧ください。@の後にアルファベットが続くものがプレースホルダーです。たとえば、 + "http://yourdomain/index.php/archives/all/2016/1" にアクセすると、ルールの中の + @topicが"all"に、@year が "2016" に、そして @month が "1" にマッチします。その後、ルートの中の + プレースホルダーがマッチした値に置き換えられ、"http://yourdomain/directory.php?topic=all&year=2016&month=1" + にリダイレクトされます。

+

ルールの中に"/index.php"を含める必要はありません。

+

無限ループになるので、ルートを "/index.php" で始めないようにしてください。

+

プレースホルダーは@で始まり、アルファベットが続きます。プレースホルダーは大文字・小文字を区別します。

+

URLルーティングは逆向きにも働きます。自作のプラグインやカスタム関数の中でURLを出力する時に、 + COM_buildURL 関数を使い、URLルーティング(admin/router.php)で独自のルールとルートを設定する + ことでURLルーティングを行うことができます。

+

注意: この機能は全てのWebサーバーで使えるとは限りません。PHPの + $_SERVER['PATH_INFO'] 変数を使用します。サイトを公開する前に検証してください。

+

高度な機能: WebサーバーとしてApacheを使用し、ユーザーがアクセするURLから + "index.php" を取り除きたいなら、以下のことを行います。警告! Webサーバーの + 設定を熟知していない場合は、この機能を使わない方が良いでしょう。

+
    +
  1. Webサーバーの rewrite モジュールを有効にします。"httpd.conf" の中で次の行を探します。
    + # LoadModule rewrite_module modules/mod_rewrite.so
    + そして行頭の#を取り除いてコメントを外します。Webサーバーを再起動するのを忘れないでください。
  2. +
  3. Geeklogをインストールしている公開領域のトップのディレクトリ(lib-common.phpがある場所)に + ".htaccess" という名前のファイルを設置し、次の行を追加します。 +
    +        <IfModule mod_rewrite.c>
    +            RewriteEngine On
    +            # RewriteBase /
    +            # Directs all Geeklog requests through the site index file
    +            RewriteCond %{REQUEST_FILENAME} !-f
    +            RewriteCond %{REQUEST_FILENAME} !-d
    +            RewriteRule ^(.*)$ /index.php/$1 [L]
    +        </IfModule>
    +    
    + Geeklogをドキュメントルートのサブディレクトリにインストールしている場合は、 +
    +            RewriteRule ^(.*)$ /index.php/$1 [L]
    +    
    を、 +
    +            RewriteRule ^(.*)$ [sub_directory]/index.php/$1 [L]
    +        
    + や、 +
    +            RewriteRule ^(.*)$ /[sub_directory]/index.php/$1 [L]
    +        
    + に変える必要があるでしょう。 +
  4. +
  5. + 最後に、管理者としてログインし、コンフィギュレーションでURLルーティングの設定を + 「有効(index.phpあり)」に変えます。 +
  6. +
+ +

ローカリゼーション(Localization)

Geeklogをローカライズするのは簡単です。文字列はすべて言語ファイルに格納されています。Geeklogに最初から同梱されているのはenglish.phpです。他の言語への翻訳に関心のある方はGeeklog翻訳(geeklog-translations)メーリングリストへの加入をお勧めします。Geeklogの翻訳に関する重要な情報はみなこのメーリングリストに投稿されます。

diff --git a/sql/mssql_tableanddata.php b/sql/mssql_tableanddata.php index 55784377e..4ee75c32a 100644 --- a/sql/mssql_tableanddata.php +++ b/sql/mssql_tableanddata.php @@ -1537,9 +1537,13 @@ $_SQL[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text')"; $_SQL[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid&mode=print', 100)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid', 110)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/archives/@topic/@year/@month', '/directory.php?topic=@topic&year=@year&month=@month', 120)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page', 130)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/portal/@item', '/links/portal.php?what=link&item=@item', 140)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/category/@cat', '/links/index.php?category=@cat', 150)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/topic/@topic', '/index.php?topic=@topic', 160)"; $_SQL[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First')"; $_SQL[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First')"; diff --git a/sql/mysql_tableanddata.php b/sql/mysql_tableanddata.php index 649ec00ae..c5f57ecd4 100644 --- a/sql/mysql_tableanddata.php +++ b/sql/mysql_tableanddata.php @@ -808,9 +808,13 @@ $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text') "; $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted') "; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid&mode=print', 100)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid', 110)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/archives/@topic/@year/@month', '/directory.php?topic=@topic&year=@year&month=@month', 120)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page', 130)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/portal/@item', '/links/portal.php?what=link&item=@item', 140)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/category/@cat', '/links/index.php?category=@cat', 150)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/topic/@topic', '/index.php?topic=@topic', 160)"; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First') "; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First') "; diff --git a/sql/pgsql_tableanddata.php b/sql/pgsql_tableanddata.php index 0f7901e3e..8e9744f28 100644 --- a/sql/pgsql_tableanddata.php +++ b/sql/pgsql_tableanddata.php @@ -826,9 +826,13 @@ $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('plaintext','Plain Old Text') "; $_DATA[] = "INSERT INTO {$_TABLES['postmodes']} (code, name) VALUES ('html','HTML Formatted') "; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; -$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid&mode=print', 100)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid', 110)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/archives/@topic/@year/@month', '/directory.php?topic=@topic&year=@year&month=@month', 120)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page', 130)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/portal/@item', '/links/portal.php?what=link&item=@item', 140)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/category/@cat', '/links/index.php?category=@cat', 150)"; +$_DATA[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/topic/@topic', '/index.php?topic=@topic', 160)"; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('ASC','Oldest First') "; $_DATA[] = "INSERT INTO {$_TABLES['sortcodes']} (code, name) VALUES ('DESC','Newest First') "; diff --git a/sql/updates/mssql_2.1.0_to_2.1.2.php b/sql/updates/mssql_2.1.0_to_2.1.2.php index e67149593..0bc38b0e7 100644 --- a/sql/updates/mssql_2.1.0_to_2.1.2.php +++ b/sql/updates/mssql_2.1.0_to_2.1.2.php @@ -18,9 +18,13 @@ "; // Add sample routes to the table -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid&mode=print', 100)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid', 110)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/archives/@topic/@year/@month', '/directory.php?topic=@topic&year=@year&month=@month', 120)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page', 130)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/portal/@item', '/links/portal.php?what=link&item=@item', 140)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/category/@cat', '/links/index.php?category=@cat', 150)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/topic/@topic', '/index.php?topic=@topic', 160)"; /** * Add new config options diff --git a/sql/updates/mysql_2.1.0_to_2.1.2.php b/sql/updates/mysql_2.1.0_to_2.1.2.php index ac18d1125..f93066271 100644 --- a/sql/updates/mysql_2.1.0_to_2.1.2.php +++ b/sql/updates/mysql_2.1.0_to_2.1.2.php @@ -11,9 +11,13 @@ )"; // Add sample routes to the table -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid&mode=print', 100)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid', 110)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/archives/@topic/@year/@month', '/directory.php?topic=@topic&year=@year&month=@month', 120)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page', 130)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/portal/@item', '/links/portal.php?what=link&item=@item', 140)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/category/@cat', '/links/index.php?category=@cat', 150)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/topic/@topic', '/index.php?topic=@topic', 160)"; /** * Add new config options diff --git a/sql/updates/pgsql_2.1.0_to_2.1.2.php b/sql/updates/pgsql_2.1.0_to_2.1.2.php index 436b4d4c4..30eee310e 100644 --- a/sql/updates/pgsql_2.1.0_to_2.1.2.php +++ b/sql/updates/pgsql_2.1.0_to_2.1.2.php @@ -11,9 +11,13 @@ )"; // Add sample routes to the table -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/article/@sid', '/article.php?story=@sid')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/topic/@topic', '/index.php?topic=@topic')"; -$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page')"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid&mode=print', 100)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/article/@sid', '/article.php?story=@sid', 110)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/archives/@topic/@year/@month', '/directory.php?topic=@topic&year=@year&month=@month', 120)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/page/@page', '/staticpages/index.php?page=@page', 130)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/portal/@item', '/links/portal.php?what=link&item=@item', 140)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/links/category/@cat', '/links/index.php?category=@cat', 150)"; +$_SQL[] = "INSERT INTO {$_TABLES['routes']} (method, rule, route, priority) VALUES (1, '/topic/@topic', '/index.php?topic=@topic', 160)"; /** * Add new config options From 0407a81ed5075fc528582fd5f1f7646ee8596df6 Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Sun, 24 Jan 2016 00:37:02 +0900 Subject: [PATCH 09/12] Fixed a typo --- public_html/docs/japanese/config.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public_html/docs/japanese/config.html b/public_html/docs/japanese/config.html index 461e100b3..aa25d7e26 100644 --- a/public_html/docs/japanese/config.html +++ b/public_html/docs/japanese/config.html @@ -88,7 +88,7 @@

サイト: サイト

URLルーティング(url_routing) いいえ 「はい」でURLルーティングを行い、「いいえ」で行わないようになります。注意: この機能を使うにはURLリライトを「はい」にしてください。
- 夏期のURLルーティングのセクションを参照してください。 + 下記のURLルーティングのセクションを参照してください。 CDNのjQueryを使う(cdn_hosted) いいえ From 73ec58cc3bdbc07417ea3674ecdea1ee3ba25948 Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Sun, 24 Jan 2016 06:20:08 +0900 Subject: [PATCH 10/12] Modified to allow routes to start with "/index.php?" (not with "/index.php/") --- language/english.php | 2 +- language/english_utf-8.php | 2 +- language/japanese_utf-8.php | 2 +- public_html/admin/router.php | 4 ++-- public_html/docs/english/config.html | 3 ++- public_html/docs/japanese/config.html | 2 +- 6 files changed, 8 insertions(+), 7 deletions(-) diff --git a/language/english.php b/language/english.php index 0d7f06ef0..b5b40126b 100644 --- a/language/english.php +++ b/language/english.php @@ -1355,7 +1355,7 @@ 13 => 'Rule is a mandatory item.', 14 => 'Route is a mandatory item.', 15 => 'Placeholders (@) in a rule and those in a route must be the same.', - 16 => 'Route must not start with "index.php".', + 16 => 'Route must not start with "/index.php/".', 17 => 'Database error occurred.', 18 => 'To enable URL routing, you have to enable URL rewrite.', 19 => '
  • Placeholders (@) must be the same both in a rule and its route.
  • A placeholder starts with "@", followed by an alphabet, optionally followed by any length of alphabet or digit.
  • Placeholders are case-sensitive.
', diff --git a/language/english_utf-8.php b/language/english_utf-8.php index d5e70af6d..f0b7f8e92 100644 --- a/language/english_utf-8.php +++ b/language/english_utf-8.php @@ -1355,7 +1355,7 @@ 13 => 'Rule is a mandatory item.', 14 => 'Route is a mandatory item.', 15 => 'Placeholders (@) in a rule and those in a route must be the same.', - 16 => 'Route must not start with "index.php".', + 16 => 'Route must not start with "/index.php/".', 17 => 'Database error occurred.', 18 => 'To enable URL routing, you have to enable URL rewrite.', 19 => '
  • Placeholders (@) must be the same both in a rule and its route.
  • A placeholder starts with "@", followed by an alphabet, optionally followed by any length of alphabet or digit.
  • Placeholders are case-sensitive.
', diff --git a/language/japanese_utf-8.php b/language/japanese_utf-8.php index 285c3a132..e07c64dde 100644 --- a/language/japanese_utf-8.php +++ b/language/japanese_utf-8.php @@ -1354,7 +1354,7 @@ 13 => 'ルールは必須項目です。', 14 => 'ルートは必須項目です。', 15 => 'ルールとルートで同じプレースホルダー(@)を定義しなければなりません。', - 16 => 'ルートの先頭にindex.phpを含むことはできません。', + 16 => 'ルートの先頭を "/index.php/" とすることはできません。', 17 => 'データベース操作でエラーが発生しました。', 18 => 'URLルーティングを有効にするには、URLリライトを有効にしてください。', 19 => '
  • プレースホルダー(@)はルールとルートで同じものを定義してください。
  • プレースホルダーは@で始まり、1文字目は英字、2文字目以降は英数字を使えます。
  • プレースホルダーは大文字・小文字を区別します。
', diff --git a/public_html/admin/router.php b/public_html/admin/router.php index 349ce1541..5f37c9d2e 100644 --- a/public_html/admin/router.php +++ b/public_html/admin/router.php @@ -343,9 +343,9 @@ function saveRoute($rid, $method, $rule, $route, $priority) $route = '/' . $route; } - // If a route starts with "/index.php", then make it an error to prevent the script + // If a route starts with "/index.php/", then make it an error to prevent the script // from going an infinite loop - if (stripos($route, '/index.php') === 0) { + if (stripos($route, '/index.php/') === 0) { $messageText = $LANG_ROUTER[16]; } diff --git a/public_html/docs/english/config.html b/public_html/docs/english/config.html index 81c8d22b0..5a8044c24 100644 --- a/public_html/docs/english/config.html +++ b/public_html/docs/english/config.html @@ -2154,7 +2154,8 @@

URL Routing

and @month matches "1" in the rule. Then, all placeholders in the route will be replaced with the matched values. And you will be redirected to "http://yourdomain/directory.php?topic=all&year=2016&month=1".

You don't have to include "/index.php" in a rule.

-

You must not start a route with "/index.php", since this will cause an infinite loop.

+

You must not start a route with "/index.php/", since this will cause an infinite loop. However, you can start + with a route with "/index.php?".

A placeholder starts with @ and an alphabetical letter or letters follow it. Placeholders are case-sensitive.

URL Routing works in the reverse way as well. When you output a URL in your plugin or custom diff --git a/public_html/docs/japanese/config.html b/public_html/docs/japanese/config.html index aa25d7e26..2378621d5 100644 --- a/public_html/docs/japanese/config.html +++ b/public_html/docs/japanese/config.html @@ -1852,7 +1852,7 @@

URLルーティング

プレースホルダーがマッチした値に置き換えられ、"http://yourdomain/directory.php?topic=all&year=2016&month=1" にリダイレクトされます。

ルールの中に"/index.php"を含める必要はありません。

-

無限ループになるので、ルートを "/index.php" で始めないようにしてください。

+

無限ループになるので、ルートの先頭は "/index.php/" にしないでください("/index.php?" は大丈夫です)。

プレースホルダーは@で始まり、アルファベットが続きます。プレースホルダーは大文字・小文字を区別します。

URLルーティングは逆向きにも働きます。自作のプラグインやカスタム関数の中でURLを出力する時に、 COM_buildURL 関数を使い、URLルーティング(admin/router.php)で独自のルールとルートを設定する From 5e9ff986ca844ab996b23c1c0e0a5360655a63aa Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Sun, 24 Jan 2016 07:15:32 +0900 Subject: [PATCH 11/12] Refactored to use class constants --- public_html/admin/router.php | 4 ++-- system/classes/router.class.php | 39 ++++++++++++++++++++++----------- 2 files changed, 28 insertions(+), 15 deletions(-) diff --git a/public_html/admin/router.php b/public_html/admin/router.php index 5f37c9d2e..fdc6d5ab7 100644 --- a/public_html/admin/router.php +++ b/public_html/admin/router.php @@ -354,8 +354,8 @@ function saveRoute($rid, $method, $rule, $route, $priority) $route = str_ireplace('&', '&', $route); // Check if placeholders are the same - $numPlaceHoldersInRule = preg_match_all(Router::PATTERN_PLACEHOLDER, $rule, $matchesRule, PREG_SET_ORDER); - $numPlaceHoldersInRoute = preg_match_all(Router::PATTERN_PLACEHOLDER, $route, $matchesRoute, PREG_SET_ORDER); + $numPlaceHoldersInRule = preg_match_all(Router::PLACEHOLDER_MATCH, $rule, $matchesRule, PREG_SET_ORDER); + $numPlaceHoldersInRoute = preg_match_all(Router::PLACEHOLDER_MATCH, $route, $matchesRoute, PREG_SET_ORDER); if ($numPlaceHoldersInRule === $numPlaceHoldersInRoute) { if ($numPlaceHoldersInRule > 0) { diff --git a/system/classes/router.class.php b/system/classes/router.class.php index 5016a5707..d242b9a00 100644 --- a/system/classes/router.class.php +++ b/system/classes/router.class.php @@ -18,7 +18,11 @@ class Router const ROUTING_WITHOUT_INDEX_PHP = 2; // Placeholder pattern - const PATTERN_PLACEHOLDER = '|(@[a-zA-Z][0-9a-zA-Z_]*)|'; + const PLACEHOLDER_MATCH = '|(@[a-zA-Z][0-9a-zA-Z_]*)|'; + const PLACEHOLDER_REPLACE = '([^/&=?#]+)'; + + // Values to escape pattern + const VALUE_MATCH = '|[^0-9a-zA-Z_.-]|'; // Default priority const DEFAULT_PRIORITY = 100; @@ -39,7 +43,7 @@ public static function setDebug($switch) } /** - * Dispatch the client + * Dispatch the client based on $_SERVER['PATH_INFO'] * * @return bool when not dispatched */ @@ -128,11 +132,12 @@ public static function dispatch() header('Location: ' . $route); COM_errorLog(__METHOD__ . ': somehow could not redirect'); + return false; } // Try comparison with placeholders - if (preg_match_all(self::PATTERN_PLACEHOLDER, $rule, $matches, PREG_SET_ORDER)) { + if (preg_match_all(self::PLACEHOLDER_MATCH, $rule, $matches, PREG_SET_ORDER)) { // Escape a period and a question mark so that they can safely be used in a regular expression $rule = str_replace(array('.', '?'), array('\.', '\?'), $rule); $placeHolders = array(); @@ -140,7 +145,7 @@ public static function dispatch() // Replace placeholders in a rule with ones for regular expressions foreach ($matches as $match) { $placeHolders[] = $match[1]; - $rule = str_replace($match[1], '([^/&=?#]+)', $rule); + $rule = str_replace($match[1], self::PLACEHOLDER_REPLACE, $rule); } $rule = '|\A' . $rule . '\z|i'; @@ -152,7 +157,10 @@ public static function dispatch() array_shift($values); foreach ($values as $value) { - $value = urlencode($value); + if (preg_match(self::VALUE_MATCH, $value)) { + $value = urlencode($value); + } + $placeHolder = array_shift($placeHolders); $route = str_replace($placeHolder, $value, $route); } @@ -183,7 +191,8 @@ public static function dispatch() /** * Convert a URL * - * e.g. [SITE_URL]/article.php?story=welcome -> [SITE_URL]/index.php/article/welcome or [SITE_URL]/article/welcome + * e.g. [SITE_URL]/article.php?story=welcome + * -> [SITE_URL]/index.php/article/welcome or [SITE_URL]/article/welcome * * @param string $url * @param int $requestMethod @@ -195,7 +204,7 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) $originalUrl = $url; - // URL rewrite is disabled + // URL rewriting is disabled if (!$_CONF['url_rewrite']) { return $originalUrl; } @@ -213,7 +222,7 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) } // Strip $url of $_CONF['site_url'] - $url = str_replace($_CONF['site_url'], '', $url); + $url = str_ireplace($_CONF['site_url'], '', $url); // Check for $requestMethod $requestMethod = intval($requestMethod, 10); @@ -261,17 +270,18 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) } // Try comparison with placeholders - if (preg_match_all(self::PATTERN_PLACEHOLDER, $route, $matches, PREG_SET_ORDER)) { + if (preg_match_all(self::PLACEHOLDER_MATCH, $route, $matches, PREG_SET_ORDER)) { $placeHolders = array(); + // Escape '.', '?' and '+' in the route so that they can safely be used in a regular expression + $route = str_replace(array('.', '?', '+'), array('\.', '\?', '\+'), $route); + // Replace placeholders in a route with ones for regular expressions foreach ($matches as $match) { $placeHolders[] = $match[1]; - $route = str_replace($match[1], '([^/&=?#]+)', $route); + $route = str_replace($match[1], self::PLACEHOLDER_REPLACE, $route); } - // Escape a period and a question mark so that they can safely be used in a regular expression - $route = str_replace(array('.', '?'), array('\.', '\?'), $route); $route = '|\A' . $route . '\z|i'; if (!preg_match($route, $url, $values)) { @@ -281,7 +291,10 @@ public static function convertUrl($url, $requestMethod = self::HTTP_REQUEST_GET) array_shift($values); foreach ($values as $value) { - $value = urlencode($value); + if (preg_match(self::VALUE_MATCH, $value)) { + $value = urlencode($value); + } + $placeHolder = array_shift($placeHolders); $rule = str_replace($placeHolder, $value, $rule); } From 6916689921f5dca0c7c2bfb86ce19db92eec6d99 Mon Sep 17 00:00:00 2001 From: Kenji ITO Date: Mon, 29 Aug 2016 15:24:48 +0900 Subject: [PATCH 12/12] Updated URL-routing feature --- language/english.php | 8 +- language/japanese_utf-8.php | 8 +- .../admin/configuration_validation.php | 7 +- public_html/admin/install/config-install.php | 4 +- public_html/admin/router.php | 9 +- public_html/docs/docstyle.css | 3 + public_html/docs/english/config.html | 244 +++++++++--------- public_html/docs/japanese/config.html | 200 +++++++------- public_html/lib-common.php | 7 + sql/mysql_tableanddata.php | 17 +- sql/pgsql_tableanddata.php | 6 +- sql/updates/mysql_2.1.1_to_2.1.2.php | 20 ++ sql/updates/pgsql_2.1.1_to_2.1.2.php | 24 +- system/classes/url.class.php | 5 + system/lib-database.php | 2 +- 15 files changed, 314 insertions(+), 250 deletions(-) diff --git a/language/english.php b/language/english.php index ba7c89f53..582108e3b 100644 --- a/language/english.php +++ b/language/english.php @@ -1381,8 +1381,9 @@ 15 => 'Placeholders (@) in a rule and those in a route must be the same.', 16 => 'Route must not start with "/index.php/".', 17 => 'Database error occurred.', - 18 => 'To enable URL routing, you have to enable URL rewrite.', - 19 => '

  • Placeholders (@) must be the same both in a rule and its route.
  • A placeholder starts with "@", followed by an alphabet, optionally followed by any length of alphabet or digit.
  • Placeholders are case-sensitive.
', + 18 => 'To enable URL routing, you have to enable URL rewrite in the Configuration.', + 19 => 'To enable URL routing, you have to enable URL routing in the Configuration.', + 20 => '
  • Placeholders (@) must be the same both in a rule and its route.
  • A placeholder starts with "@", followed by an alphabet, optionally followed by any length of alphabet or digit.
  • Placeholders are case-sensitive.
', ); ############################################################################### @@ -2429,7 +2430,8 @@ 33 => array('Disabled' => 0, 'Enabled' => 1, 'Enabled (No Links)' => 2, 'Enabled (No Outbound Links)' => 3), 34 => array('grid' => 'grid', 'list' => 'list'), 35 => array('default' => 'default', 'Name (asc)' => 'NAME_ASC', 'Name (desc)' => 'NAME_DESC', 'Type (asc)' => 'TYPE_ASC', 'Type (desc)' => 'TYPE_DESC', 'Modified (asc)' => 'MODIFIED_ASC', 'Modified (desc)' => 'MODIFIED_DESC'), - 36 => array('False' => 'false', 'Frontpage only' => 'frontpage', 'Frontpage and Topics' => 'frontpage_topics') + 36 => array('False' => 'false', 'Frontpage only' => 'frontpage', 'Frontpage and Topics' => 'frontpage_topics'), + 37 => array('Disabled' => 0, 'Enabled(with "index.php")' => 1, 'Enabled(without "index.php")' => 2), ); ################################################################################ diff --git a/language/japanese_utf-8.php b/language/japanese_utf-8.php index 03f648d48..372097ddb 100644 --- a/language/japanese_utf-8.php +++ b/language/japanese_utf-8.php @@ -1383,8 +1383,9 @@ 15 => 'ルールとルートで同じプレースホルダー(@)を定義しなければなりません。', 16 => 'ルートの先頭を "/index.php/" とすることはできません。', 17 => 'データベース操作でエラーが発生しました。', - 18 => 'URLルーティングを有効にするには、URLリライトを有効にしてください。', - 19 => '
  • プレースホルダー(@)はルールとルートで同じものを定義してください。
  • プレースホルダーは@で始まり、1文字目は英字、2文字目以降は英数字を使えます。
  • プレースホルダーは大文字・小文字を区別します。
', + 18 => 'URLルーティングを有効にするには、コンフィギュレーションでURLリライトを有効にしてください。', + 19 => 'URLルーティングを有効にするには、コンフィギュレーションでURLルーティングを有効にしてください。', + 20 => '
  • プレースホルダー(@)はルールとルートで同じものを定義してください。
  • プレースホルダーは@で始まり、1文字目は英字、2文字目以降は英数字を使えます。
  • プレースホルダーは大文字・小文字を区別します。
', ); ############################################################################### @@ -2439,7 +2440,8 @@ 33 => array('無効にする' => 0, '有効にする' => 1, '有効にする(リンクなし)' => 2, '有効にする(外部リンクなし)' => 3), 34 => array('グリッド' => 'grid', 'リスト' => 'list'), 35 => array('デフォルト' => 'default', '名前(昇順)' => 'NAME_ASC', '名前(降順)' => 'NAME_DESC', '種類(昇順)' => 'TYPE_ASC', '種類(降順)' => 'TYPE_DESC', '変更日時(昇順)' => 'MODIFIED_ASC', '変更日時(降順)' => 'MODIFIED_DESC'), - 36 => array('False' => 'false', 'Frontpage only' => 'frontpage', 'Frontpage and Topics' => 'frontpage_topics') + 36 => array('False' => 'false', 'Frontpage only' => 'frontpage', 'Frontpage and Topics' => 'frontpage_topics'), + 37 => array('無効' => 0, '有効(index.phpあり)' => 1, '有効(index.phpなし)' => 2), ); ############################################################################### diff --git a/public_html/admin/configuration_validation.php b/public_html/admin/configuration_validation.php index 6f0e01443..6999b7166 100644 --- a/public_html/admin/configuration_validation.php +++ b/public_html/admin/configuration_validation.php @@ -2,7 +2,7 @@ /* Reminder: always indent with 4 spaces (no tabs). */ // +---------------------------------------------------------------------------+ -// | Geeklog 1.7 | +// | Geeklog 2.1 | // +---------------------------------------------------------------------------+ // | configuration_validation.php | // | | @@ -30,7 +30,7 @@ // | | // +---------------------------------------------------------------------------+ -if (strpos(strtolower($_SERVER['PHP_SELF']), 'configuration_validation.php') !== false) { +if (stripos($_SERVER['PHP_SELF'], 'configuration_validation.php') !== false) { die('This file can not be used on its own!'); } @@ -50,6 +50,7 @@ 'message' => isset($LANG_VALIDATION['yearOrRange']) ? $LANG_VALIDATION['yearOrRange'] : $LANG_VALIDATION['default'] ); $_CONF_VALIDATE['Core']['url_rewrite'] = array('rule' => 'boolean'); +$_CONF_VALIDATE['Core']['url_routing'] = array('rule' => array('inList', array(0, 1, 2), false)); $_CONF_VALIDATE['Core']['cdn_hosted'] = array('rule' => 'boolean'); $_CONF_VALIDATE['Core']['meta_tags'] = array('rule' => array('inList', array(0, 1, 2), false)); $_CONF_VALIDATE['Core']['meta_description'] = array('rule' => 'stringOrEmpty'); @@ -719,5 +720,3 @@ // Subgroup Filemanager, Tab Audios $_CONF_VALIDATE['Core']['filemanager_show_audio_player'] = array('rule' => 'boolean'); //$_CONF_VALIDATE['Core']['filemanager_audios_ext'] = array('rule' => 'boolean'); - -?> diff --git a/public_html/admin/install/config-install.php b/public_html/admin/install/config-install.php index 7d73c8bb9..01deee8da 100644 --- a/public_html/admin/install/config-install.php +++ b/public_html/admin/install/config-install.php @@ -2,7 +2,7 @@ /* Reminder: always indent with 4 spaces (no tabs). */ // +---------------------------------------------------------------------------+ -// | Geeklog 1.6 | +// | Geeklog 2.1 | // +---------------------------------------------------------------------------+ // | config-install.php | // | | @@ -54,7 +54,7 @@ function install_config() $c->add('owner_name','','text',0,0,NULL,1000,TRUE, $me, 0); $c->add('copyrightyear',date('Y'),'text',0,0,NULL,1440,FALSE, $me, 0); $c->add('url_rewrite',FALSE,'select',0,0,1,1800,TRUE, $me, 0); - $c->add('url_routing',FALSE,'select',0,0,36,1850,TRUE, $me, 0); + $c->add('url_routing',0,'select',0,0,37,1850,TRUE, $me, 0); $c->add('cdn_hosted',FALSE,'select',0,0,1,1900,TRUE, $me, 0); $c->add('meta_tags',0,'select',0,0,23,2000,TRUE, $me, 0); $c->add('meta_description','Geeklog - The secure Content Management System.','textarea',0,0,NULL,2010,TRUE, $me, 0); diff --git a/public_html/admin/router.php b/public_html/admin/router.php index fdc6d5ab7..3f248b30f 100644 --- a/public_html/admin/router.php +++ b/public_html/admin/router.php @@ -40,8 +40,9 @@ require_once './auth.inc.php'; if (!SEC_inGroup('Root')) { + $content = COM_showMessageText($MESSAGE[29], $MESSAGE[30]); $display = COM_createHTMLDocument( - COM_showMessageText($MESSAGE[29], $MESSAGE[30]), + $content, array('pagetitle' => $MESSAGE[30]) ); COM_accessLog("User {$_USER['username']} tried to illegally access the URL routing administration screen"); @@ -114,7 +115,7 @@ function getRouteEditor($rid = 0) 'lang_router_rule' => $LANG_ROUTER[5], 'lang_router_route' => $LANG_ROUTER[6], 'lang_router_priority' => $LANG_ROUTER[7], - 'lang_router_notice' => $LANG_ROUTER[19], + 'lang_router_notice' => $LANG_ROUTER[20], 'lang_save' => $LANG_ADMIN['save'], 'lang_cancel' => $LANG_ADMIN['cancel'], )); @@ -233,6 +234,10 @@ function listRoutes() $notice .= ' ' . $LANG_ROUTER[18]; } + if (!isset($_CONF['url_routing']) || ($_CONF['url_routing'] == Router::ROUTING_DISABLED)) { + $notice .= ' ' . $LANG_ROUTER[19]; + } + $retval = COM_startBlock($LANG_ROUTER[2], '', COM_getBlockTemplate('_admin_block', 'header')) . ADMIN_createMenu( $menu_arr, diff --git a/public_html/docs/docstyle.css b/public_html/docs/docstyle.css index eb8cf064a..1102f27a4 100644 --- a/public_html/docs/docstyle.css +++ b/public_html/docs/docstyle.css @@ -123,3 +123,6 @@ a.wikipedia { border-bottom: 1px dotted black; } +span.tt { + font-family:'Lucida Console', monospace; +} diff --git a/public_html/docs/english/config.html b/public_html/docs/english/config.html index 81ec892ee..be04d732c 100644 --- a/public_html/docs/english/config.html +++ b/public_html/docs/english/config.html @@ -14,10 +14,10 @@

Geeklog Configuration

Configuration files

-

Previous versions of Geeklog used one huge file called config.php +

Previous versions of Geeklog used one huge file called config.php that held all the core configuration options. As of Geeklog 1.5.0, most of the configuration options have been moved to the database and can now be -reached from the Configuration admin panel within Geeklog.

+reached from the Configuration admin panel within Geeklog.

For technical reasons, some configuration options still have to be stored in files. There are two such configuration files now:

@@ -63,7 +63,7 @@

Site: Site

Base URL of the admin area of your site (no trailing slash). You won't have to change this normally, but some hosting services use a predefined "admin" directory for other purposes. In this case, you can - rename Geeklog's admin directory and adjust the URL accordingly to + rename Geeklog's admin directory and adjust the URL accordingly to avoid conflicts. site_name @@ -80,14 +80,14 @@

Site: Site

disabled. If the text begins with "http:" then visitors are redirected to that URL.
Note: The option which actually disables the site can be found - in the siteconfig.php file. + in the siteconfig.php file. owner_name The name of the owner of the site. This is used in the copyright notice if set, else the site name is used. copyrightyear - (disabled) + (disabled) Set this to the year you want to appear in the copyright notice of your site's footer. If not set, Geeklog will use the current year. @@ -97,8 +97,8 @@

Site: Site

Also see the section on URL Rewriting below. url_routing - disabled(0) - Enable (true) or disable (false) URL routing. Caution: This feature takes effect only when URL Rewriting is enabled.
+ Disabled + Enable or disable URL routing. Caution: This feature takes effect only when URL Rewriting is enabled.
Also see the section on URL Routing below. cdn_hosted @@ -144,11 +144,11 @@

Site: Mail

Used to select how to send email. Can be one of 'smtp', 'sendmail', or 'mail'. sendmail_path - /usr/bin/sendmail + /usr/bin/sendmail If you chose 'sendmail' for the backend setting, this specifies the complete path to the sendmail binary. sendmail_args - '' (empty) + '' (empty) If you chose 'sendmail' for the backend setting, this variable can be used to pass additional parameters to the sendmail binary. @@ -279,7 +279,7 @@

Site: PEAR

use the PEAR packages installed in $_CONF['path_pear'] (see below) path_pear - /path/to/geeklog/system/pear/ + /path/to/geeklog/system/pear/ When $_CONF['have_pear'] (see above) is set to false, this is the path where Geeklog expects to find the PEAR packages it requires (e.g. @@ -329,7 +329,7 @@

Site: Search

search_limits 10,15,25,30 - The result limits a user can select. Each value must be separated with a comma. + The result limits a user can select. Each value must be separated with a comma. num_search_results 30 @@ -530,7 +530,7 @@

Stories and Trackback: Trackback

check (but using option 1 and 2 doesn't make sense and will be treated as if you requested option 2).
Options are: 0 = don't perform any checks, 1 = check only for your site's main URL ($_CONF['site_url']), 2 = check for the exact URL of the entry (e.g. an article) on your site, 4 = check IP address of the sender of the trackback against the site referred to in the trackback URL.
- Example: $_CONF['check_trackback_link'] = 6; // check for the exact URL (2) and proper IP address (4) + Example: $_CONF['check_trackback_link'] = 6; // check for the exact URL (2) and proper IP address (4) multiple_trackbacks 0 @@ -592,22 +592,22 @@

Theme: Theme

Document Type Declaration (aka DOCTYPE aka DTD) to use for all the themes on your - site, assuming they use the {doctype} variable instead of a - hard-coded DOCTYPE in their header.thtml. + site, assuming they use the {doctype} variable instead of a + hard-coded DOCTYPE in their header.thtml. menu_elements array('contribute', 'search', 'stats', 'directory', 'plugins') Specifies which entries are displayed in the site's menu bar (if your theme uses the {menu_elements} variable to display - the menu bar). Can be any combination of 'home', - 'contribute', 'search', 'stats', - 'directory', 'login', 'prefs', 'plugins', and - 'custom' where 'plugins' is the same as the + the menu bar). Can be any combination of 'home', + 'contribute', 'search', 'stats', + 'directory', 'login', 'prefs', 'plugins', and + 'custom' where 'plugins' is the same as the {plg_menu_elements} variable, i.e. a list of the menu entries - provided by plugins, and 'custom' displays the entries returned by + provided by plugins, and 'custom' displays the entries returned by a custom function CUSTOM_menuEntries (see - lib-custom.php for details). + lib-custom.php for details). path_themes path/to/path_themes @@ -615,7 +615,7 @@

Theme: Theme

cache_templates true - If set to true, all templates will be cached, which + If set to true, all templates will be cached, which should improve performance of the web site. In some cases, caching could slow performance down. For example, if the disk access is slow on the web server or if the web server is accessing Windows shared drives, setting this @@ -623,7 +623,7 @@

Theme: Theme

cache_mobile true - If set to true, mobile devices (phones and tablets) will be cached + If set to true, mobile devices (phones and tablets) will be cached separately from computers. This includes the template files, blocks, articles and other plugins which may use Geeklog's template cache system. You should only set this to false if you do not plan to display different information depending on if a mobile device is detected being used by the user. Performance will be improved slightly if set to false since @@ -639,7 +639,7 @@

Theme: Advanced Settings

show_right_blocks false - If set to true, the right-side column of blocks + If set to true, the right-side column of blocks will be displayed on all pages (instead of only on the index page). @@ -675,7 +675,7 @@

Blocks: Admin Block

sort_admin false - If set to true will sort the entries in the Admin's + If set to true will sort the entries in the Admin's block and the icons on the Command and Control page alphabetically. link_documentation @@ -795,7 +795,7 @@

Users and Submissions: Users

disable_new_user_registration false - When set to true completely disables all options + When set to true completely disables all options to sign up as a new user. allow_user_themes @@ -831,13 +831,13 @@

Users and Submissions: Users

If you allow users to log in with accounts on remote services (like LDAP or LiveJournal), this option will at the service's name to the username to avoid confusion with local users of the same name. Set to - false to disable. + false to disable. custom_registration false When set to true, Geeklog will let you use your own signup form for new user registrations. Please see the file - lib-custom.php that ships with Geeklog for an example. + lib-custom.php that ships with Geeklog for an example. standard true @@ -851,11 +851,11 @@

Users and Submissions: Users

3rdparty false - Allow (when set to true) users who already have + Allow (when set to true) users who already have an account with some other service to log into your Geeklog site with the login for that service. Currently supported: LDAP and LiveJournal.
Please note that to enable login for a specific service, you need an - authorization class in system/classes/authentication. If you only + authorization class in system/classes/authentication. If you only want to allow LDAP but not LiveJournal users (or vice versa), simply remove the class file for the unwanted service(s).
See Remote Authentication in Geeklog for more information. @@ -870,7 +870,7 @@

Users and Submissions: Users

facebook_login false - Allow (when set to true) users who already have + Allow (when set to true) users who already have an account with Facebook to log into Geeklog with said account using OAuth. You must set the Facebook application ID and secret. facebook_consumer_key @@ -887,7 +887,7 @@

Users and Submissions: Users

linkedin_login false - Allow (when set to true) users who already have + Allow (when set to true) users who already have an account with LinkedIn to log into Geeklog with said account using OAuth. You must set the LinkedIn API and secret key. linkedin_consumer_key @@ -904,7 +904,7 @@

Users and Submissions: Users

twitter_login false - Allow (when set to true) users who already have + Allow (when set to true) users who already have an account with Twitter to log into Geeklog with said account using OAuth. You must set the Twitter consumer key and secret. twitter_consumer_key @@ -921,7 +921,7 @@

Users and Submissions: Users

google_login false - Allow (when set to true) users who already have + Allow (when set to true) users who already have an account with Google to log into Geeklog with said account using OAuth. You must set the Google client id and client secret. google_consumer_key @@ -938,7 +938,7 @@

Users and Submissions: Users

microsoft_login false - Allow (when set to true) users who already have + Allow (when set to true) users who already have an account with Microsoft to log into Geeklog with said account using OAuth. You must set the Microsoft client id and client secret. microsoft_consumer_key @@ -955,7 +955,7 @@

Users and Submissions: Users

yahoo_login false - Allow (when set to true) users who already have + Allow (when set to true) users who already have an account with Yahoo to log into Geeklog with said account using OAuth. You must set the Yahoo consumer key and consumer secret. yahoo_consumer_key @@ -972,7 +972,7 @@

Users and Submissions: Users

github_login false - Allow (when set to true) users who already have + Allow (when set to true) users who already have an account with GitHub to log into Geeklog with said account using OAuth. You must set the GitHub client id and client secret. github_consumer_key @@ -1113,7 +1113,7 @@

Users and Submissions: User Submission

comma-separated list of domain names from which user submissions will not be queued (but approved automatically). Regular expressions are also allowed and interpreted.
Example: - 'mycompany.com,myothercompany.com' + 'mycompany.com,myothercompany.com' disallow_domains '' @@ -1123,7 +1123,7 @@

Users and Submissions: User Submission

when the user submission queue has been switched off. Again, regular expression can be used.
Example disallow email addresses with a certain domain name and from any ".edu" domain: - 'somebaddomain.com,\.edu$' + 'somebaddomain.com,\.edu$'

Users and Submissions: Submission Settings

@@ -1140,7 +1140,7 @@

Users and Submissions: Submission Settingslistdraftstories 0 When set to 1, this will display an additional block on the - submissions page (moderation.php) that lists all the stories that + submissions page (moderation.php) that lists all the stories that have the 'draft' flag set. postmode @@ -1268,15 +1268,15 @@

Images: Image Library

images to be resized or if you don't have those packages available. path_to_mogrify - (disabled) + (disabled) If you chose 'imagemagick' for $_CONF['image_lib'] above, then this should hold the complete path to the mogrify executable (from the ImageMagick package), e.g. - '/usr/bin/mogrify' (ImageMagick 5.4.9 or newer recommended). + '/usr/bin/mogrify' (ImageMagick 5.4.9 or newer recommended). path_to_netpbm - (disabled) + (disabled) If you chose 'netpbm' for $_CONF['image_lib'] above, then this should hold the complete path to the directory where the binaries from the Netpbm package are kept, e.g. @@ -1300,11 +1300,11 @@

Images: Upload

1 When unscaled images are kept (see above), this option lets the user chose between using the scaled or unscaled image in the story, i.e. - enables the [unscaledX] image tag (in addition to the - [imageX] tag). + enables the [unscaledX] image tag (in addition to the + [imageX] tag). jpeg_quality - (disabled) + (disabled) Control the image quality when resizing JPEGs. All the image libraries supported by Geeklog are based on the IJG JPEG library which uses an arbitrary range of 0-100 to specify the "quality" (note that this is @@ -1319,7 +1319,7 @@

Images: Upload

debug_image_upload false When set to true, this option enables debugging - output to be written into Geeklog's error.log file during the + output to be written into Geeklog's error.log file during the upload of an image. This is useful to track down problems with the image upload and resizing. @@ -1344,7 +1344,7 @@

Images: Images in Articles

$_CONF['image_lib'] above). max_image_size - 1048576 (equals 1 MB) + 1048576 (equals 1 MB) Max. size of an image in bytes. If it exceeds this, it is is rejected (even if you're using a graphics package to resize images). @@ -1369,7 +1369,7 @@

Images: Topic Icons

$_CONF['image_lib'] above). max_topicicon_size - 65536 (equals 64 KB) + 65536 (equals 64 KB) Max. size of a topic icon in bytes. If it exceeds this, it is rejected (even if you're using a graphics package to resize images). @@ -1394,12 +1394,12 @@

Images: Photos

$_CONF['image_lib'] above). max_photo_size - 65536 (equals 64 KB) + 65536 (equals 64 KB) Max. size of a user photo in bytes. If it exceeds this, it is rejected (even if you're using a graphics package to resize images). force_photo_width - (disabled) + (disabled) This option, when enabled, will only apply when displaying a user photo. The <img> tag for the user photo will be emitted with a max. width, as specified by this option. @@ -1408,7 +1408,7 @@

Images: Photos

shaped user photos to break your page's layout (e.g. in a forum). default_photo - (disabled) + (disabled) When enabled, this option should point to an image (full URL required!) that should be displayed for users without a user photo. When this option is not set and a user does not have a user photo (or an Images: Gravatar use_gravatar false - If enabled (set to true), a user's avatar image will + If enabled (set to true), a user's avatar image will be requested from gravatar.com if the user didn't upload a user photo (i.e. an uploaded photo always takes precedence).
@@ -1433,7 +1433,7 @@

Images: Gravatar

a lot of userphotos for different users (e.g. forum threads). gravatar_rating - (disabled) + (disabled) Avatars submitted to gravatar.com are rated with the rating system used for movies (in the U.S.), i.e. the letters G, PG, R, or X. This option will let you chose the maximum allowed rating for an avatar. @@ -1464,7 +1464,7 @@

Languages and Locale: Language

If set to 1, users can select the language for the site labels from My Account. language_files - (disabled) + (disabled) For multi-lingual content setups only: A list mapping language shortcuts ('en', 'de', etc.) to the Geeklog language files to use. These shortcuts must each contain the same number of characters and the language file must exist in the Geeklog languages directory.
@@ -1475,7 +1475,7 @@

Languages and Locale: Language

Both must either be enabled (for multi-language content) or disabled (for content of only one language). languages - (disabled) + (disabled) For multi-lingual content setups only: A list mapping language shortcuts ('en', 'de', etc.) to the language's native name ("English", "Deutsch", etc.). These shortcuts must match the shortcuts set in the "Language Files" configuration option.
@@ -1527,7 +1527,7 @@

Languages and Locale: Locale

week_start Sun - First day of the week in the calendar. Can be either 'Sun' (Sunday) or 'Mon' (Monday). + First day of the week in the calendar. Can be either 'Sun' (Sunday) or 'Mon' (Monday). hour_mode 12 @@ -1548,7 +1548,7 @@

Languages and Locale: Locale

How many decimal places to display. timezone - (disabled) + (disabled) If your server is located in a different timezone, use this option to set your local (i.e. your own) timezone, so that the time and date on the site match your own.
@@ -1614,7 +1614,7 @@

Miscellaneous: Cookies

Cookie path (see the PHP manual for details). cookiedomain - (empty) + (empty) The domain that the cookie is available. Geeklog will attempt to guess the correct value for this setting (based on the 'site_url' variable). See the PHP manual for details. cookiesecure @@ -1631,11 +1631,11 @@

Miscellaneous: Miscellaneous

notification array() - Send an email notification to $_CONF['site_email'] + Send an email notification to $_CONF['site_email'] when a new story, comment, trackback or pingback has been submitted - or a new user has registered with the site. The array() can hold - any combination of the strings 'story', 'comment', - 'trackback', 'pingback', and 'user' (separated + or a new user has registered with the site. The array() can hold + any combination of the strings 'story', 'comment', + 'trackback', 'pingback', and 'user' (separated by commas), depending on which notification(s) you want.
Example: array('story','user'); would send notifications when a new story has been submitted or a new user has @@ -1647,7 +1647,7 @@

Miscellaneous: Miscellaneous

Geeklog can emulate a cronjob, i.e. trigger a certain action at a given time. The code to be executed can be provided by a plugin or through the CUSTOM_runScheduledTask function in your - lib-custom.php. The value given is in seconds and specifies the + lib-custom.php. The value given is in seconds and specifies the interval in which the code should be executed (e.g. 86400 for daily activation).
Please note that to trigger this action, you will need to have someone @@ -1687,7 +1687,7 @@

Miscellaneous: Miscellaneous

href="http://en.wikipedia.org/wiki/Clickjacking">Clickjacking: This option indicates that the site's content should not be displayed in a frame. This only works, however, when the visitor's browser respects the - X-FRAME-OPTIONS HTTP header. Options are to disallow all framing + X-FRAME-OPTIONS HTTP header. Options are to disallow all framing (Strict), only allow framing from within the same site (Same Origin), or to allow all framing (disabled). We strongly suggest not to disable this option. @@ -1727,7 +1727,7 @@

Miscellaneous: Debug

for debugging purposes!
Tip: If an error prevents you from logging into your site to enable that option, you can also enable it in your - siteconfig.php file. + siteconfig.php file.

Miscellaneous: Daily Digest

@@ -1746,7 +1746,7 @@

Miscellaneous: Daily Digest

1 When emailstories (above) is enabled, send only the title and the link to the new stories (0), or send the entire introtext (1) or send - the first n characters from the introtext (where n = any other number) + the first n characters from the introtext (where n = any other number) emailstoriesperdefault 0 @@ -1806,7 +1806,7 @@

Miscellaneous: Censoring

Text to replace a censored word with censorlist - array(a list of "bad" words goes here ...) + array(a list of "bad" words goes here ...) An array of censored words @@ -1818,7 +1818,7 @@

Miscellaneous: IP Lookup

Description ip_lookup - not set + not set The IP addresses of comment posters are logged and displayed for admin users. When this variable is set to point to a service that can do IP address lookups, it's possible to lookup the owner of an IP address by clicking on it, making it easier to report abuse to ISPs, etc.
$_CONF['ip_lookup'] should hold the complete URL to the lookup service, with a '*' marking the place where the IP address should go. It's also possible to use Tom Willet's NetTools package, in which case the correct setting would be $_CONF['ip_lookup'] = $_CONF['site_url'] . '/nettools/whois.php?domain=*'; @@ -1837,7 +1837,7 @@

Miscellaneous: Webservices

restrict_webservices false Set this to true to restrict webservices usage - to users with the webservices.atompub permission (e.g. those in + to users with the webservices.atompub permission (e.g. those in the predefined "Webservices Users" group). atom_max_stories @@ -2027,7 +2027,7 @@

File Manager: Audios

db-config.php

-

As the name implies, the file db-config.php contains the database +

As the name implies, the file db-config.php contains the database configuration. This information is put there during the initial install and you should not normally have to edit this file.

@@ -2037,7 +2037,7 @@

db-config.php

Description _DB_host localhost - Database Server (to be entered in the form: hostname:port:unixsocket). In most cases you won't need to change the default value. + Database Server (to be entered in the form: hostname:port:unixsocket). In most cases you won't need to change the default value. _DB_name geeklog Database Name @@ -2061,7 +2061,7 @@

db-config.php

siteconfig.php

-

The siteconfig.php file holds configuration data that can not be +

The siteconfig.php file holds configuration data that can not be stored in the database. Again, most of this information is put there during the installation and you should not normally have to edit this file.

@@ -2092,13 +2092,13 @@

siteconfig.php

set is recommended. rootdebug - (disabled) + (disabled) Same as the 'rootdebug' option in the Configuration. However, sometimes an error may occur that prevents you from logging into your site and enabling the 'rootdebug' option. In such a case, you can uncomment this line and enable the option here.
In addition to 'true' and 'false', you can also set this option to 'force' - (only in siteconfig.php). This will enable displaying of sensitive + (only in siteconfig.php). This will enable displaying of sensitive information like passwords and cookies.
In any case, the same strong warning as above applies here, too: Do not leave this option enabled on a "live" @@ -2114,9 +2114,9 @@

URL Rewriting

supported for URLs to stories, static pages, the article directory, and links.

URL rewriting means that your URLs will look like this

-

http://www.geeklog.net/article.php/20021022234959146

+

http://www.geeklog.net/article.php/20021022234959146

instead of like this

-

http://www.geeklog.net/article.php?story=20021022234959146

+

http://www.geeklog.net/article.php?story=20021022234959146

While some search engines will pick up the second form, Google seems to prefer the first format and often ignores the second format.

Note: This feature may not work with all web servers. It @@ -2136,13 +2136,13 @@

URL Routing

- http://yourdomain/article/[sid]/print - http://yourdomain/article.php?story=[sid]&mode=print + http://yourdomain/article/@sid/print + http://yourdomain/article.php?story=@sid&mode=print 100 - http://yourdomain/article/[sid] - http://yourdomain/article.php?story=[sid] + http://yourdomain/article/@sid + http://yourdomain/article.php?story=@sid 110 @@ -2173,19 +2173,19 @@

URL Routing

-

Look at the first row in the table. This means if you access "http://yourdomain/index.php/article/[sid]/print", - then you will be redirected to "http://yourdomain/article.php?story=[sid]&mode=print". - [sid] is a story ID.

+

Look at the first row in the table. This means if you access "http://yourdomain/index.php/article/@sid/print", + then you will be redirected to "http://yourdomain/article.php?story=@sid&mode=print". + @sid is a story ID.

Then, look at the third row. You will see an at mark (@), followed by alphabetical letters. This is a placeholder. For instance, when you access "http://yourdomain/index.php/archives/all/2016/1", @topic matches "all", @year matches "2016", and @month matches "1" in the rule. Then, all placeholders in the route will be replaced with the matched values. And you will be redirected to "http://yourdomain/directory.php?topic=all&year=2016&month=1".

You don't have to include "/index.php" in a rule.

-

You must not start a route with "/index.php/", since this will cause an infinite loop. However, you can start +

You must NOT start a route with "/index.php/", since this will cause an infinite loop. However, you can start with a route with "/index.php?".

A placeholder starts with @ and an alphabetical letter or letters follow it. - Placeholders are case-sensitive.

+ Placeholders are case-sensitive.

URL Routing works in the reverse way as well. When you output a URL in your plugin or custom function, you can URL-route it by using COM_buildURL function and adding your own rule and route in the URL Routing screen (admin/router.php).

@@ -2226,7 +2226,7 @@

URL Routing

  • Finally, log in as admin and go to the Configuration screen, and set URL Routing - to "Enabled (without index.php)". + to 'Enabled (without "index.php")'.
  • @@ -2248,9 +2248,9 @@

    Locale and Date Formats

    will pull the default locale from the operating system. The date formats are handled by your locale. Isn't that smart? Locale names are OS dependent. On most UNIX hosts, you can find locale codes in the -/usr/share/locale/locale.alias file and on some systems the command -locale -a will display all available locales on a system. If a -locale doesn't exist you can create it using the localedef command.

    +/usr/share/locale/locale.alias file and on some systems the command +locale -a will display all available locales on a system. If a +locale doesn't exist you can create it using the localedef command.

    More info on locale: http://www.opengroup.org/onlinepubs/7908799/xbd/locale.html
    @@ -2260,39 +2260,39 @@

    Locale and Date Formats

    Date Format Syntax

      -
    • %a - abbreviated weekday name according to the current locale
    • -
    • %A - full weekday name according to the current locale
    • -
    • %b - abbreviated month name according to the current locale
    • -
    • %B - full month name according to the current locale
    • -
    • %c - preferred date and time representation for the current locale
    • -
    • %C - century number (the year divided by 100 and truncated to an integer, range 00 to 99)
    • -
    • %d - day of the month as a decimal number (range 00 to 31)
    • -
    • %D - same as %m/%d/%y
    • -
    • %e - day of the month as a decimal number, a single digit is preceded by a space (range ' 1' to '31')
    • -
    • %h - same as %b
    • -
    • %H - hour as a decimal number using a 24-hour clock (range 00 to 23)
    • -
    • %I - hour as a decimal number using a 12-hour clock (range 01 to 12)
    • -
    • %j - day of the year as a decimal number (range 001 to 366)
    • -
    • %m - month as a decimal number (range 1 to 12)
    • -
    • %M - minute as a decimal number
    • -
    • %n - newline character
    • -
    • %p - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale
    • -
    • %r - time in a.m. and p.m. notation
    • -
    • %R - time in 24 hour notation
    • -
    • %S - second as a decimal number
    • -
    • %t - tab character
    • -
    • %T - current time, equal to %H:%M:%S
    • -
    • %u - weekday as a decimal number [1,7], with 1 representing Monday
    • -
    • %U - week number of the current year as a decimal number, starting with the first Sunday as the first day of the first week
    • -
    • %V - The ISO 8601:1988 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the current year, and with Monday as the first day of the week.
    • -
    • %W - week number of the current year as a decimal number, starting with the first Monday as the first day of the first week
    • -
    • %w - day of the week as a decimal, Sunday being 0
    • -
    • %x - preferred date representation for the current locale without the time
    • -
    • %X - preferred time representation for the current locale without the date
    • -
    • %y - year as a decimal number without a century (range 00 to 99)
    • -
    • %Y - year as a decimal number including the century
    • -
    • %Z - time zone or name or abbreviation
    • -
    • %% - a literal `%' character
    • +
    • %a - abbreviated weekday name according to the current locale
    • +
    • %A - full weekday name according to the current locale
    • +
    • %b - abbreviated month name according to the current locale
    • +
    • %B - full month name according to the current locale
    • +
    • %c - preferred date and time representation for the current locale
    • +
    • %C - century number (the year divided by 100 and truncated to an integer, range 00 to 99)
    • +
    • %d - day of the month as a decimal number (range 00 to 31)
    • +
    • %D - same as %m/%d/%y
    • +
    • %e - day of the month as a decimal number, a single digit is preceded by a space (range ' 1' to '31')
    • +
    • %h - same as %b
    • +
    • %H - hour as a decimal number using a 24-hour clock (range 00 to 23)
    • +
    • %I - hour as a decimal number using a 12-hour clock (range 01 to 12)
    • +
    • %j - day of the year as a decimal number (range 001 to 366)
    • +
    • %m - month as a decimal number (range 1 to 12)
    • +
    • %M - minute as a decimal number
    • +
    • %n - newline character
    • +
    • %p - either `am' or `pm' according to the given time value, or the corresponding strings for the current locale
    • +
    • %r - time in a.m. and p.m. notation
    • +
    • %R - time in 24 hour notation
    • +
    • %S - second as a decimal number
    • +
    • %t - tab character
    • +
    • %T - current time, equal to %H:%M:%S
    • +
    • %u - weekday as a decimal number [1,7], with 1 representing Monday
    • +
    • %U - week number of the current year as a decimal number, starting with the first Sunday as the first day of the first week
    • +
    • %V - The ISO 8601:1988 week number of the current year as a decimal number, range 01 to 53, where week 1 is the first week that has at least 4 days in the current year, and with Monday as the first day of the week.
    • +
    • %W - week number of the current year as a decimal number, starting with the first Monday as the first day of the first week
    • +
    • %w - day of the week as a decimal, Sunday being 0
    • +
    • %x - preferred date representation for the current locale without the time
    • +
    • %X - preferred time representation for the current locale without the date
    • +
    • %y - year as a decimal number without a century (range 00 to 99)
    • +
    • %Y - year as a decimal number including the century
    • +
    • %Z - time zone or name or abbreviation
    • +
    • %% - a literal `%' character