1<?php 2# Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team) 3# All rights reserved. See LICENSE file for licensing details 4 5if (IN_serendipity !== true) { 6 die ("Don't hack!"); 7} 8 9/** 10 * Converts a string into a filename that can be used safely in HTTP URLs 11 * 12 * @access public 13 * @param string input string 14 * @param boolean Shall dots in the filename be removed? (Required for certain regex rules) 15 * @return string output string 16 */ 17function serendipity_makeFilename($str, $stripDots = false) { 18 static $from = array( 19 ' ', 20 '%', 21 22 '�', 23 '�', 24 25 '�', 26 '�', 27 28 '�', 29 '�', 30 31 '�', 32 33 '�', 34 '�', 35 '�', 36 37 '�', 38 '�', 39 '�', 40 41 '�', 42 '�', 43 '�', 44 '�', 45 46 '�', 47 '�', 48 '�', 49 '�', 50 51 '�', 52 '�', 53 '�', 54 55 '�', 56 '�', 57 58 '�', 59 60 '�'); 61 62 static $to = array( 63 '-', 64 '%25', 65 66 'AE', 67 'ae', 68 69 'OE', 70 'oe', 71 72 'UE', 73 'ue', 74 75 'ss', 76 77 'e', 78 'e', 79 'e', 80 81 'i', 82 'i', 83 'i', 84 85 'a', 86 'a', 87 'a', 88 'a', 89 90 'o', 91 'o', 92 'o', 93 'o', 94 95 'u', 96 'u', 97 'u', 98 99 'c', 100 'C', 101 102 'n', 103 104 'y'); 105 106 if (isset($GLOBALS['i18n_filename_utf8'])) { 107 $str = str_replace(' ', '_', $str); 108 $str = str_replace('&', '%25', $str); 109 $str = str_replace('/', '%2F', $str); 110 $str = urlencode($str); 111 } else { 112 if (isset($GLOBALS['i18n_filename_from'])) { 113 // Replace international chars not detected by every locale. 114 // The array of chars is defined in the language file. 115 $str = str_replace($GLOBALS['i18n_filename_from'], $GLOBALS['i18n_filename_to'], $str); 116 117 if (LANG_CHARSET == 'UTF-8') { 118 // URLs need to be 7bit - since this function takes care of the most common ISO-8859-1 119 // characters, try to UTF8-decode the string first. 120 $str = utf8_decode($str); 121 } 122 } else { 123 // Replace international chars not detected by every locale 124 if (LANG_CHARSET == 'UTF-8') { 125 // URLs need to be 7bit - since this function takes care of the most common ISO-8859-1 126 // characters, try to UTF8-decode the string first. 127 $str = utf8_decode($str); 128 } 129 130 $str = str_replace($from, $to, $str); 131 } 132 133 // Nuke chars not allowed in our URI 134 $str = preg_replace('#[^' . PAT_FILENAME . ']#i', '', $str); 135 } 136 137 // Check if dots are allowed 138 if ($stripDots) { 139 $str = str_replace('.', '', $str); 140 } 141 142 // Remove consecutive separators 143 $str = preg_replace('#'. $to[0] .'{2,}#s', $to[0], $str); 144 145 // Remove excess separators 146 $str = trim($str, $to[0]); 147 148 if (empty($str)) { 149 if (isset($GLOBALS['i18n_unknown'])) { 150 $str = $GLOBALS['i18n_unknown']; 151 } else { 152 $str = 'unknown'; 153 } 154 } 155 156 return $str; 157} 158 159/** 160 * Initialize permalinks, if the user did not specify those yet 161 * 162 * @access public 163 * @return null 164 */ 165function serendipity_initPermalinks() { 166 global $serendipity; 167 168 if (!isset($serendipity['permalinkStructure'])) { 169 $serendipity['permalinkStructure'] = 'archives/%id%-%title%.html'; 170 } 171 172 if (!isset($serendipity['permalinkFeedAuthorStructure'])) { 173 $serendipity['permalinkFeedAuthorStructure'] = 'feeds/authors/%id%-%realname%.rss'; 174 } 175 176 if (!isset($serendipity['permalinkFeedCategoryStructure'])) { 177 $serendipity['permalinkFeedCategoryStructure'] = 'feeds/categories/%id%-%name%.rss'; 178 } 179 180 if (!isset($serendipity['permalinkCategoryStructure'])) { 181 $serendipity['permalinkCategoryStructure'] = 'categories/%id%-%name%'; 182 } 183 184 if (!isset($serendipity['permalinkAuthorStructure'])) { 185 $serendipity['permalinkAuthorStructure'] = 'authors/%id%-%realname%'; 186 } 187 188 if (!isset($serendipity['permalinkArchivesPath'])) { 189 $serendipity['permalinkArchivesPath'] = 'archives'; 190 } 191 192 if (!isset($serendipity['permalinkArchivePath'])) { 193 $serendipity['permalinkArchivePath'] = 'archive'; 194 } 195 196 if (!isset($serendipity['permalinkCategoriesPath'])) { 197 $serendipity['permalinkCategoriesPath'] = 'categories'; 198 } 199 200 if (!isset($serendipity['permalinkAuthorsPath'])) { 201 $serendipity['permalinkAuthorsPath'] = 'authors'; 202 } 203 204 if (!isset($serendipity['permalinkUnsubscribePath'])) { 205 $serendipity['permalinkUnsubscribePath'] = 'unsubscribe'; 206 } 207 208 if (!isset($serendipity['permalinkDeletePath'])) { 209 $serendipity['permalinkDeletePath'] = 'delete'; 210 } 211 212 if (!isset($serendipity['permalinkApprovePath'])) { 213 $serendipity['permalinkApprovePath'] = 'approve'; 214 } 215 216 if (!isset($serendipity['permalinkFeedsPath'])) { 217 $serendipity['permalinkFeedsPath'] = 'feeds'; 218 } 219 220 if (!isset($serendipity['permalinkPluginPath'])) { 221 $serendipity['permalinkPluginPath'] = 'plugin'; 222 } 223 224 if (!isset($serendipity['permalinkAdminPath'])) { 225 $serendipity['permalinkAdminPath'] = 'admin'; 226 } 227 228 if (!isset($serendipity['permalinkSearchPath'])) { 229 $serendipity['permalinkSearchPath'] = 'search'; 230 } 231 232 if (!isset($serendipity['permalinkCommentsPath'])) { 233 $serendipity['permalinkCommentsPath'] = 'comments'; 234 } 235 236 /* URI paths 237 * These could be defined in the language headers, except that would break 238 * backwards URL compatibility 239 */ 240 @define('PATH_ARCHIVES', $serendipity['permalinkArchivesPath']); 241 @define('PATH_ARCHIVE', $serendipity['permalinkArchivePath']); 242 @define('PATH_CATEGORIES', $serendipity['permalinkCategoriesPath']); 243 @define('PATH_UNSUBSCRIBE', $serendipity['permalinkUnsubscribePath']); 244 @define('PATH_DELETE', $serendipity['permalinkDeletePath']); 245 @define('PATH_APPROVE', $serendipity['permalinkApprovePath']); 246 @define('PATH_FEEDS', $serendipity['permalinkFeedsPath']); 247 @define('PATH_PLUGIN', $serendipity['permalinkPluginPath']); 248 @define('PATH_ADMIN', $serendipity['permalinkAdminPath']); 249 @define('PATH_SEARCH', $serendipity['permalinkSearchPath']); 250 @define('PATH_COMMENTS', $serendipity['permalinkCommentsPath']); 251 252 /* URI patterns 253 * Note that it's important to use @ as the pattern delimiter. DO NOT use shortcuts 254 * like \d or \s, since mod_rewrite will use the regexps as well and chokes on them. 255 * If you add new patterns, remember to add the new rules to the *.tpl files and 256 * function serendipity_installFiles(). 257 */ 258 @define('PAT_FILENAME', '0-9a-z\.\_!;,\+\-\%'); 259 @define('PAT_FILENAME_MATCH', '[' . PAT_FILENAME . ']+'); 260 @define('PAT_DIRNAME_MATCH', '[' . PAT_FILENAME . '/]*'); 261 @define('PAT_CSS', '@/(serendipity\.css|serendipity_admin\.css)@'); 262 @define('PAT_JS', '@/(serendipity\.js|serendipity_admin\.js)@'); 263 @define('PAT_FEED', '@/(index|atom[0-9]*|rss|b2rss|b2rdf).(rss|rdf|rss2|xml)@'); 264 @define('PAT_COMMENTSUB', '@/([0-9]+)[_\-][' . PAT_FILENAME . ']*\.html@i'); 265 266 return true; 267} 268 269/** 270 * Build an array containing all regular expression permalinks 271 * 272 * @access public 273 * @param boolean If set to true, the list of permalinks will be returned. If false, all permalinks will be applied as Constants 274 * @return array (conditional on $return) List of permalinks 275 */ 276function &serendipity_permalinkPatterns($return = false) { 277 global $serendipity; 278 279 $PAT = array(); 280 281 $PAT['UNSUBSCRIBE'] = '@/' . $serendipity['permalinkUnsubscribePath'].'/(.*)/([0-9]+)@'; 282 $PAT['APPROVE'] = '@/' . $serendipity['permalinkApprovePath'].'/(.*)/(.*)/([0-9]+)@'; 283 $PAT['DELETE'] = '@/' . $serendipity['permalinkDeletePath'].'/(.*)/(.*)/([0-9]+)@'; 284 $PAT['ARCHIVES'] = '@/' . $serendipity['permalinkArchivesPath'].'([/A-Za-z0-9]+)\.html@'; 285 $PAT['FEEDS'] = '@/' . $serendipity['permalinkFeedsPath'].'/@'; 286 $PAT['ADMIN'] = '@/(' . $serendipity['permalinkAdminPath'] . '|entries)(/.+)?$@'; 287 $PAT['ARCHIVE'] = '@/' . $serendipity['permalinkArchivePath'] . '/?@'; 288 $PAT['CATEGORIES'] = '@/' . $serendipity['permalinkCategoriesPath'].'/([0-9;]+)@'; 289 $PAT['PLUGIN'] = '@/(' . $serendipity['permalinkPluginPath'] . '|plugin)/(.*)@'; 290 $PAT['SEARCH'] = '@/' . $serendipity['permalinkSearchPath'] . '/(.*)@'; 291 $PAT['COMMENTS'] = '@/' . $serendipity['permalinkCommentsPath'] . '/(.*)@'; 292 $PAT['PERMALINK'] = '@(' . serendipity_makePermalinkRegex($serendipity['permalinkStructure'], 'entry') . ')/?@i'; 293 $PAT['PERMALINK_CATEGORIES'] = '@' . serendipity_makePermalinkRegex($serendipity['permalinkCategoryStructure'], 'category') . '@i'; 294 $PAT['PERMALINK_FEEDCATEGORIES'] = '@' . serendipity_makePermalinkRegex($serendipity['permalinkFeedCategoryStructure'], 'category') . '@i'; 295 $PAT['PERMALINK_FEEDAUTHORS'] = '@' . serendipity_makePermalinkRegex($serendipity['permalinkFeedAuthorStructure'], 'author') . '@i'; 296 $PAT['PERMALINK_AUTHORS'] = '@' . serendipity_makePermalinkRegex($serendipity['permalinkAuthorStructure'], 'author') . '@i'; 297 298 if ($return) { 299 return $PAT; 300 } else { 301 foreach($PAT AS $constant => $value) { 302 define('PAT_' . $constant, $value); 303 } 304 305 $return = true; 306 return $return; 307 } 308} 309 310/** 311 * Search the reference to a specific permalink 312 * 313 * This query will show the Entry/Category/Author-ID to a permalink, if that permalink 314 * does not contain %id%. 315 * 316 * @access public 317 * @param string The permalink configuration string 318 * @param string The URL to check 319 * @param string A default return value if no permalink is found 320 * @param string The type of a permalink (entry|category|author) 321 * @return string The ID of the permalink type 322 */ 323function serendipity_searchPermalink($struct, $url, $default, $type = 'entry') { 324 global $serendipity; 325 326 if (stristr($struct, '%id%') === FALSE) { 327 $url = preg_replace('@^(' . preg_quote($serendipity['serendipityHTTPPath'], '@') . '(' . preg_quote($serendipity['indexFile'], '@') . ')?\??(url=)?/?)([^&?]+).*@', '\4', $url); 328 // If no entryid is submitted, we rely on a new DB call to fetch the permalink. 329 $pq = "SELECT entry_id, data 330 FROM {$serendipity['dbPrefix']}permalinks 331 WHERE (permalink = '" . serendipity_db_escape_string($url) . "' 332 OR permalink = '" . serendipity_db_escape_string($default) . "') 333 AND type = '" . serendipity_db_escape_string($type) . "' 334 AND entry_id > 0 335 LIMIT 1"; 336// echo $pq; // DEBUG 337// die($pq); // DEBUG 338 $permalink = serendipity_db_query($pq, true, 'both', false, false, false, true); 339 340 if (is_array($permalink)) { 341 return $permalink['entry_id']; 342 } 343 } 344 345 return $default; 346} 347 348/** 349 * Create a permalink for the given input data 350 * 351 * You can pass an entry array, or an author array to this function 352 * and then get a permalink valid for that array 353 * 354 * @access public 355 * @param array The input data used for building the permalink 356 * @param string The type of the permalink (entry|category|author) 357 * @return string The permalink 358 */ 359function serendipity_getPermalink(&$data, $type = 'entry') { 360 switch($type) { 361 case 'entry': 362 return serendipity_archiveURL( 363 $data['id'], 364 $data['title'], 365 '', 366 false, 367 array('timestamp' => $data['timestamp']) 368 ); 369 break; 370 371 case 'category': 372 return serendipity_categoryURL($data, '', false); 373 break; 374 375 case 'author': 376 return serendipity_authorURL($data, '', false); 377 break; 378 } 379 380 return false; 381} 382 383/** 384 * Update a permalink with new data 385 * 386 * @access public 387 * @param array The input data used for building the permalink 388 * @param string The type of the permalink (entry|category|author) 389 * @return string The database result 390 */ 391function serendipity_updatePermalink(&$data, $type = 'entry') { 392 global $serendipity; 393 394 $link = serendipity_getPermalink($data, $type); 395 return(serendipity_db_query(sprintf("UPDATE {$serendipity['dbPrefix']}permalinks 396 SET permalink = '%s' 397 WHERE entry_id = %s 398 AND type = '%s'", 399 400 serendipity_db_escape_string($link), 401 (int)$data['id'], 402 serendipity_db_escape_string($type)))); 403} 404 405/** 406 * Insert a new Permalink into the database for latter retrieval 407 * 408 * This function is basically only used if you have no '%id%' value in your permalink config. 409 * 410 * @access public 411 * @param array The input data used for building the permalink 412 * @param string The type of the permalink (entry|category|author) 413 * @return string The permalink 414 */ 415function serendipity_insertPermalink(&$data, $type = 'entry') { 416 global $serendipity; 417 418 $link = serendipity_getPermalink($data, $type); 419 420 switch($type) { 421 case 'entry': 422 $idfield = 'id'; 423 break; 424 425 case 'author': 426 $idfield = 'authorid'; 427 break; 428 429 case 'category': 430 $idfield = 'categoryid'; 431 break; 432 } 433 434 return(serendipity_db_query(sprintf("INSERT INTO {$serendipity['dbPrefix']}permalinks 435 (permalink, entry_id, type) 436 VALUES ('%s', '%s', '%s')", 437 438 serendipity_db_escape_string($link), 439 (int)$data[$idfield], 440 serendipity_db_escape_string($type)))); 441} 442 443/** 444 * Build all permalinks for all current entries, authors and categories 445 * 446 * @access public 447 * @return null 448 */ 449function serendipity_buildPermalinks() { 450 global $serendipity; 451 452 $entries = serendipity_db_query("SELECT id, title, timestamp FROM {$serendipity['dbPrefix']}entries"); 453 454 if (is_array($entries)) { 455 serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}permalinks WHERE type = 'entry'"); 456 457 foreach($entries AS $entry) { 458 serendipity_insertPermalink($entry, 'entry'); 459 } 460 } 461 462 $authors = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}authors"); 463 464 if (is_array($authors)) { 465 serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}permalinks WHERE type = 'author'"); 466 467 foreach($authors AS $author) { 468 serendipity_insertPermalink($author, 'author'); 469 } 470 } 471 472 $categories = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}category"); 473 474 if (is_array($categories)) { 475 serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}permalinks WHERE type = 'category'"); 476 477 foreach($categories AS $category) { 478 serendipity_insertPermalink($category, 'category'); 479 } 480 } 481} 482 483/** 484 * Uses logic to figure out how the URI should look, based on current rewrite rule 485 * 486 * @access public 487 * @param string The URL part that you want to format to "pretty urls" 488 * @param string The path/URL you want as a prefix for your pretty URL 489 * @param boolean If set to TRUE this will bypass all pretty URLs and format the link so that it works everywhere 490 * @return string The rewritten URL 491 */ 492function serendipity_rewriteURL($path, $key='baseURL', $forceNone = false) { 493 global $serendipity; 494 return $serendipity[$key] . ($serendipity['rewrite'] == 'none' || ($serendipity['rewrite'] != 'none' && $forceNone) ? $serendipity['indexFile'] . '?/' : '') . $path; 495} 496 497/** 498 * Format a permalink according to the configured format 499 * 500 * @access public 501 * @param string The URL format to use 502 * @param array The input data to format a permalink 503 * @param string The type of the permalink (entry|category|author) 504 * @return string The formatted permalink 505 */ 506function serendipity_makePermalink($format, $data, $type = 'entry') { 507 global $serendipity; 508 static $entryKeys = array('%id%', '%lowertitle%', '%title%', '%day%', '%month%', '%year%'); 509 static $authorKeys = array('%id%', '%username%', '%realname%', '%email%'); 510 static $categoryKeys = array('%id%', '%name%', '%parentname%', '%description%'); 511 512 switch($type) { 513 case 'entry': 514 if (!isset($data['entry']['timestamp']) && preg_match('@(%day%|%month%|%year%)@', $format)) { 515 // We need the timestamp to build the URI, but no timestamp has been submitted. Thus we need to fetch the data. 516 $ts = serendipity_db_query("SELECT timestamp FROM {$serendipity['dbPrefix']}entries WHERE id = " . (int)$data['id'], true); 517 if (is_array($ts)) { 518 $data['entry']['timestamp'] = $ts['timestamp']; 519 } else { 520 $data['entry']['timestamp'] = time(); 521 } 522 } 523 524 $ts = serendipity_serverOffsetHour($data['entry']['timestamp']); 525 526 $ftitle = serendipity_makeFilename($data['title']); 527 $fltitle = strtolower($ftitle); 528 529 $replacements = 530 array( 531 (int)$data['id'], 532 $fltitle, 533 $ftitle, 534 date('d', $ts), 535 date('m', $ts), 536 date('Y', $ts) 537 ); 538 return str_replace($entryKeys, $replacements, $format); 539 break; 540 541 case 'author': 542 $replacements = 543 array( 544 (int)$data['authorid'], 545 serendipity_makeFilename($data['username'], true), 546 serendipity_makeFilename($data['realname'], true), 547 serendipity_makeFilename($data['email'], true) 548 ); 549 return str_replace($authorKeys, $replacements, $format); 550 break; 551 552 case 'category': 553 $parent_path = array(); 554 555 // This is expensive. Only lookup if required. 556 if (strstr($format, '%parentname%')) { 557 $parents = serendipity_getCategoryRoot($data['categoryid']); 558 if (is_array($parents)) { 559 foreach($parents AS $parent) { 560 $parent_path[] = serendipity_makeFilename($parent['category_name'], true); 561 } 562 } 563 } 564 565 $replacements = 566 array( 567 (int)$data['categoryid'], 568 serendipity_makeFilename($data['category_name'], true), 569 implode('/', $parent_path), 570 serendipity_makeFilename($data['category_description'], true) 571 ); 572 return str_replace($categoryKeys, $replacements, $format); 573 break; 574 } 575 576 return false; 577} 578 579/** 580 * Convert a permalink configuration into a regular expression for use in rewrite rules 581 * 582 * @access public 583 * @param string The URL format to use 584 * @param string The type of the permalink (entry|category|author) 585 * @return string The regular expression to a permalink URL 586 */ 587function serendipity_makePermalinkRegex($format, $type = 'entry') { 588 static $entryKeys = array('%id%', '%lowertitle%', '%title%', '%day%', '%month%', '%year%'); 589 static $entryRegexValues = array('([0-9]+)', PAT_FILENAME_MATCH, PAT_FILENAME_MATCH, '[0-9]{1,2}', '[0-9]{1,2}', '[0-9]{4}'); 590 591 static $authorKeys = array('%id%', '%username%', '%realname%', '%email%'); 592 static $authorRegexValues = array('([0-9]+)', PAT_FILENAME_MATCH, PAT_FILENAME_MATCH, PAT_FILENAME_MATCH); 593 594 static $categoryKeys = array('%id%', '%name%', '%parentname%', '%description%'); 595 static $categoryRegexValues = array('([0-9;]+)', PAT_FILENAME_MATCH, PAT_DIRNAME_MATCH, PAT_FILENAME_MATCH); 596 597 switch($type) { 598 case 'entry': 599 return str_replace($entryKeys, $entryRegexValues, preg_quote($format)); 600 break; 601 602 case 'author': 603 return str_replace($authorKeys, $authorRegexValues, preg_quote($format)); 604 break; 605 606 case 'category': 607 return str_replace($categoryKeys, $categoryRegexValues, preg_quote($format)); 608 break; 609 } 610} 611 612/** 613 * Create a permalink for an entry permalink 614 * 615 * @access public 616 * @param int The entry ID 617 * @param string The entry title 618 * @param string The base URL/path key 619 * @param boolean Shall the link be rewritten to a pretty URL? 620 * @param array Additional entry data 621 * @return string The permalink 622 */ 623function serendipity_archiveURL($id, $title, $key = 'baseURL', $checkrewrite = true, $entryData = null) { 624 global $serendipity; 625 $path = serendipity_makePermalink($serendipity['permalinkStructure'], array('id'=> $id, 'title' => $title, 'entry' => $entryData)); 626 if ($checkrewrite) { 627 $path = serendipity_rewriteURL($path, $key); 628 } 629 return $path; 630} 631 632/** 633 * Create a permalink for an authors permalink 634 * 635 * @access public 636 * @param array The author data 637 * @param string The base URL/path key 638 * @param boolean Shall the link be rewritten to a pretty URL? 639 * @return string The permalink 640 */ 641function serendipity_authorURL(&$data, $key = 'baseURL', $checkrewrite = true) { 642 global $serendipity; 643 $path = serendipity_makePermalink($serendipity['permalinkAuthorStructure'], $data, 'author'); 644 if ($checkrewrite) { 645 $path = serendipity_rewriteURL($path, $key); 646 } 647 return $path; 648} 649 650/** 651 * Create a permalink for an category permalink 652 * 653 * @access public 654 * @param array The category data 655 * @param string The base URL/path key 656 * @param boolean Shall the link be rewritten to a pretty URL? 657 * @return string The permalink 658 */ 659function serendipity_categoryURL(&$data, $key = 'baseURL', $checkrewrite = true) { 660 global $serendipity; 661 $path = serendipity_makePermalink($serendipity['permalinkCategoryStructure'], $data, 'category'); 662 if ($checkrewrite) { 663 $path = serendipity_rewriteURL($path, $key); 664 } 665 return $path; 666} 667 668/** 669 * Create a permalink for an RSS feed permalink 670 * 671 * @access public 672 * @param array The entry data 673 * @param string The base URL/path key 674 * @param boolean Shall the link be rewritten to a pretty URL? 675 * @return string The permalink 676 */ 677function serendipity_feedCategoryURL(&$data, $key = 'baseURL', $checkrewrite = true) { 678 global $serendipity; 679 $path = serendipity_makePermalink($serendipity['permalinkFeedCategoryStructure'], $data, 'category'); 680 if ($checkrewrite) { 681 $path = serendipity_rewriteURL($path, $key); 682 } 683 return $path; 684} 685 686/** 687 * Create a permalink for an RSS authors' feed permalink 688 * 689 * @access public 690 * @param array The entry data 691 * @param string The base URL/path key 692 * @param boolean Shall the link be rewritten to a pretty URL? 693 * @return string The permalink 694 */ 695function serendipity_feedAuthorURL(&$data, $key = 'baseURL', $checkrewrite = true) { 696 global $serendipity; 697 $path = serendipity_makePermalink($serendipity['permalinkFeedAuthorStructure'], $data, 'author'); 698 if ($checkrewrite) { 699 $path = serendipity_rewriteURL($path, $key); 700 } 701 return $path; 702} 703 704/** 705 * Create a permalink for an archive date 706 * 707 * @access public 708 * @param string The archive's date 709 * @param boolean If true, only summary archive 710 * @param string The base URL/path key 711 * @return string The permalink 712 */ 713function serendipity_archiveDateUrl($range, $summary=false, $key='baseURL') { 714 return serendipity_rewriteURL(PATH_ARCHIVES . '/' . $range . ($summary ? '/summary' : '') . '.html', $key); 715} 716 717/** 718 * Returns the URL to the current page that is being viewed 719 * 720 * @access public 721 * @return string the current URL 722 */ 723function serendipity_currentURL($strict = false) { 724 global $serendipity; 725 726 // All that URL getting humpty-dumpty is necessary to allow a user to change the template in the 727 // articles view. POSTing data to that page only works with mod_rewrite and not the ErrorDocument 728 // redirection, so we need to generate the ErrorDocument-URI here. 729 730 $uri = @parse_url($_SERVER['REQUEST_URI']); 731 $qst = ''; 732 if (!empty($uri['query'])) { 733 $qst = '&' . str_replace('&', '&', $uri['query']); 734 } 735 $uri['path'] = preg_replace('@^' . preg_quote($serendipity['serendipityHTTPPath']) . '@i', ($strict ? '/' : ''), $uri['path']); 736 $uri['path'] = preg_replace('@^(&)?' . preg_quote($serendipity['indexFile']) . '(&)@i', '', $uri['path']); 737 $url = $serendipity['serendipityHTTPPath'] . $serendipity['indexFile'] . '?' . $uri['path'] . $qst; 738 $url = str_replace( 739 array( 740 $serendipity['indexFile'] . '&', 741 '"', 742 "'", 743 '<', 744 '>', 745 '`' 746 ), 747 748 array( 749 '', 750 '', 751 '', 752 '', 753 '' 754 ), 755 756 $url); // Kill possible looped repitions and bad characters which could occur 757 758 if ($strict) { 759 $url = preg_replace('@(//+)@', '/', $url); 760 } 761 762 return $url; 763} 764 765/** 766 * Get the URI Arguments for the current HTTP Request 767 * 768 * @access public 769 * @param string The URI made for this request 770 * @param boolean If enabled, then no Dots are allowed in the URL for permalinks 771 * @return 772 */ 773function serendipity_getUriArguments($uri, $wildcard = false) { 774 global $serendipity; 775 static $indexFile = null; 776 777 if ($indexFile === null) { 778 $_indexFile = explode('.', $serendipity['indexFile']); 779 $indexFile = $_indexFile[0]; 780 } 781 782 /* Explode the path into sections, to later be able to check for arguments and add our own */ 783 preg_match('/^'. preg_quote($serendipity['serendipityHTTPPath'], '/') . '(' . preg_quote($serendipity['indexFile'], '/') . '\?\/)?(' . ($wildcard ? '.+' : '[!;,_a-z0-9\-*\/%\+]+') . ')/i', $uri, $_res); 784 if (strlen($_res[2]) != 0) { 785 $args = explode('/', $_res[2]); 786 if ($args[0] == $indexFile || $args[0] == $serendipity['indexFile']) { 787 unset($args[0]); 788 } 789 $args = array_unique($args); 790 return $args; 791 } else { 792 return array(); 793 } 794} 795 796