'[a-zA-Z]+', // abbreviated month name according to the current locale '%B' => '[a-zA-Z]+', // full month name according to the current locale '%C' => '[0-9]{2}', // century number (the year divided by 100 and truncated to an integer, range 00 to 99) '%h' => '[a-zA-Z]+', // same as %b '%m' => '([0-9]{2})', // month as a decimal number (range 01 to 12) '%d' => '([0-9]{2})', // day as a decimal number (range 01 to 31) '%U' => '[0-9]{1,2}', // week number of the current year as a decimal number, starting with the first Sunday as the first day of the first week '%V' => '[0-9]{2}', // 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. (Use %G or %g for the year component that corresponds to the week number for the specified timestamp.) '%W' => '[0-9]{1,2}', // week number of the current year as a decimal number, starting with the first Monday as the first day of the first week '%y' => '([0-9]{2})', // year as a decimal number without a century (range 00 to 99) '%Y' => '([0-9]{4})' // year as a decimal number including the century ); var $_strftime_verbs = array( // for conversion from selected verbs below to formats above '{year}' => '%Y', '{monthnum}' => '%m', '{day}' => '%d', '{hour}' => '%H', '{minute}' => '%M', '{second}' => '%S' ); var $_permalink_verbs = array( 'year' => '[0-9]{4}', 'monthnum' => '[0-9]{2}', 'day' => '[0-9]{2}', 'hour' => '[0-9]{2}', 'minute' => '[0-9]{2}', 'second' => '[0-9]{2}', 'postname' => '([-a-zA-Z0-9_]+)', 'post_name' => '([-a-zA-Z0-9_]+)', 'post_id' => '([0-9]+)', 'category_id' => '([0-9]+)', 'category_name' => '([-a-zA-Z0-9_]+)', 'category' => '', // unsupported for now, since it requires an additional JOIN in plugins 'author' => '' // unsupported for now, since it requires an additional JOIN in plugins ); function LightPressModRewrite() { $basedir = get_option('lp_opt_basedir'); if (!$basedir) { trigger_error('LightPress active with no options set (null basedir), skipping LightPress .htaccess filter', E_USER_WARNING); } $this->basedir = $basedir; $this->_rootdir = dirname(dirname(dirname($basedir))); $parsed_url = parse_url(get_option('siteurl')); if (!isset($parsed_url['path'])) $parsed_url['path'] = ''; $this->_lp_base = $parsed_url['path']; $parsed_url = parse_url(get_option('home')); if (!isset($parsed_url['path'])) $parsed_url['path'] = ''; $this->_base = $parsed_url['path']; } function WPsubdirs() { if (!is_null($this->_wp_base)) return $this->_wp_base; // find WP subdir(s) $url = get_option('lp_opt_url'); $wp_url = get_option('lp_opt_wp_url'); $pos = strpos($wp_url, $url); if (($url != $wp_url) && ($pos !== false)) { $pos += strlen($url) + 1; $base = substr($wp_url, $pos); if (substr($base, -1) != '/') $base .= '/'; } else { $base = ''; } $this->_wp_base =& $base; return $base; } function buildHtaccess($comment=false) { // TODO: refactor this thing $this->_htaccess = ''; $ht =& $this->_htaccess; if ($comment) { $c = '#'; $ht .= "##\n## LightPress mod_rewrite rules, copy in the LP public folder and remove comments\n##\n"; } else { $c = ''; } $ht .= "${c}\n${c}\n${c}\n${c}RewriteEngine On\n"; $parsed_url = parse_url(get_option('siteurl')); if (!isset($parsed_url['path'])) $parsed_url['path'] = ''; $lp_base = $this->_lp_base . '/wp-content/plugins/lightpress'; $ht .= $c . "RewriteBase {$lp_base}\n"; $ht .= $c . 'RewriteCond %{REQUEST_FILENAME} -f [OR]' . "\n"; $ht .= $c . 'RewriteCond %{REQUEST_FILENAME} -d' . "\n"; $ht .= $this->_getIndexRules($c); $ht .= $this->_getFeedRules($c); $ht .= $this->_getTagRules($c); $ht .= $this->_getCategoryRules($c); $ht .= $this->_getArchiveRules($c); $ht .= $this->_getPostRules($c); $ht .= $this->_getEndRules($c); $ht .= "${c}\n${c}\n"; return $ht; } function buildLightHttpd() { $base = $this->_base; $lp_base = $this->_lp_base; if (substr($lp_base, 0, 1) != '/') $lp_base = '/' . $lp_base; $rules = array(); // index $rules['# index'] = ''; $rules['^' . $base . '/?$'] = 'index.php'; $rules['^' . $base . '/record/([0-9]+)/?$'] = 'index.php?i=$1'; // feeds $rules['# feeds'] = ''; $rules['^' . $base . '/rss2.xml'] = 'feed.php'; $rules['^' . $base . '/atom.xml'] = 'feed.php?feed=atom'; $rules['^' . $base . '/feed$'] = 'feed.php'; $rules['^' . $base . '/feed/?(feed|rss|rss2|rdf|atom)/?$'] = 'feed.php?feed=$1'; $wp_base = $this->WPsubdirs(); $rules['^' . $base . '/' . $wp_base . 'wp-atom.php'] = 'feed.php'; $rules['^' . $base . '/' . $wp_base . 'wp-rss.php'] = 'feed.php'; $rules['^' . $base . '/' . $wp_base . 'wp-rss2.php'] = 'feed.php'; // search $prefix = str_replace('?', '\\?', get_option('lp_opt_search_prefix')); $rules['# search'] = ''; $rules['^' . $base . '/' . $prefix . '/?$'] = 'index.php'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/rss2.xml/?$'] = 'feed.php?q=$1'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/?$'] = 'index.php?q=$1'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/record/?([0-9]*)/?$'] = 'index.php?q=$1&i=$2'; // author $prefix = str_replace('?', '\\?', get_option('lp_opt_author_prefix')); $rules['# author'] = ''; $rules['^' . $base . '/' . $prefix . '/?$'] = 'index.php'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/rss2.xml/?$'] = 'feed.php?u=$1'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/?$'] = 'index.php?u=$1'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/record/?([0-9]*)/?$'] = 'index.php?u=$1&i=$2'; // stats $rules['# stats'] = ''; $rules['^' . $base . '/stats.gif$'] = 'stats.php'; // extended archives and categories $rules['# extended archives and categories'] = ''; $rules['^' . $base . '/archives/?$'] = 'list_archives.php'; $rules['^' . $base . '/categories/?$'] = 'list_categories.php'; // sitemaps $rules['# sitemaps'] = ''; $rules['^' . $base . '/sitemap.xml'] = 'sitemap.php?sitemap=1'; $rules['^' . $base . '/sitemap_index.xml'] = 'sitemap.php'; // tags $prefix = str_replace('?', '\\?', get_option('lp_opt_tag_prefix')); $rules['# tags'] = ''; $rules['^' . $base . '/' . $prefix . '/(.+)/rss2.xml$'] = 'feed.php?tag=$1'; $rules['^' . $base . '/' . $prefix . '/(.+)/atom.xml$'] = 'feed.php?tag=$1&feed=atom'; $rules['^' . $base . '/' . $prefix . '/(.+)/record/?([0-9]*)/?$'] = 'index.php?tag=$1&i=$2'; $rules['^' . $base . '/' . $prefix . '/(.+)/?$'] = 'index.php?tag=$1'; // categories $prefix = str_replace('?', '\\?', get_option('lp_opt_category_prefix')); $rules['# categories'] = ''; $rules['^' . $base . '/' . $prefix . '/([^/]+)/?$'] = 'index.php?c=$1'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/record/?([0-9]*)/?$'] = 'index.php?c=$1&i=$2'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/rss2.xml$'] = 'feed.php?c=$1'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/atom.xml$'] = 'feed.php?c=$1&feed=atom'; $rules['^' . $base . '/' . $prefix . '/([^/]+)/sitemap.xml$'] = 'sitemap.php?c=$1&sitemap=1'; // archives $prefix =& $this->getArchivePrefix(); $rules['# archives'] = ''; $rules['^' . $base . '/' . $prefix . '/?$'] = 'index.php?y=$1&m=$2&d=$3'; $rules['^' . $base . '/' . $prefix . '/record/?([0-9]*)/?$'] = 'index.php?y=$1&m=$2&d=$3&i=$4'; $rules['^' . $base . '/' . $prefix . '/sitemap.xml$'] = 'sitemap.php?y=$1&m=$2&d=$3&sitemap=1'; // posts list($prefix, $get_vars) = $this->getPostPrefix(); $rules['# posts'] = ''; // posts - base rule $rules['^' . $base . '/' . $prefix . '/?$'] = 'index.php?' . implode('&', $get_vars); // posts - comment submission $rules['^' . $base . '/' . $prefix . '/?\?(.*)$'] = 'index.php?' . implode('&', $get_vars) . '&$' . (count($get_vars) + 1); // posts - anchor $rules['^' . $base . '/' . $prefix . '/?(#.*)$'] = 'index.php?' . implode('&', $get_vars) . '$' . (count($get_vars) + 1); $rules['^' . $base . '/trackback/([^/]+)/?$'] = 'index.php?p=$1&action=trackback'; // short-circuit /wp-admin $rules['# short-circuit wp-admin'] = ''; $rules['^' . $lp_base . '/wp-admin/?$'] = 'wp-admin/'; // pages $rules['# pages'] = ''; $rules['# to exclude URLs from the eat-all page rules, add to the negative lookbehind assertions below'] = ''; $rules['# eg to exclude /styles/any_file use (?$v) { if ($k[0] == '#') $lt .= "\t$k\n"; else $lt .= sprintf("\t%s => \"{$lp_base}%s\",\n", str_pad('"' . $k . '"', 60), $v); } if ($catchall) $lt .= "\t" . str_pad('"^' . $base . '(/.*)$"', 60) . '=> "$1"' . "\n"; $lt .= ")"; $this->_lighty =& $lt; return $lt; } function _getIndexRules($c) { $ht = "${c}\n${c}# index page\n"; $ht .= $c . 'RewriteRule ^/?$ index.php [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^record/([0-9]+)/?$ index.php?i=$1 [QSA,L]' . "\n"; $prefix = str_replace('?', '\\?', get_option('lp_opt_search_prefix')); $ht .= $c . 'RewriteRule ^' . $prefix . '/?$ index.php [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml/?$ feed.php?q=$1 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?q=$1 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?q=$1&i=$2 [QSA,L]' . "\n"; $prefix = str_replace('?', '\\?', get_option('lp_opt_author_prefix')); $ht .= $c . 'RewriteRule ^' . $prefix . '/?$ index.php [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml/?$ feed.php?u=$1 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?u=$1 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?u=$1&i=$2 [QSA,L]' . "\n"; $ht .= "$c\n"; $ht .= "$c# stats\n"; $ht .= $c . 'RewriteRule ^stats.gif$ stats.php [QSA,L]' . "\n"; $ht .= "$c# archives list\n"; $ht .= $c . 'RewriteRule ^archives/?$ list_archives.php [QSA,L]' . "\n"; $ht .= "$c# categories list\n"; $ht .= $c . 'RewriteRule ^categories/?$ list_categories.php [QSA,L]' . "\n"; return $ht; } function _getFeedRules($c) { $ht = "${c}\n${c}#feeds\n"; # feeds $ht .= $c . 'RewriteRule ^rss2.xml feed.php [L]' . "\n"; $ht .= $c . 'RewriteRule ^atom.xml feed.php?feed=atom [L]' . "\n"; $ht .= $c . 'RewriteRule ^sitemap.xml sitemap.php?sitemap=1 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^sitemap_index.xml sitemap.php [L]' . "\n"; $ht .= "${c}\n${c}# feeds (WP compatibility)\n"; $base = $this->WPsubdirs(); $ht .= $c . 'RewriteRule ^' . $base . 'wp-atom.php feed.php [L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $base . 'wp-rss.php feed.php [L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $base . 'wp-rss2.php feed.php [L]' . "\n"; $ht .= $c . 'RewriteRule ^feed$ feed.php [L]' . "\n"; $ht .= $c . 'RewriteRule ^feed/?(feed|rss|rss2|rdf|atom)/?$ feed.php?feed=$1 [QSA,L]' . "\n"; return $ht; } function _getTagRules($c) { $prefix = str_replace('?', '\\?', get_option('lp_opt_tag_prefix')); $ht = "${c}\n${c}# tag searches\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/(.+)/rss2.xml$ feed.php?tag=$1 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/(.+)/atom.xml$ feed.php?tag=$1&feed=atom [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/(.+)/record/?([0-9]*)/?$ index.php?tag=$1&i=$2 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/(.+)/?$ index.php?tag=$1 [QSA,L]' . "\n"; return $ht; } function _getCategoryRules($c) { $prefix = str_replace('?', '\\?', get_option('lp_opt_category_prefix')); $ht = "${c}\n${c}# categories\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?c=$1 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?c=$1&i=$2 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml$ feed.php?c=$1 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/atom.xml$ feed.php?c=$1&feed=atom [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)/sitemap.xml$ sitemap.php?c=$1&sitemap=1 [QSA,L]' . "\n"; return $ht; } function &getArchivePrefix() { if (!is_null($this->_archive_prefix)) return $this->_archive_prefix; $prefix = str_replace('?', '\\?', get_option('lp_opt_archives_prefix')); $prefix = str_replace( array_keys($this->_strftime_verbs), array_values($this->_strftime_verbs), $prefix); $prefix = str_replace( array_keys($this->_strftime_formats), array_values($this->_strftime_formats), $prefix); $this->_archive_prefix =& $prefix; return $prefix; } function _getArchiveRules($c) { // we assume %Y and %m never swap position // TODO: find a way to interpret a few more strftime codes // and detect the position of %Y %m to correctly place // y=$n m=$n $prefix =& $this->getArchivePrefix(); $ht = "${c}\n${c}# archives\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/?$ index.php?y=$1&m=$2 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/record/?([0-9]*)/?$ index.php?y=$1&m=$2&i=$3 [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/sitemap.xml$ sitemap.php?y=$1&m=$2&sitemap=1 [QSA,L]' . "\n"; return $ht; } function getPostPrefix() { if (!is_null($this->_post_prefix)) return array($this->_post_prefix, $this->_post_vars); $prefix = str_replace('?', '\\?', get_option('lp_opt_post_prefix')); $get_vars = array(); $m = array(); preg_match_all('/{([^}]+)}/', $prefix, $m, PREG_SET_ORDER); foreach ($m as $match) { list($curly_token, $token) = $match; if (!isset($this->_permalink_verbs[$token])) continue; $prefix = str_replace($curly_token, $this->_permalink_verbs[$token], $prefix); switch ($token) { case 'postname': case 'post_name': $get_vars[] = 'p=$' . (count($get_vars) + 1); break; case 'post_id': $get_vars[] = 'pi=$' . (count($get_vars) + 1); break; } } $this->_post_prefix =& $prefix; $this->_post_vars =& $get_vars; return array($prefix, $get_vars); } function _getPostRules($c) { list($prefix, $get_vars) = $this->getPostPrefix(); $ht = "${c}\n${c}# posts\n"; $ht .= $c . 'RewriteRule ^' . $prefix . '/?$ index.php?' . implode('&', $get_vars) . ' [QSA,L]' . "\n"; $ht .= $c . 'RewriteRule ^trackback/([^/]+)/?$ index.php?p=$1&action=trackback [QSA,L]' . "\n"; $prefix = str_replace('?', '\\?', get_option('lp_opt_pages_prefix')); $suffix = get_option('lp_opt_pages_suffix'); if ($prefix) $ht .= $c . 'RewriteRule ^' . $prefix . '/([^/]+)' . $suffix . '/?$ index.php?s=$1 [QSA,L]' . "\n"; return $ht; } function _getEndRules($c) { $suffix = get_option('lp_opt_pages_suffix'); if (!$suffix) $suffix = ''; $pre = $c . 'RewriteCond %{REQUEST_FILENAME} !-f' . "\n" . $c . 'RewriteCond %{REQUEST_FILENAME} !-d' . "\n"; $ht = ''; # end rules $ht .= "\n" . $c . '#catchall rules for parent (1st level) category/pages' . "\n"; $ht .= $pre . $c . 'RewriteRule ^([^/]+)' . $suffix . '/?$ index.php?y1=$1 [QSA,L]' . "\n"; $ht .= $pre . $c . 'RewriteRule ^([^/]+)' . $suffix . '/record/?([0-9]*)/?$/?$ index.php?y1=$1&i=$2 [QSA,L]' . "\n"; $ht .= "\n" . $c . '#catchall rules for subparent/child (2nd level) category/pages' . "\n"; $ht .= $pre . $c . 'RewriteRule ^([^/]+)/([^/]+)' . $suffix . '/?$ index.php?y1=$1&y2=$2 [QSA,L]' . "\n"; $ht .= $pre . $c . 'RewriteRule ^([^/]+)/([^/]+)' . $suffix . '/record/?([0-9]*)/?$/?$ index.php?y1=$1&y2=$2&i=$3 [QSA,L]' . "\n"; $ht .= "\n" . $c . '#catchall rules for child (3rd level) category/pages' . "\n"; $ht .= $pre . $c . 'RewriteRule ^([^/]+)/([^/]+)/([^/]+)' . $suffix . '/?$ index.php?y1=$1&y2=$2&y3=$3 [QSA,L]' . "\n"; $ht .= $pre . $c . 'RewriteRule ^([^/]+)/([^/]+)/([^/]+)' . $suffix . '/record/?([0-9]*)/?$/?$ index.php?y1=$1&y2=$2&y3=$3&i=$4 [QSA,L]' . "\n"; return $ht; } function raiseError($message, $method, $line, $type=E_USER_WARNING) { trigger_error( sprintf("%s.%s() line %d: %s", get_class($this), $method, $line, $message), $type); } } ?>