'[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_]+', '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() { // TODO: refactor this thing $this->_htaccess = ''; $ht =& $this->_htaccess; $ht .= "\nRewriteEngine 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 .= "RewriteBase {$lp_base}\n"; $ht .= 'RewriteCond %{REQUEST_FILENAME} -f [OR]' . "\n"; $ht .= 'RewriteCond %{REQUEST_FILENAME} -d' . "\n"; $ht .= $this->_getIndexRules(); $ht .= $this->_getFeedRules(); $ht .= $this->_getTagRules(); $ht .= $this->_getCategoryRules(); $ht .= $this->_getArchiveRules(); $ht .= $this->_getPostRules(); $ht .= $this->_getEndRules(); $ht .= "\n\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/?(.*)$'] = $base . '/wp-admin/$1'; // 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 if (strpos($v, 'wp-admin') !== false) $lt .= sprintf("\t%s => \"%s\",\n", str_pad('"' . $k . '"', 60), $v); else $lt .= sprintf("\t%s => \"{$lp_base}%s\",\n", str_pad('"' . $k . '"', 60), $v); } $lt .= ")"; $this->_lighty =& $lt; return $lt; } function _getIndexRules() { $ht = "\n# index page\n"; $ht .= 'RewriteRule ^/?$ index.php [QSA,L]' . "\n"; $ht .= 'RewriteRule ^record/([0-9]+)/?$ index.php?i=$1 [QSA,L]' . "\n"; $prefix = str_replace('?', '\\?', get_option('lp_opt_search_prefix')); $ht .= 'RewriteRule ^' . $prefix . '/?$ index.php [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml/?$ feed.php?q=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?q=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?q=$1&i=$2 [QSA,L]' . "\n"; $prefix = str_replace('?', '\\?', get_option('lp_opt_author_prefix')); $ht .= 'RewriteRule ^' . $prefix . '/?$ index.php [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml/?$ feed.php?u=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?u=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?u=$1&i=$2 [QSA,L]' . "\n"; $ht .= "\n"; $ht .= "# stats\n"; $ht .= 'RewriteRule ^stats.gif$ stats.php [QSA,L]' . "\n"; $ht .= "# archives list\n"; $ht .= 'RewriteRule ^archives/?$ list_archives.php [QSA,L]' . "\n"; $ht .= "# categories list\n"; $ht .= 'RewriteRule ^categories/?$ list_categories.php [QSA,L]' . "\n"; return $ht; } function _getFeedRules() { $ht = "\n#feeds\n"; # feeds $ht .= 'RewriteRule ^rss2.xml feed.php [L]' . "\n"; $ht .= 'RewriteRule ^atom.xml feed.php?feed=atom [L]' . "\n"; $ht .= 'RewriteRule ^sitemap.xml sitemap.php?sitemap=1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^sitemap_index.xml sitemap.php [L]' . "\n"; $ht .= "# feeds (WP compatibility)\n"; $base = $this->WPsubdirs(); $ht .= 'RewriteRule ^' . $base . 'wp-atom.php feed.php [L]' . "\n"; $ht .= 'RewriteRule ^' . $base . 'wp-rss.php feed.php [L]' . "\n"; $ht .= 'RewriteRule ^' . $base . 'wp-rss2.php feed.php [L]' . "\n"; $ht .= 'RewriteRule ^feed$ feed.php [L]' . "\n"; $ht .= 'RewriteRule ^feed/?(feed|rss|rss2|rdf|atom)/?$ feed.php?feed=$1 [QSA,L]' . "\n"; return $ht; } function _getTagRules() { $prefix = str_replace('?', '\\?', get_option('lp_opt_tag_prefix')); $ht = "\n# tag searches\n"; $ht .= 'RewriteRule ^' . $prefix . '/(.+)/rss2.xml$ feed.php?tag=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/(.+)/atom.xml$ feed.php?tag=$1&feed=atom [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/(.+)/record/?([0-9]*)/?$ index.php?tag=$1&i=$2 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/(.+)/?$ index.php?tag=$1 [QSA,L]' . "\n"; return $ht; } function _getCategoryRules() { $prefix = str_replace('?', '\\?', get_option('lp_opt_category_prefix')); $ht = "\n# categories\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/?$ index.php?c=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/record/?([0-9]*)/?$ index.php?c=$1&i=$2 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/rss2.xml$ feed.php?c=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)/atom.xml$ feed.php?c=$1&feed=atom [QSA,L]' . "\n"; $ht .= '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() { // 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 = "\n# archives\n"; $ht .= 'RewriteRule ^' . $prefix . '/?$ index.php?y=$1&m=$2 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/record/?([0-9]*)/?$ index.php?y=$1&m=$2&i=$3 [QSA,L]' . "\n"; $ht .= '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() { list($prefix, $get_vars) = $this->getPostPrefix(); $ht = "\n# posts\n"; $ht .= 'RewriteRule ^' . $prefix . '/?$ index.php?' . implode('&', $get_vars) . ' [QSA,L]' . "\n"; $ht .= 'RewriteRule ^trackback/([^/]+)/?$ index.php?p=$1&action=trackback [QSA,L]' . "\n"; // paged comments $comments_prefix = str_replace('?', '\\?', get_option('lp_opt_comments_prefix')); if (!$comments_prefix) $comments_prefix = 'comments'; $get_vars[] = 'i=$' . (count($get_vars) + 1); $ht .= 'RewriteRule ^' . $prefix . '/' . $comments_prefix . '/([0-9]+)/?$ index.php?' . implode('&', $get_vars) . ' [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $prefix . '/' . $comments_prefix . '/(last)/?$ index.php?' . implode('&', $get_vars) . ' [QSA,L]' . "\n"; // pages $prefix = str_replace('?', '\\?', get_option('lp_opt_pages_prefix')); $suffix = get_option('lp_opt_pages_suffix'); if ($prefix) $ht .= 'RewriteRule ^' . $prefix . '/([^/]+)' . $suffix . '/?$ index.php?s=$1 [QSA,L]' . "\n"; return $ht; } function _getEndRules() { $suffix = get_option('lp_opt_pages_suffix'); if (!$suffix) $suffix = ''; $pre = 'RewriteCond %{REQUEST_FILENAME} !-f' . "\n" . 'RewriteCond %{REQUEST_FILENAME} !-d' . "\n"; $ht = ''; # page rules $ht .= "\n" . '# page rules' . "\n"; global $wpdb; $pages = $wpdb->get_results("select distinct post_name from {$wpdb->prefix}posts where post_status='static' and post_parent=0", ARRAY_N); if (is_array($pages)) { $parent_pages = $wpdb->get_results("select distinct p2.post_name from {$wpdb->prefix}posts p inner join {$wpdb->prefix}posts p2 on p2.id=p.post_parent where p.post_status='static' and p2.post_parent=0", ARRAY_N); if (is_array($parent_pages)) { // ugly, but I'm tired... foreach ($parent_pages as $page) $parent_pages[$page[0]] = null; } else { $parent_pages = array(); } foreach ($pages as $page) { $page_name = $page[0]; $ht .= 'RewriteRule ^' . $page_name . '' . $suffix . '/?$ index.php?s=' . $page_name . ' [QSA,L]' . "\n"; if (isset($parent_pages[$page_name])) { $ht .= 'RewriteRule ^' . $page_name . '/([^/]+)' . $suffix . '/?$ index.php?y1=' . $page_name . '&y2=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $page_name . '/([^/]+)/([^/]+)' . $suffix . '/?$ index.php?y1=' . $page_name . '&y2=$1&y3=$2 [QSA,L]' . "\n"; } } } # two-level category rules $ht .= "\n" . '# two-level category rules' . "\n"; $categories = $wpdb->get_results("select distinct c2.category_nicename from {$wpdb->prefix}categories c inner join {$wpdb->prefix}categories c2 on c2.cat_id=c.category_parent where c2.category_parent=0", ARRAY_N); if (is_array($categories)) { foreach ($categories as $cat) { $cat_name = str_replace(' ', '\\s', $cat[0]); $ht .= 'RewriteRule ^' . $cat_name . '/?$ index.php?y1=' . $cat_name . ' [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $cat_name . '/record/?([0-9]*)/?$ index.php?y1=' . $cat_name . '&i=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $cat_name . '/([^/]+)/?$ index.php?y1=' . $cat_name . '&y2=$1 [QSA,L]' . "\n"; $ht .= 'RewriteRule ^' . $cat_name . '/([^/]+)/record/?([0-9]*)/?$ index.php?y1=' . $cat_name . '&y2=$1&i=$2 [QSA,L]' . "\n"; #$ht .= 'RewriteRule ^' . $cat_name . '/([^/]+)/([^/]+)/?$ index.php?y1=' . $cat_name . '&y2=$1&y3=$2 [QSA,L]' . "\n"; #$ht .= 'RewriteRule ^' . $cat_name . '/([^/]+)/([^/]+)/record/?([0-9]*)/?$ index.php?y1=' . $cat_name . '&y2=$1&y3=$2&i=$3 [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); } } ?>