857 lines
29 KiB
PHP
857 lines
29 KiB
PHP
<?php
|
|
# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
|
|
# All rights reserved. See LICENSE file for licensing details
|
|
|
|
if (IN_serendipity !== true) {
|
|
die ("Don't hack!");
|
|
}
|
|
|
|
/**
|
|
* Converts a string into a filename that can be used safely in HTTP URLs
|
|
*
|
|
* @access public
|
|
* @param string input string
|
|
* @param boolean Shall dots in the filename be removed? (Required for certain regex rules)
|
|
* @return string output string
|
|
*/
|
|
function serendipity_makeFilename($str, $stripDots = false) {
|
|
|
|
// These are UTF-8 replacements happening regardless of selected locale
|
|
static $pre_from = array(
|
|
'🇦',
|
|
'🇧',
|
|
'🇨',
|
|
'🇩',
|
|
'🇪',
|
|
'🇫',
|
|
'🇬',
|
|
'🇭',
|
|
'🇮',
|
|
'🇯',
|
|
'🇰',
|
|
'🇱',
|
|
'🇲',
|
|
'🇳',
|
|
'🇴',
|
|
'🇵',
|
|
'🇶',
|
|
'🇷',
|
|
'🇸',
|
|
'🇹',
|
|
'🇺',
|
|
'🇻',
|
|
'🇼',
|
|
'🇽',
|
|
'🇾',
|
|
'🇿');
|
|
|
|
static $pre_to = array(
|
|
'A',
|
|
'B',
|
|
'C',
|
|
'D',
|
|
'E',
|
|
'F',
|
|
'G',
|
|
'H',
|
|
'I',
|
|
'J',
|
|
'L',
|
|
'M',
|
|
'N',
|
|
'O',
|
|
'P',
|
|
'Q',
|
|
'R',
|
|
'S',
|
|
'T',
|
|
'U',
|
|
'V',
|
|
'W',
|
|
'X',
|
|
'Y',
|
|
'Z');
|
|
|
|
// These are replacements happening after all UTF-8 characters have been stripped away
|
|
static $from = array(
|
|
' ',
|
|
'%',
|
|
|
|
'Ä',
|
|
'ä',
|
|
|
|
'Ö',
|
|
'ö',
|
|
|
|
'Ü',
|
|
'ü',
|
|
|
|
'ß',
|
|
|
|
'é',
|
|
'è',
|
|
'ê',
|
|
|
|
'í',
|
|
'ì',
|
|
'î',
|
|
|
|
'á',
|
|
'à',
|
|
'â',
|
|
'å',
|
|
|
|
'ó',
|
|
'ò',
|
|
'ô',
|
|
'õ',
|
|
|
|
'ú',
|
|
'ù',
|
|
'û',
|
|
|
|
'ç',
|
|
'Ç',
|
|
|
|
'ñ',
|
|
|
|
'ý');
|
|
|
|
static $to = array(
|
|
'-',
|
|
'%25',
|
|
|
|
'AE',
|
|
'ae',
|
|
|
|
'OE',
|
|
'oe',
|
|
|
|
'UE',
|
|
'ue',
|
|
|
|
'ss',
|
|
|
|
'e',
|
|
'e',
|
|
'e',
|
|
|
|
'i',
|
|
'i',
|
|
'i',
|
|
|
|
'a',
|
|
'a',
|
|
'a',
|
|
'a',
|
|
|
|
'o',
|
|
'o',
|
|
'o',
|
|
'o',
|
|
|
|
'u',
|
|
'u',
|
|
'u',
|
|
|
|
'c',
|
|
'C',
|
|
|
|
'n',
|
|
|
|
'y');
|
|
|
|
if (isset($GLOBALS['i18n_filename_utf8'])) {
|
|
$str = str_replace(' ', '_', $str);
|
|
$str = str_replace('&', '%25', $str);
|
|
$str = str_replace('/', '%2F', $str);
|
|
$str = urlencode($str);
|
|
} else {
|
|
// Replace some emojis and flags into latin characters before utf8_decode() strips them away
|
|
$str = str_replace($pre_from, $pre_to, $str);
|
|
|
|
if (isset($GLOBALS['i18n_filename_from'])) {
|
|
// Replace international chars not detected by every locale.
|
|
// The array of chars is defined in the language file.
|
|
$str = str_replace($GLOBALS['i18n_filename_from'], $GLOBALS['i18n_filename_to'], $str);
|
|
|
|
// URLs need to be 7bit - since this function takes care of the most common ISO-8859-1
|
|
// characters, try to UTF8-decode the string first.
|
|
$str = utf8_decode($str);
|
|
} else {
|
|
// Replace international chars not detected by every locale
|
|
$str = str_replace($from, $to, $str);
|
|
|
|
// URLs need to be 7bit - since this function takes care of the most common ISO-8859-1
|
|
// characters, try to UTF8-decode the string first.
|
|
$str = utf8_decode($str);
|
|
}
|
|
|
|
// Nuke chars not allowed in our URI
|
|
$str = preg_replace('#[^' . PAT_FILENAME . ']#i', '', $str);
|
|
}
|
|
|
|
// Check if dots are allowed
|
|
if ($stripDots) {
|
|
$str = str_replace('.', '', $str);
|
|
}
|
|
|
|
// Remove consecutive separators
|
|
$str = preg_replace('#'. $to[0] .'{2,}#s', $to[0], $str);
|
|
|
|
// Remove excess separators
|
|
$str = trim($str, $to[0]);
|
|
|
|
if (empty($str)) {
|
|
if (isset($GLOBALS['i18n_unknown'])) {
|
|
$str = $GLOBALS['i18n_unknown'];
|
|
} else {
|
|
$str = 'unknown';
|
|
}
|
|
}
|
|
|
|
return $str;
|
|
}
|
|
|
|
/**
|
|
* Initialize permalinks, if the user did not specify those yet
|
|
*
|
|
* @access public
|
|
* @return null
|
|
*/
|
|
function serendipity_initPermalinks() {
|
|
global $serendipity;
|
|
|
|
if (!isset($serendipity['permalinkStructure'])) {
|
|
$serendipity['permalinkStructure'] = 'archives/%id%-%title%.html';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkFeedAuthorStructure'])) {
|
|
$serendipity['permalinkFeedAuthorStructure'] = 'feeds/authors/%id%-%realname%.rss';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkFeedCategoryStructure'])) {
|
|
$serendipity['permalinkFeedCategoryStructure'] = 'feeds/categories/%id%-%name%.rss';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkCategoryStructure'])) {
|
|
$serendipity['permalinkCategoryStructure'] = 'categories/%id%-%name%';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkAuthorStructure'])) {
|
|
$serendipity['permalinkAuthorStructure'] = 'authors/%id%-%realname%';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkArchivesPath'])) {
|
|
$serendipity['permalinkArchivesPath'] = 'archives';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkArchivePath'])) {
|
|
$serendipity['permalinkArchivePath'] = 'archive';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkCategoriesPath'])) {
|
|
$serendipity['permalinkCategoriesPath'] = 'categories';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkAuthorsPath'])) {
|
|
$serendipity['permalinkAuthorsPath'] = 'authors';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkUnsubscribePath'])) {
|
|
$serendipity['permalinkUnsubscribePath'] = 'unsubscribe';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkDeletePath'])) {
|
|
$serendipity['permalinkDeletePath'] = 'delete';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkApprovePath'])) {
|
|
$serendipity['permalinkApprovePath'] = 'approve';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkFeedsPath'])) {
|
|
$serendipity['permalinkFeedsPath'] = 'feeds';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkPluginPath'])) {
|
|
$serendipity['permalinkPluginPath'] = 'plugin';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkAdminPath'])) {
|
|
$serendipity['permalinkAdminPath'] = 'admin';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkSearchPath'])) {
|
|
$serendipity['permalinkSearchPath'] = 'search';
|
|
}
|
|
|
|
if (!isset($serendipity['permalinkCommentsPath'])) {
|
|
$serendipity['permalinkCommentsPath'] = 'comments';
|
|
}
|
|
|
|
/* URI paths
|
|
* These could be defined in the language headers, except that would break
|
|
* backwards URL compatibility
|
|
*/
|
|
@define('PATH_ARCHIVES', $serendipity['permalinkArchivesPath']);
|
|
@define('PATH_ARCHIVE', $serendipity['permalinkArchivePath']);
|
|
@define('PATH_CATEGORIES', $serendipity['permalinkCategoriesPath']);
|
|
@define('PATH_UNSUBSCRIBE', $serendipity['permalinkUnsubscribePath']);
|
|
@define('PATH_DELETE', $serendipity['permalinkDeletePath']);
|
|
@define('PATH_APPROVE', $serendipity['permalinkApprovePath']);
|
|
@define('PATH_FEEDS', $serendipity['permalinkFeedsPath']);
|
|
@define('PATH_PLUGIN', $serendipity['permalinkPluginPath']);
|
|
@define('PATH_ADMIN', $serendipity['permalinkAdminPath']);
|
|
@define('PATH_SEARCH', $serendipity['permalinkSearchPath']);
|
|
@define('PATH_COMMENTS', $serendipity['permalinkCommentsPath']);
|
|
|
|
/* URI patterns
|
|
* Note that it's important to use @ as the pattern delimiter. DO NOT use shortcuts
|
|
* like \d or \s, since mod_rewrite will use the regexps as well and chokes on them.
|
|
* If you add new patterns, remember to add the new rules to the *.tpl files and
|
|
* function serendipity_installFiles().
|
|
*/
|
|
@define('PAT_FILENAME', '0-9a-z\.\_!;,\+\-\%');
|
|
@define('PAT_FILENAME_MATCH', '[' . PAT_FILENAME . ']+');
|
|
@define('PAT_DIRNAME_MATCH', '[' . PAT_FILENAME . '/]*');
|
|
@define('PAT_CSS', '@/(serendipity\.css|serendipity_admin\.css)@');
|
|
@define('PAT_JS', '@/(serendipity\.js|serendipity_admin\.js)@');
|
|
@define('PAT_FEED', '@/(index|atom[0-9]*|rss|b2rss|b2rdf).(rss|rdf|rss2|xml)@');
|
|
@define('PAT_COMMENTSUB', '@/([0-9]+)[_\-][' . PAT_FILENAME . ']*\.html@i');
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Build an array containing all regular expression permalinks
|
|
*
|
|
* @access public
|
|
* @param boolean If set to true, the list of permalinks will be returned. If false, all permalinks will be applied as Constants
|
|
* @return array (conditional on $return) List of permalinks
|
|
*/
|
|
function &serendipity_permalinkPatterns($return = false) {
|
|
global $serendipity;
|
|
|
|
$PAT = array();
|
|
|
|
$PAT['UNSUBSCRIBE'] = '@/' . $serendipity['permalinkUnsubscribePath'].'/(.*)/([0-9]+)@';
|
|
$PAT['APPROVE'] = '@/' . $serendipity['permalinkApprovePath'].'/(.*)/(.*)/([0-9]+)@';
|
|
$PAT['DELETE'] = '@/' . $serendipity['permalinkDeletePath'].'/(.*)/(.*)/([0-9]+)@';
|
|
$PAT['ARCHIVES'] = '@/' . $serendipity['permalinkArchivesPath'].'([/A-Za-z0-9]+)\.html@';
|
|
$PAT['FEEDS'] = '@/' . $serendipity['permalinkFeedsPath'].'/@';
|
|
$PAT['ADMIN'] = '@/(' . $serendipity['permalinkAdminPath'] . '|entries)(/.+)?$@';
|
|
$PAT['ARCHIVE'] = '@/' . $serendipity['permalinkArchivePath'] . '/?@';
|
|
$PAT['CATEGORIES'] = '@/' . $serendipity['permalinkCategoriesPath'].'/([0-9;]+)@';
|
|
$PAT['PLUGIN'] = '@/(' . $serendipity['permalinkPluginPath'] . '|plugin)/(.*)@';
|
|
$PAT['SEARCH'] = '@/' . $serendipity['permalinkSearchPath'] . '/(.*)@';
|
|
$PAT['COMMENTS'] = '@/' . $serendipity['permalinkCommentsPath'] . '/(.*)@';
|
|
$PAT['PERMALINK'] = '@(' . serendipity_makePermalinkRegex($serendipity['permalinkStructure'], 'entry') . ')/?@i';
|
|
$PAT['PERMALINK_CATEGORIES'] = '@' . serendipity_makePermalinkRegex($serendipity['permalinkCategoryStructure'], 'category') . '@i';
|
|
$PAT['PERMALINK_FEEDCATEGORIES'] = '@' . serendipity_makePermalinkRegex($serendipity['permalinkFeedCategoryStructure'], 'category') . '@i';
|
|
$PAT['PERMALINK_FEEDAUTHORS'] = '@' . serendipity_makePermalinkRegex($serendipity['permalinkFeedAuthorStructure'], 'author') . '@i';
|
|
$PAT['PERMALINK_AUTHORS'] = '@' . serendipity_makePermalinkRegex($serendipity['permalinkAuthorStructure'], 'author') . '@i';
|
|
|
|
if ($return) {
|
|
return $PAT;
|
|
} else {
|
|
foreach($PAT AS $constant => $value) {
|
|
define('PAT_' . $constant, $value);
|
|
}
|
|
|
|
$return = true;
|
|
return $return;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Search the reference to a specific permalink
|
|
*
|
|
* This query will show the Entry/Category/Author-ID to a permalink, if that permalink
|
|
* does not contain %id%.
|
|
*
|
|
* @access public
|
|
* @param string The permalink configuration string
|
|
* @param string The URL to check
|
|
* @param string A default return value if no permalink is found
|
|
* @param string The type of a permalink (entry|category|author)
|
|
* @return string The ID of the permalink type
|
|
*/
|
|
function serendipity_searchPermalink($struct, $url, $default, $type = 'entry') {
|
|
global $serendipity;
|
|
|
|
if (stristr($struct, '%id%') === FALSE) {
|
|
$url = preg_replace('@^(' . preg_quote($serendipity['serendipityHTTPPath'], '@') . '(' . preg_quote($serendipity['indexFile'], '@') . ')?\??(url=)?/?)([^&?]+).*@', '\4', $url);
|
|
// If no entryid is submitted, we rely on a new DB call to fetch the permalink.
|
|
$pq = "SELECT entry_id, data
|
|
FROM {$serendipity['dbPrefix']}permalinks
|
|
WHERE (permalink = '" . serendipity_db_escape_string($url) . "'
|
|
OR permalink = '" . serendipity_db_escape_string($default) . "')
|
|
AND type = '" . serendipity_db_escape_string($type) . "'
|
|
AND entry_id > 0
|
|
LIMIT 1";
|
|
// echo $pq; // DEBUG
|
|
// die($pq); // DEBUG
|
|
$permalink = serendipity_db_query($pq, true, 'both', false, false, false, true);
|
|
|
|
if (is_array($permalink)) {
|
|
return $permalink['entry_id'];
|
|
}
|
|
}
|
|
|
|
return $default;
|
|
}
|
|
|
|
/**
|
|
* Create a permalink for the given input data
|
|
*
|
|
* You can pass an entry array, or an author array to this function
|
|
* and then get a permalink valid for that array
|
|
*
|
|
* @access public
|
|
* @param array The input data used for building the permalink
|
|
* @param string The type of the permalink (entry|category|author)
|
|
* @return string The permalink
|
|
*/
|
|
function serendipity_getPermalink(&$data, $type = 'entry') {
|
|
switch($type) {
|
|
case 'entry':
|
|
return serendipity_archiveURL(
|
|
$data['id'],
|
|
$data['title'],
|
|
'',
|
|
false,
|
|
array('timestamp' => $data['timestamp'])
|
|
);
|
|
break;
|
|
|
|
case 'category':
|
|
return serendipity_categoryURL($data, '', false);
|
|
break;
|
|
|
|
case 'author':
|
|
return serendipity_authorURL($data, '', false);
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Update a permalink with new data
|
|
*
|
|
* @access public
|
|
* @param array The input data used for building the permalink
|
|
* @param string The type of the permalink (entry|category|author)
|
|
* @return string The database result
|
|
*/
|
|
function serendipity_updatePermalink(&$data, $type = 'entry') {
|
|
global $serendipity;
|
|
|
|
$link = serendipity_getPermalink($data, $type);
|
|
return(serendipity_db_query(sprintf("UPDATE {$serendipity['dbPrefix']}permalinks
|
|
SET permalink = '%s'
|
|
WHERE entry_id = %s
|
|
AND type = '%s'",
|
|
|
|
serendipity_db_escape_string($link),
|
|
(int)$data['id'],
|
|
serendipity_db_escape_string($type))));
|
|
}
|
|
|
|
/**
|
|
* Insert a new Permalink into the database for latter retrieval
|
|
*
|
|
* This function is basically only used if you have no '%id%' value in your permalink config.
|
|
*
|
|
* @access public
|
|
* @param array The input data used for building the permalink
|
|
* @param string The type of the permalink (entry|category|author)
|
|
* @return string The permalink
|
|
*/
|
|
function serendipity_insertPermalink(&$data, $type = 'entry') {
|
|
global $serendipity;
|
|
|
|
$link = serendipity_getPermalink($data, $type);
|
|
|
|
switch($type) {
|
|
case 'entry':
|
|
$idfield = 'id';
|
|
break;
|
|
|
|
case 'author':
|
|
$idfield = 'authorid';
|
|
break;
|
|
|
|
case 'category':
|
|
$idfield = 'categoryid';
|
|
break;
|
|
}
|
|
|
|
return(serendipity_db_query(sprintf("INSERT INTO {$serendipity['dbPrefix']}permalinks
|
|
(permalink, entry_id, type)
|
|
VALUES ('%s', '%s', '%s')",
|
|
|
|
serendipity_db_escape_string($link),
|
|
(int)$data[$idfield],
|
|
serendipity_db_escape_string($type))));
|
|
}
|
|
|
|
/**
|
|
* Build all permalinks for all current entries, authors and categories
|
|
*
|
|
* @access public
|
|
* @return null
|
|
*/
|
|
function serendipity_buildPermalinks() {
|
|
global $serendipity;
|
|
|
|
serendipity_db_begin_transaction();
|
|
|
|
$entries = serendipity_db_query("SELECT id, title, timestamp FROM {$serendipity['dbPrefix']}entries");
|
|
|
|
if (is_array($entries)) {
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}permalinks WHERE type = 'entry'");
|
|
|
|
foreach($entries AS $entry) {
|
|
serendipity_insertPermalink($entry, 'entry');
|
|
}
|
|
}
|
|
|
|
$authors = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}authors");
|
|
|
|
if (is_array($authors)) {
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}permalinks WHERE type = 'author'");
|
|
|
|
foreach($authors AS $author) {
|
|
serendipity_insertPermalink($author, 'author');
|
|
}
|
|
}
|
|
|
|
$categories = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}category");
|
|
|
|
if (is_array($categories)) {
|
|
serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}permalinks WHERE type = 'category'");
|
|
|
|
serendipity_plugin_api::hook_event('multilingual_strip_langs',$categories, array('category_name','category_description'));
|
|
foreach($categories AS $category) {
|
|
serendipity_insertPermalink($category, 'category');
|
|
}
|
|
}
|
|
|
|
serendipity_db_end_transaction(true);
|
|
}
|
|
|
|
/**
|
|
* Uses logic to figure out how the URI should look, based on current rewrite rule
|
|
*
|
|
* @access public
|
|
* @param string The URL part that you want to format to "pretty urls"
|
|
* @param string The path/URL you want as a prefix for your pretty URL
|
|
* @param boolean If set to TRUE this will bypass all pretty URLs and format the link so that it works everywhere
|
|
* @return string The rewritten URL
|
|
*/
|
|
function serendipity_rewriteURL($path, $key='baseURL', $forceNone = false) {
|
|
global $serendipity;
|
|
return ($serendipity[$key] ?? null) . ($serendipity['rewrite'] == 'none' || ($serendipity['rewrite'] != 'none' && $forceNone) ? $serendipity['indexFile'] . '?/' : '') . $path;
|
|
}
|
|
|
|
/**
|
|
* Format a permalink according to the configured format
|
|
*
|
|
* @access public
|
|
* @param string The URL format to use
|
|
* @param array The input data to format a permalink
|
|
* @param string The type of the permalink (entry|category|author)
|
|
* @return string The formatted permalink
|
|
*/
|
|
function serendipity_makePermalink($format, $data, $type = 'entry') {
|
|
global $serendipity;
|
|
static $entryKeys = array('%id%', '%lowertitle%', '%title%', '%day%', '%month%', '%year%');
|
|
static $authorKeys = array('%id%', '%username%', '%realname%', '%email%');
|
|
static $categoryKeys = array('%id%', '%name%', '%parentname%', '%description%');
|
|
|
|
switch($type) {
|
|
case 'entry':
|
|
if (!isset($data['entry']['timestamp']) && preg_match('@(%day%|%month%|%year%)@', $format)) {
|
|
// We need the timestamp to build the URI, but no timestamp has been submitted. Thus we need to fetch the data.
|
|
$ts = serendipity_db_query("SELECT timestamp FROM {$serendipity['dbPrefix']}entries WHERE id = " . (int)$data['id'], true);
|
|
if (is_array($ts)) {
|
|
$data['entry']['timestamp'] = $ts['timestamp'];
|
|
} else {
|
|
$data['entry']['timestamp'] = time();
|
|
}
|
|
}
|
|
|
|
$ts = serendipity_serverOffsetHour($data['entry']['timestamp'] ?? null);
|
|
|
|
$ftitle = serendipity_makeFilename($data['title']);
|
|
$fltitle = strtolower($ftitle);
|
|
|
|
$replacements =
|
|
array(
|
|
(int)$data['id'],
|
|
$fltitle,
|
|
$ftitle,
|
|
date('d', $ts),
|
|
date('m', $ts),
|
|
date('Y', $ts)
|
|
);
|
|
return str_replace($entryKeys, $replacements, $format);
|
|
break;
|
|
|
|
case 'author':
|
|
$replacements =
|
|
array(
|
|
(int)$data['authorid'],
|
|
serendipity_makeFilename($data['username'], true),
|
|
serendipity_makeFilename($data['realname'], true),
|
|
serendipity_makeFilename($data['email'], true)
|
|
);
|
|
return str_replace($authorKeys, $replacements, $format);
|
|
break;
|
|
|
|
case 'category':
|
|
$parent_path = array();
|
|
|
|
// This is expensive. Only lookup if required.
|
|
if (strstr($format, '%parentname%')) {
|
|
$parents = serendipity_getCategoryRoot($data['categoryid']);
|
|
if (is_array($parents)) {
|
|
foreach($parents AS $parent) {
|
|
$parent_path[] = serendipity_makeFilename($parent['category_name'], true);
|
|
}
|
|
}
|
|
}
|
|
|
|
$replacements =
|
|
array(
|
|
(int)$data['categoryid'],
|
|
serendipity_makeFilename($data['category_name'], true),
|
|
implode('/', $parent_path),
|
|
serendipity_makeFilename($data['category_description'], true)
|
|
);
|
|
return str_replace($categoryKeys, $replacements, $format);
|
|
break;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Convert a permalink configuration into a regular expression for use in rewrite rules
|
|
*
|
|
* @access public
|
|
* @param string The URL format to use
|
|
* @param string The type of the permalink (entry|category|author)
|
|
* @return string The regular expression to a permalink URL
|
|
*/
|
|
function serendipity_makePermalinkRegex($format, $type = 'entry') {
|
|
static $entryKeys = array('%id%', '%lowertitle%', '%title%', '%day%', '%month%', '%year%');
|
|
static $entryRegexValues = array('([0-9]+)', PAT_FILENAME_MATCH, PAT_FILENAME_MATCH, '[0-9]{1,2}', '[0-9]{1,2}', '[0-9]{4}');
|
|
|
|
static $authorKeys = array('%id%', '%username%', '%realname%', '%email%');
|
|
static $authorRegexValues = array('([0-9]+)', PAT_FILENAME_MATCH, PAT_FILENAME_MATCH, PAT_FILENAME_MATCH);
|
|
|
|
static $categoryKeys = array('%id%', '%name%', '%parentname%', '%description%');
|
|
static $categoryRegexValues = array('([0-9;]+)', PAT_FILENAME_MATCH, PAT_DIRNAME_MATCH, PAT_FILENAME_MATCH);
|
|
|
|
switch($type) {
|
|
case 'entry':
|
|
return str_replace($entryKeys, $entryRegexValues, preg_quote($format));
|
|
break;
|
|
|
|
case 'author':
|
|
return str_replace($authorKeys, $authorRegexValues, preg_quote($format));
|
|
break;
|
|
|
|
case 'category':
|
|
return str_replace($categoryKeys, $categoryRegexValues, preg_quote($format));
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Create a permalink for an entry permalink
|
|
*
|
|
* @access public
|
|
* @param int The entry ID
|
|
* @param string The entry title
|
|
* @param string The base URL/path key
|
|
* @param boolean Shall the link be rewritten to a pretty URL?
|
|
* @param array Additional entry data
|
|
* @return string The permalink
|
|
*/
|
|
function serendipity_archiveURL($id, $title, $key = 'baseURL', $checkrewrite = true, $entryData = null) {
|
|
global $serendipity;
|
|
$path = serendipity_makePermalink($serendipity['permalinkStructure'], array('id'=> $id, 'title' => $title, 'entry' => $entryData));
|
|
if ($checkrewrite) {
|
|
$path = serendipity_rewriteURL($path, $key);
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Create a permalink for an authors permalink
|
|
*
|
|
* @access public
|
|
* @param array The author data
|
|
* @param string The base URL/path key
|
|
* @param boolean Shall the link be rewritten to a pretty URL?
|
|
* @return string The permalink
|
|
*/
|
|
function serendipity_authorURL(&$data, $key = 'baseURL', $checkrewrite = true) {
|
|
global $serendipity;
|
|
$path = serendipity_makePermalink($serendipity['permalinkAuthorStructure'], $data, 'author');
|
|
if ($checkrewrite) {
|
|
$path = serendipity_rewriteURL($path, $key);
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Create a permalink for an category permalink
|
|
*
|
|
* @access public
|
|
* @param array The category data
|
|
* @param string The base URL/path key
|
|
* @param boolean Shall the link be rewritten to a pretty URL?
|
|
* @return string The permalink
|
|
*/
|
|
function serendipity_categoryURL(&$data, $key = 'baseURL', $checkrewrite = true) {
|
|
global $serendipity;
|
|
$path = serendipity_makePermalink($serendipity['permalinkCategoryStructure'], $data, 'category');
|
|
if ($checkrewrite) {
|
|
$path = serendipity_rewriteURL($path, $key);
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Create a permalink for an RSS feed permalink
|
|
*
|
|
* @access public
|
|
* @param array The entry data
|
|
* @param string The base URL/path key
|
|
* @param boolean Shall the link be rewritten to a pretty URL?
|
|
* @return string The permalink
|
|
*/
|
|
function serendipity_feedCategoryURL(&$data, $key = 'baseURL', $checkrewrite = true) {
|
|
global $serendipity;
|
|
$path = serendipity_makePermalink($serendipity['permalinkFeedCategoryStructure'], $data, 'category');
|
|
if ($checkrewrite) {
|
|
$path = serendipity_rewriteURL($path, $key);
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Create a permalink for an RSS authors' feed permalink
|
|
*
|
|
* @access public
|
|
* @param array The entry data
|
|
* @param string The base URL/path key
|
|
* @param boolean Shall the link be rewritten to a pretty URL?
|
|
* @return string The permalink
|
|
*/
|
|
function serendipity_feedAuthorURL(&$data, $key = 'baseURL', $checkrewrite = true) {
|
|
global $serendipity;
|
|
$path = serendipity_makePermalink($serendipity['permalinkFeedAuthorStructure'], $data, 'author');
|
|
if ($checkrewrite) {
|
|
$path = serendipity_rewriteURL($path, $key);
|
|
}
|
|
return $path;
|
|
}
|
|
|
|
/**
|
|
* Create a permalink for an archive date
|
|
*
|
|
* @access public
|
|
* @param string The archive's date
|
|
* @param boolean If true, only summary archive
|
|
* @param string The base URL/path key
|
|
* @return string The permalink
|
|
*/
|
|
function serendipity_archiveDateUrl($range, $summary=false, $key='baseURL') {
|
|
return serendipity_rewriteURL(PATH_ARCHIVES . '/' . $range . ($summary ? '/summary' : '') . '.html', $key);
|
|
}
|
|
|
|
/**
|
|
* Returns the URL to the current page that is being viewed
|
|
*
|
|
* @access public
|
|
* @return string the current URL
|
|
*/
|
|
function serendipity_currentURL($strict = false) {
|
|
global $serendipity;
|
|
|
|
// All that URL getting humpty-dumpty is necessary to allow a user to change the template in the
|
|
// articles view. POSTing data to that page only works with mod_rewrite and not the ErrorDocument
|
|
// redirection, so we need to generate the ErrorDocument-URI here.
|
|
|
|
$uri = @parse_url($_SERVER['REQUEST_URI']);
|
|
$qst = '';
|
|
if (!empty($uri['query'])) {
|
|
$qst = '&' . str_replace('&', '&', $uri['query']);
|
|
}
|
|
$uri['path'] = preg_replace('@^' . preg_quote($serendipity['serendipityHTTPPath']) . '@i', ($strict ? '/' : ''), $uri['path']);
|
|
$uri['path'] = preg_replace('@^(&)?' . preg_quote($serendipity['indexFile']) . '(&)@i', '', $uri['path']);
|
|
$url = $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] . '?' . $uri['path'] . $qst;
|
|
$url = str_replace(
|
|
array(
|
|
$serendipity['indexFile'] . '&',
|
|
'"',
|
|
"'",
|
|
'<',
|
|
'>',
|
|
'`'
|
|
),
|
|
|
|
array(
|
|
'',
|
|
'',
|
|
'',
|
|
'',
|
|
''
|
|
),
|
|
|
|
$url); // Kill possible looped repitions and bad characters which could occur
|
|
|
|
if ($strict) {
|
|
$url = preg_replace('@(//+)@', '/', $url);
|
|
}
|
|
|
|
return $url;
|
|
}
|
|
|
|
/**
|
|
* Get the URI Arguments for the current HTTP Request
|
|
*
|
|
* @access public
|
|
* @param string The URI made for this request
|
|
* @param boolean If enabled, then no Dots are allowed in the URL for permalinks
|
|
* @return
|
|
*/
|
|
function serendipity_getUriArguments($uri, $wildcard = false) {
|
|
global $serendipity;
|
|
static $indexFile = null;
|
|
|
|
if ($indexFile === null) {
|
|
$_indexFile = explode('.', $serendipity['indexFile']);
|
|
$indexFile = $_indexFile[0];
|
|
}
|
|
|
|
/* Explode the path into sections, to later be able to check for arguments and add our own */
|
|
preg_match('/^'. preg_quote($serendipity['serendipityHTTPPath'], '/') . '(' . preg_quote($serendipity['indexFile'], '/') . '\?\/)?(' . ($wildcard ? '.+' : '[!;,_a-z0-9\-*\/%\+]+') . ')/i', $uri, $_res);
|
|
if (strlen($_res[2] ?? null) != 0) {
|
|
$args = explode('/', $_res[2]);
|
|
if ($args[0] == $indexFile || $args[0] == $serendipity['indexFile']) {
|
|
unset($args[0]);
|
|
}
|
|
$args = array_unique($args);
|
|
return $args;
|
|
} else {
|
|
return array();
|
|
}
|
|
}
|