/********************************************************************************** * nWordPress is an automated migration of WordPress 2.5.1 performed by Numiton. * * copyright : (C) 2008 Numiton - www.numiton.com * email : numiton@users.sourceforge.net * * $Id: WP_Rewrite.java,v 1.3 2008/10/10 16:48:03 numiton Exp $ * **********************************************************************************/ /********************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * **********************************************************************************/ /*************************************************************************** * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * ***************************************************************************/ package org.numiton.nwp.wp_includes; import static com.numiton.PhpCommonConstants.BOOLEAN_FALSE; import static com.numiton.VarHandling.*; import static com.numiton.generic.PhpWeb.getIncluded; import java.io.Serializable; import java.util.Map; import java.util.Set; import org.apache.log4j.Logger; import org.numiton.nwp.GlobalConsts; import org.numiton.nwp.GlobalVars; import org.numiton.nwp.wp_admin.includes.MiscPage; import com.numiton.URL; import com.numiton.array.Array; import com.numiton.array.ArrayEntry; import com.numiton.generic.*; import com.numiton.ntile.til.libraries.php.quercus.QRegExPerl; import com.numiton.string.Strings; /* WP_Rewrite class *******************************************************************************/ public class WP_Rewrite implements ContextCarrierInterface, Serializable, Cloneable { protected static final Logger LOG = Logger.getLogger(WP_Rewrite.class.getName()); public GlobalConsts gConsts; public GlobalVars gVars; public String permalink_structure; public boolean use_trailing_slashes; public Object category_base; public Object tag_base; public String category_structure; public String tag_structure; public String author_base = "author"; public String author_structure; public String date_structure; public String page_structure; public String search_base = "search"; public String search_structure; public String comments_base = "comments"; public String feed_base = "feed"; public Object comments_feed_structure; public String feed_structure; public String front; public String root = ""; public String index = "index.php"; public String matches = ""; public Array<Object> rules = new Array<Object>(); public Array<Object> extra_rules = new Array<Object>(); //those not generated by the class, see add_rewrite_rule() public Array<Object> extra_rules_top = new Array<Object>(); //those not generated by the class, see add_rewrite_rule() public Array<Object> non_wp_rules = new Array<Object>(); //rules that don't redirect to WP's index.php public Array<Object> extra_permastructs = new Array<Object>(); public Array<Object> endpoints = new Array<Object>(); public boolean use_verbose_rules = false; public boolean use_verbose_page_rules = true; public Array<Object> rewritecode = new Array<Object>(new ArrayEntry<Object>("%year%"), new ArrayEntry<Object>("%monthnum%"), new ArrayEntry<Object>("%day%"), new ArrayEntry<Object>("%hour%"), new ArrayEntry<Object>("%minute%"), new ArrayEntry<Object>("%second%"), new ArrayEntry<Object>("%postname%"), new ArrayEntry<Object>("%post_id%"), new ArrayEntry<Object>("%category%"), new ArrayEntry<Object>("%tag%"), new ArrayEntry<Object>("%author%"), new ArrayEntry<Object>("%pagename%"), new ArrayEntry<Object>("%search%")); public Array<Object> rewritereplace = new Array<Object>(new ArrayEntry<Object>("([0-9]{4})"), new ArrayEntry<Object>("([0-9]{1,2})"), new ArrayEntry<Object>("([0-9]{1,2})"), new ArrayEntry<Object>("([0-9]{1,2})"), new ArrayEntry<Object>("([0-9]{1,2})"), new ArrayEntry<Object>("([0-9]{1,2})"), new ArrayEntry<Object>("([^/]+)"), new ArrayEntry<Object>("([0-9]+)"), new ArrayEntry<Object>("(.+?)"), new ArrayEntry<Object>("(.+?)"), new ArrayEntry<Object>("([^/]+)"), new ArrayEntry<Object>("([^/]+?)"), new ArrayEntry<Object>("(.+)")); public Array<Object> queryreplace = new Array<Object>(new ArrayEntry<Object>("year="), new ArrayEntry<Object>("monthnum="), new ArrayEntry<Object>("day="), new ArrayEntry<Object>("hour="), new ArrayEntry<Object>("minute="), new ArrayEntry<Object>("second="), new ArrayEntry<Object>("name="), new ArrayEntry<Object>("p="), new ArrayEntry<Object>("category_name="), new ArrayEntry<Object>("tag="), new ArrayEntry<Object>("author_name="), new ArrayEntry<Object>("pagename="), new ArrayEntry<Object>("s=")); public Array<Object> feeds = new Array<Object>(new ArrayEntry<Object>("feed"), new ArrayEntry<Object>("rdf"), new ArrayEntry<Object>("rss"), new ArrayEntry<Object>("rss2"), new ArrayEntry<Object>("atom")); public String comment_feed_structure; public WP_Rewrite(GlobalVars javaGlobalVariables, GlobalConsts javaGlobalConstants) { setContext(javaGlobalVariables, javaGlobalConstants); this.init(); } public boolean using_permalinks() { if (empty(this.permalink_structure)) { return false; } else { return true; } } public boolean using_index_permalinks() { if (empty(this.permalink_structure)) { return false; } // If the index is not in the permalink, we're using mod_rewrite. if (QRegExPerl.preg_match("#^/*" + this.index + "#", this.permalink_structure)) { return true; } return false; } public boolean using_mod_rewrite_permalinks() { if (this.using_permalinks() && !this.using_index_permalinks()) { return true; } else { return false; } } public String preg_index(int number) { String match_prefix = null; String match_suffix = null; match_prefix = "$"; match_suffix = ""; if (!empty(this.matches)) { match_prefix = "$" + this.matches + "["; match_suffix = "]"; } return match_prefix + strval(number) + match_suffix; } public Array<Object> page_uri_index() { Array<Object> posts = new Array<Object>(); Array<Object> page_uris = new Array<Object>(); Array<Object> page_attachment_uris = new Array<Object>(); String uri = null; Object id = null; Array<Object> attachments = new Array<Object>(); String attach_uri = null; StdClass attachment = null; Object post = null; //get pages in order of hierarchy, i.e. children after parents posts = getIncluded(PostPage.class, gVars, gConsts).get_page_hierarchy(gVars.wpdb.get_results("SELECT ID, post_name, post_parent FROM " + gVars.wpdb.posts + " WHERE post_type = \'page\'"), 0); //now reverse it, because we need parents after children for rewrite rules to work properly posts = Array.array_reverse(posts, true); page_uris = new Array<Object>(); page_attachment_uris = new Array<Object>(); if (!booleanval(posts)) { return new Array<Object>(new ArrayEntry<Object>(new Array<Object>()), new ArrayEntry<Object>(new Array<Object>())); } for (Map.Entry javaEntry575 : posts.entrySet()) { id = javaEntry575.getKey(); post = javaEntry575.getValue(); // URL => page name uri = getIncluded(PostPage.class, gVars, gConsts).get_page_uri(intval(id)); attachments = gVars.wpdb.get_results(gVars.wpdb.prepare("SELECT ID, post_name, post_parent FROM " + gVars.wpdb.posts + " WHERE post_type = \'attachment\' AND post_parent = %d", id)); if (booleanval(attachments)) { for (Map.Entry javaEntry576 : attachments.entrySet()) { attachment = (StdClass) javaEntry576.getValue(); attach_uri = getIncluded(PostPage.class, gVars, gConsts).get_page_uri(intval(StdClass.getValue(attachment, "ID"))); page_attachment_uris.putValue(attach_uri, StdClass.getValue(attachment, "ID")); } } page_uris.putValue(uri, id); } return new Array<Object>(new ArrayEntry<Object>(page_uris), new ArrayEntry<Object>(page_attachment_uris)); } public Array<Object> page_rewrite_rules() { Array<Object> rewrite_rules = new Array<Object>(); String page_structure = null; Array<Object> page_uris = new Array<Object>(); Object uris = null; /* Do not change type */ Object attachment_uris = null; /* Do not change type */ Object uri = null; Object pagename = null; rewrite_rules = new Array<Object>(); page_structure = this.get_page_permastruct(); if (!this.use_verbose_page_rules) { this.add_rewrite_tag("%pagename%", "(.+?)", "pagename="); rewrite_rules = Array.array_merge(rewrite_rules, this.generate_rewrite_rules(page_structure, gConsts.getEP_PAGES())); return rewrite_rules; } page_uris = this.page_uri_index(); uris = page_uris.getValue(0); attachment_uris = page_uris.getValue(1); if (is_array(attachment_uris)) { for (Map.Entry javaEntry577 : ((Array<?>) attachment_uris).entrySet()) { uri = javaEntry577.getKey(); pagename = javaEntry577.getValue(); this.add_rewrite_tag("%pagename%", "(" + uri + ")", "attachment="); rewrite_rules = Array.array_merge(rewrite_rules, this.generate_rewrite_rules(page_structure, gConsts.getEP_PAGES())); } } if (is_array(uris)) { for (Map.Entry javaEntry578 : ((Array<?>) uris).entrySet()) { uri = javaEntry578.getKey(); pagename = javaEntry578.getValue(); this.add_rewrite_tag("%pagename%", "(" + uri + ")", "pagename="); rewrite_rules = Array.array_merge(rewrite_rules, this.generate_rewrite_rules(page_structure, gConsts.getEP_PAGES())); } } return rewrite_rules; } public String get_date_permastruct() { Array<Object> endians = new Array<Object>(); String date_endian = null; String endian = null; String front = null; Array tokens = new Array(); int tok_index = 0; Object token = null; if (isset(this.date_structure)) { return this.date_structure; } if (empty(this.permalink_structure)) { this.date_structure = ""; return strval(false); } // The date permalink must have year, month, and day separated by slashes. endians = new Array<Object>(new ArrayEntry<Object>("%year%/%monthnum%/%day%"), new ArrayEntry<Object>("%day%/%monthnum%/%year%"), new ArrayEntry<Object>("%monthnum%/%day%/%year%")); this.date_structure = ""; date_endian = ""; for (Map.Entry javaEntry579 : endians.entrySet()) { endian = strval(javaEntry579.getValue()); if (!strictEqual(BOOLEAN_FALSE, Strings.strpos(this.permalink_structure, endian))) { date_endian = endian; break; } } if (empty(date_endian)) { date_endian = "%year%/%monthnum%/%day%"; } // Do not allow the date tags and %post_id% to overlap in the permalink // structure. If they do, move the date tags to $front/date/. front = this.front; QRegExPerl.preg_match_all("/%.+?%/", this.permalink_structure, tokens); tok_index = 1; for (Map.Entry javaEntry580 : (Set<Map.Entry>) tokens.getArrayValue(0).entrySet()) { token = javaEntry580.getValue(); if (equal(token, "%post_id%") && (tok_index <= 3)) { front = front + "date/"; break; } tok_index++; } this.date_structure = front + date_endian; return this.date_structure; } public String get_year_permastruct() { String structure = null; structure = this.get_date_permastruct(); /*this.permalink_structure*/ if (empty(structure)) { return strval(false); } structure = Strings.str_replace("%monthnum%", "", structure); structure = Strings.str_replace("%day%", "", structure); structure = QRegExPerl.preg_replace("#/+#", "/", structure); return structure; } public String get_month_permastruct() { String structure = null; structure = this.get_date_permastruct(); /*this.permalink_structure*/ if (empty(structure)) { return strval(false); } structure = Strings.str_replace("%day%", "", structure); structure = QRegExPerl.preg_replace("#/+#", "/", structure); return structure; } public String get_day_permastruct() { return this.get_date_permastruct(); } /*this.permalink_structure*/ public String get_category_permastruct() { if (isset(this.category_structure)) { return this.category_structure; } if (empty(this.permalink_structure)) { this.category_structure = ""; return ""; } if (empty(this.category_base)) { this.category_structure = this.front + "category/"; } else { this.category_structure = strval(this.category_base) + "/"; } this.category_structure = this.category_structure + "%category%"; return this.category_structure; } public String get_tag_permastruct() { if (isset(this.tag_structure)) { return this.tag_structure; } if (empty(this.permalink_structure)) { this.tag_structure = ""; return ""; } if (empty(this.tag_base)) { this.tag_structure = this.front + "tag/"; } else { this.tag_structure = strval(this.tag_base) + "/"; } this.tag_structure = this.tag_structure + "%tag%"; return this.tag_structure; } public String get_extra_permastruct(String name) { if (isset(this.extra_permastructs.getValue(name))) { return strval(this.extra_permastructs.getValue(name)); } return strval(false); } public String get_author_permastruct() { if (isset(this.author_structure)) { return this.author_structure; } if (empty(this.permalink_structure)) { this.author_structure = ""; return strval(false); } this.author_structure = this.front + this.author_base + "/%author%"; return this.author_structure; } public String get_search_permastruct() { if (isset(this.search_structure)) { return this.search_structure; } if (empty(this.permalink_structure)) { this.search_structure = ""; return strval(false); } this.search_structure = this.root + this.search_base + "/%search%"; return this.search_structure; } public String get_page_permastruct() { if (isset(this.page_structure)) { return this.page_structure; } if (empty(this.permalink_structure)) { this.page_structure = ""; return strval(false); } this.page_structure = this.root + "%pagename%"; return this.page_structure; } public String get_feed_permastruct() { if (isset(this.feed_structure)) { return this.feed_structure; } if (empty(this.permalink_structure)) { this.feed_structure = ""; return strval(false); } this.feed_structure = this.root + this.feed_base + "/%feed%"; return this.feed_structure; } public String get_comment_feed_permastruct() { if (isset(this.comment_feed_structure)) { return this.comment_feed_structure; } if (empty(this.permalink_structure)) { this.comment_feed_structure = ""; return strval(false); } this.comment_feed_structure = this.root + this.comments_base + "/" + this.feed_base + "/%feed%"; return this.comment_feed_structure; } public void add_rewrite_tag(String tag, String pattern, String query) { Object position = null; // If the tag already exists, replace the existing pattern and query for // that tag, otherwise add the new tag, pattern, and query to the end of // the arrays. position = Array.array_search(tag, this.rewritecode); if (!strictEqual(false, position) && !strictEqual(null, position)) { this.rewritereplace.putValue(position, pattern); this.queryreplace.putValue(position, query); } else { this.rewritecode.putValue(tag); this.rewritereplace.putValue(pattern); this.queryreplace.putValue(query); } } public Array<Object> generate_rewrite_rules(String permalink_structure, int ep_mask) { return generate_rewrite_rules(permalink_structure, ep_mask, true, true, false, true, true); } public Array<Object> generate_rewrite_rules(String permalink_structure, int ep_mask, boolean paged) { return generate_rewrite_rules(permalink_structure, ep_mask, paged, true, false, true, true); } public Array<Object> generate_rewrite_rules(String permalink_structure, int ep_mask, boolean paged, boolean feed) { return generate_rewrite_rules(permalink_structure, ep_mask, paged, feed, false, true, true); } public Array<Object> generate_rewrite_rules(String permalink_structure, int ep_mask, boolean paged, boolean feed, boolean forcomments) { return generate_rewrite_rules(permalink_structure, ep_mask, paged, feed, forcomments, true, true); } public Array<Object> generate_rewrite_rules(String permalink_structure, int ep_mask, boolean paged, boolean feed, boolean forcomments, boolean walk_dirs) { return generate_rewrite_rules(permalink_structure, ep_mask, paged, feed, forcomments, walk_dirs, true); } /** * the main WP_Rewrite function. generate the rules from permalink structure */ public Array<Object> generate_rewrite_rules(String permalink_structure, int ep_mask, boolean paged, boolean feed, boolean forcomments, boolean walk_dirs, boolean endpoints) { String feedregex2 = null; Object feed_name = null; String feedregex = null; String trackbackregex = null; String pageregex = null; Array<Object> ep_query_append = new Array<Object>(); String epmatch = null; Array<Object> endpoint = new Array<Object>(); String epquery = null; String front = null; Array tokens = new Array(); int num_tokens = 0; String index = null; String feedindex = null; String trackbackindex = null; int i = 0; Array<Object> queries = new Array<Object>(); /* Is used only as array */ String query_token = null; String structure = null; Array<String> dirs = new Array<String>(); int num_dirs = 0; Array<Object> post_rewrite = new Array<Object>(); String struct = null; int j = 0; String match = null; int num_toks = 0; Array toks = new Array(); String query = null; Object ep_mask_specific = null; String pagematch = null; String pagequery = null; String feedmatch = null; String feedquery = null; String feedmatch2 = null; String feedquery2 = null; Array<Object> rewrite = new Array<Object>(); Array<Object> ep = new Array<Object>(); Object regex = null; boolean post = false; boolean page = false; String trackbackmatch = null; String trackbackquery = null; String submatchbase = null; String sub1 = null; String sub1tb = null; String sub1feed = null; String sub1feed2 = null; String sub2 = null; String sub2tb = null; String sub2feed = null; String sub2feed2 = null; String subquery = null; String subtbquery = null; String subfeedquery = null; //build a regex to match the feed section of URLs, something like (feed|atom|rss|rss2)/? feedregex2 = ""; for (Map.Entry javaEntry581 : this.feeds.entrySet()) { feed_name = javaEntry581.getValue(); feedregex2 = feedregex2 + strval(feed_name) + "|"; } feedregex2 = "(" + Strings.trim(feedregex2, "|") + ")/?$"; //$feedregex is identical but with /feed/ added on as well, so URLs like <permalink>/feed/atom //and <permalink>/atom are both possible feedregex = this.feed_base + "/" + feedregex2; //build a regex to match the trackback and page/xx parts of URLs trackbackregex = "trackback/?$"; pageregex = "page/?([0-9]{1,})/?$"; //build up an array of endpoint regexes to append => queries to append if (endpoints) { ep_query_append = new Array<Object>(); for (Map.Entry javaEntry582 : this.endpoints.entrySet()) { endpoint = (Array<Object>) javaEntry582.getValue(); //match everything after the endpoint name, but allow for nothing to appear there epmatch = strval(endpoint.getValue(1)) + "(/(.*))?/?$"; //this will be appended on to the rest of the query for each dir epquery = "&" + strval(endpoint.getValue(1)) + "="; ep_query_append.putValue(epmatch, new Array<Object>(new ArrayEntry<Object>(endpoint.getValue(0)), new ArrayEntry<Object>(epquery))); } } //get everything up to the first rewrite tag front = Strings.substr(permalink_structure, 0, Strings.strpos(permalink_structure, "%")); //build an array of the tags (note that said array ends up being in $tokens[0]) QRegExPerl.preg_match_all("/%.+?%/", permalink_structure, tokens); num_tokens = Array.count(tokens.getValue(0)); index = this.index; //probably 'index.php' feedindex = index; trackbackindex = index; //build a list from the rewritecode and queryreplace arrays, that will look something like //tagname=$matches[i] where i is the current $i for (i = 0; i < num_tokens; ++i) { if (0 < i) { queries.putValue(i, strval(queries.getValue(i - 1)) + "&"); } else { queries.putValue(i, ""); } query_token = strval(Strings.str_replace(this.rewritecode, this.queryreplace, strval(tokens.getArrayValue(0).getValue(i)))) + this.preg_index(i + 1); queries.putValue(i, strval(queries.getValue(i)) + query_token); } //get the structure, minus any cruft (stuff that isn't tags) at the front structure = permalink_structure; if (!equal(front, "/")) { structure = Strings.str_replace(front, "", structure); } //create a list of dirs to walk over, making rewrite rules for each level //so for example, a $structure of /%year%/%month%/%postname% would create //rewrite rules for /%year%/, /%year%/%month%/ and /%year%/%month%/%postname% structure = Strings.trim(structure, "/"); if (walk_dirs) { dirs = Strings.explode("/", structure); } else { dirs.putValue(structure); } num_dirs = Array.count(dirs); //strip slashes from the front of $front front = QRegExPerl.preg_replace("|^/+|", "", front); //the main workhorse loop post_rewrite = new Array<Object>(); struct = front; for (j = 0; j < num_dirs; ++j) { //get the struct for this dir, and trim slashes off the front struct = struct + dirs.getValue(j) + "/"; //accumulate. see comment near explode('/', $structure) above struct = Strings.ltrim(struct, "/"); //replace tags with regexes match = Strings.str_replace(this.rewritecode, this.rewritereplace, struct); //make a list of tags, and store how many there are in $num_toks num_toks = QRegExPerl.preg_match_all("/%.+?%/", struct, toks); //get the 'tagname=$matches[i]' query = ((isset(queries) && is_array(queries)) ? strval(queries.getValue(num_toks - 1)) : ""); //set up $ep_mask_specific which is used to match more specific URL types { int javaSwitchSelector89 = 0; if (equal(dirs.getValue(j), "%year%")) { javaSwitchSelector89 = 1; } if (equal(dirs.getValue(j), "%monthnum%")) { javaSwitchSelector89 = 2; } if (equal(dirs.getValue(j), "%day%")) { javaSwitchSelector89 = 3; } switch (javaSwitchSelector89) { case 1: { ep_mask_specific = gConsts.getEP_YEAR(); break; } case 2: { ep_mask_specific = gConsts.getEP_MONTH(); break; } case 3: { ep_mask_specific = gConsts.getEP_DAY(); break; } } } //create query for /page/xx pagematch = match + pageregex; pagequery = index + "?" + query + "&paged=" + this.preg_index(num_toks + 1); //create query for /feed/(feed|atom|rss|rss2|rdf) feedmatch = match + feedregex; feedquery = feedindex + "?" + query + "&feed=" + this.preg_index(num_toks + 1); //create query for /(feed|atom|rss|rss2|rdf) (see comment near creation of $feedregex) feedmatch2 = match + feedregex2; feedquery2 = feedindex + "?" + query + "&feed=" + this.preg_index(num_toks + 1); //if asked to, turn the feed queries into comment feed ones if (forcomments) { feedquery = feedquery + "&withcomments=1"; feedquery2 = feedquery2 + "&withcomments=1"; } //start creating the array of rewrites for this dir rewrite = new Array<Object>(); if (feed) { //...adding on /feed/ regexes => queries rewrite = new Array<Object>(new ArrayEntry<Object>(feedmatch, feedquery), new ArrayEntry<Object>(feedmatch2, feedquery2)); } if (paged) { //...and /page/xx ones rewrite = Array.array_merge(rewrite, new Array<Object>(new ArrayEntry<Object>(pagematch, pagequery))); } //do endpoints if (endpoints) { for (Map.Entry javaEntry583 : ep_query_append.entrySet()) { regex = javaEntry583.getKey(); ep = (Array<Object>) javaEntry583.getValue(); //add the endpoints on if the mask fits if (booleanval(intval(ep.getValue(0)) & ep_mask) || booleanval(intval(ep.getValue(0)) & intval(ep_mask_specific))) { rewrite.putValue(match + regex, index + "?" + query + strval(ep.getValue(1)) + this.preg_index(num_toks + 2)); } } } //if we've got some tags in this dir if (booleanval(num_toks)) { post = false; page = false; //check to see if this dir is permalink-level: i.e. the structure specifies an //individual post. Do this by checking it contains at least one of 1) post name, //2) post ID, 3) page name, 4) timestamp (year, month, day, hour, second and //minute all present). Set these flags now as we need them for the endpoints. if (!strictEqual(Strings.strpos(struct, "%postname%"), BOOLEAN_FALSE) || !strictEqual(Strings.strpos(struct, "%post_id%"), BOOLEAN_FALSE) || !strictEqual(Strings.strpos(struct, "%pagename%"), BOOLEAN_FALSE) || (!strictEqual(Strings.strpos(struct, "%year%"), BOOLEAN_FALSE) && !strictEqual(Strings.strpos(struct, "%monthnum%"), BOOLEAN_FALSE) && !strictEqual(Strings.strpos(struct, "%day%"), BOOLEAN_FALSE) && !strictEqual(Strings.strpos(struct, "%hour%"), BOOLEAN_FALSE) && !strictEqual(Strings.strpos(struct, "%minute%"), BOOLEAN_FALSE) && !strictEqual(Strings.strpos(struct, "%second%"), BOOLEAN_FALSE))) { post = true; if (!strictEqual(Strings.strpos(struct, "%pagename%"), BOOLEAN_FALSE)) { page = true; } } //if we're creating rules for a permalink, do all the endpoints like attachments etc if (post) { post = true; //create query and regex for trackback trackbackmatch = match + trackbackregex; trackbackquery = trackbackindex + "?" + query + "&tb=1"; //trim slashes from the end of the regex for this dir match = Strings.rtrim(match, "/"); //get rid of brackets submatchbase = Strings.str_replace(new Array<Object>(new ArrayEntry<Object>("("), new ArrayEntry<Object>(")")), "", match); //add a rule for at attachments, which take the form of <permalink>/some-text sub1 = submatchbase + "/([^/]+)/"; sub1tb = sub1 + trackbackregex; //add trackback regex <permalink>/trackback/... sub1feed = sub1 + feedregex; //and <permalink>/feed/(atom|...) sub1feed2 = sub1 + feedregex2; //and <permalink>/(feed|atom...) //add an ? as we don't have to match that last slash, and finally a $ so we //match to the end of the URL //add another rule to match attachments in the explicit form: //<permalink>/attachment/some-text sub2 = submatchbase + "/attachment/([^/]+)/"; sub2tb = sub2 + trackbackregex; //and add trackbacks <permalink>/attachment/trackback sub2feed = sub2 + feedregex; //feeds, <permalink>/attachment/feed/(atom|...) sub2feed2 = sub2 + feedregex2; //and feeds again on to this <permalink>/attachment/(feed|atom...) //create queries for these extra tag-ons we've just dealt with subquery = index + "?attachment=" + this.preg_index(1); subtbquery = subquery + "&tb=1"; subfeedquery = subquery + "&feed=" + this.preg_index(2); //do endpoints for attachments if (!empty(endpoint)) { for (Map.Entry javaEntry584 : ep_query_append.entrySet()) { regex = javaEntry584.getKey(); ep = (Array<Object>) javaEntry584.getValue(); if (booleanval(intval(ep.getValue(0)) & gConsts.getEP_ATTACHMENT())) { rewrite.putValue(sub1 + regex, subquery + "?" + strval(ep.getValue(1)) + this.preg_index(2)); rewrite.putValue(sub2 + regex, subquery + "?" + strval(ep.getValue(1)) + this.preg_index(2)); } } } //now we've finished with endpoints, finish off the $sub1 and $sub2 matches sub1 = sub1 + "?$"; sub2 = sub2 + "?$"; //allow URLs like <permalink>/2 for <permalink>/page/2 match = match + "(/[0-9]+)?/?$"; query = index + "?" + query + "&page=" + this.preg_index(num_toks + 1); } else { //not matching a permalink so this is a lot simpler //close the match and finalise the query match = match + "?$"; query = index + "?" + query; } //create the final array for this dir by joining the $rewrite array (which currently //only contains rules/queries for trackback, pages etc) to the main regex/query for //this dir rewrite = Array.array_merge(rewrite, new Array<Object>(new ArrayEntry<Object>(match, query))); //if we're matching a permalink, add those extras (attachments etc) on if (post) { //add trackback rewrite = Array.array_merge(new Array<Object>(new ArrayEntry<Object>(trackbackmatch, trackbackquery)), rewrite); //add regexes/queries for attachments, attachment trackbacks and so on if (!page) { //require <permalink>/attachment/stuff form for pages because of confusion with subpages rewrite = Array.array_merge(rewrite, new Array<Object>(new ArrayEntry<Object>(sub1, subquery), new ArrayEntry<Object>(sub1tb, subtbquery), new ArrayEntry<Object>(sub1feed, subfeedquery), new ArrayEntry<Object>(sub1feed2, subfeedquery))); } rewrite = Array.array_merge(new Array<Object>( new ArrayEntry<Object>(sub2, subquery), new ArrayEntry<Object>(sub2tb, subtbquery), new ArrayEntry<Object>(sub2feed, subfeedquery), new ArrayEntry<Object>(sub2feed2, subfeedquery)), rewrite); } } //if($num_toks) //add the rules for this dir to the accumulating $post_rewrite post_rewrite = Array.array_merge(rewrite, post_rewrite); } //foreach ($dir) return post_rewrite; //the finished rules. phew! } public Array<Object> generate_rewrite_rule(String permalink_structure, boolean walk_dirs) { return this.generate_rewrite_rules(permalink_structure, gConsts.getEP_NONE(), false, false, false, walk_dirs); } /** * rewrite_rules Construct rewrite matches and queries from permalink * structure. Returns an associate array of matches and queries. */ public Array<Object> rewrite_rules() { Array<Object> rewrite; Array<Object> robots_rewrite = new Array<Object>(); Array<Object> default_feeds = new Array<Object>(); Array<Object> post_rewrite = new Array<Object>(); Array<Object> date_rewrite = new Array<Object>(); Array<Object> root_rewrite = new Array<Object>(); Array<Object> comments_rewrite = new Array<Object>(); String search_structure = null; Array<Object> search_rewrite = new Array<Object>(); Array<Object> category_rewrite = new Array<Object>(); Array<Object> tag_rewrite = new Array<Object>(); Array<Object> author_rewrite = new Array<Object>(); Array<Object> page_rewrite = new Array<Object>(); String permastruct = null; rewrite = new Array<Object>(); if (empty(this.permalink_structure)) { return rewrite; } // robots.txt robots_rewrite = new Array<Object>(new ArrayEntry<Object>("robots.txt$", this.index + "?robots=1")); //Default Feed rules - These are require to allow for the direct access files to work with permalink structure starting with %category% default_feeds = new Array<Object>( new ArrayEntry<Object>(".*/wp-atom.php$", this.index + "?feed=atom"), new ArrayEntry<Object>(".*/wp-rdf.php$", this.index + "?feed=rdf"), new ArrayEntry<Object>(".*/wp-rss.php$", this.index + "?feed=rss"), new ArrayEntry<Object>(".*/wp-rss2.php$", this.index + "?feed=rss2"), new ArrayEntry<Object>(".*/wp-feed.php$", this.index + "?feed=feed"), new ArrayEntry<Object>(".*/wp-commentsrss2.php$", this.index + "?feed=rss2&withcomments=1")); // Post post_rewrite = this.generate_rewrite_rules(this.permalink_structure, gConsts.getEP_PERMALINK()); post_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("post_rewrite_rules", post_rewrite); // Date date_rewrite = this.generate_rewrite_rules(this.get_date_permastruct(), gConsts.getEP_DATE()); date_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("date_rewrite_rules", date_rewrite); // Root root_rewrite = this.generate_rewrite_rules(this.root + "/", gConsts.getEP_ROOT()); root_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("root_rewrite_rules", root_rewrite); // Comments comments_rewrite = this.generate_rewrite_rules(this.root + this.comments_base, gConsts.getEP_COMMENTS(), true, true, true, false); comments_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("comments_rewrite_rules", comments_rewrite); // Search search_structure = this.get_search_permastruct(); search_rewrite = this.generate_rewrite_rules(search_structure, gConsts.getEP_SEARCH()); search_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("search_rewrite_rules", search_rewrite); // Categories category_rewrite = this.generate_rewrite_rules(this.get_category_permastruct(), gConsts.getEP_CATEGORIES()); category_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("category_rewrite_rules", category_rewrite); // Tags tag_rewrite = this.generate_rewrite_rules(this.get_tag_permastruct(), gConsts.getEP_TAGS()); tag_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("tag_rewrite_rules", tag_rewrite); // Authors author_rewrite = this.generate_rewrite_rules(this.get_author_permastruct(), gConsts.getEP_AUTHORS()); author_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("author_rewrite_rules", author_rewrite); // Pages page_rewrite = this.page_rewrite_rules(); page_rewrite = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("page_rewrite_rules", page_rewrite); // Extra permastructs for (Map.Entry javaEntry585 : this.extra_permastructs.entrySet()) { permastruct = strval(javaEntry585.getValue()); this.extra_rules_top = Array.array_merge(this.extra_rules_top, this.generate_rewrite_rules(permastruct, gConsts.getEP_NONE())); } // Put them together. if (this.use_verbose_page_rules) { this.rules = Array.array_merge( this.extra_rules_top, robots_rewrite, default_feeds, page_rewrite, root_rewrite, comments_rewrite, search_rewrite, category_rewrite, tag_rewrite, author_rewrite, date_rewrite, post_rewrite, this.extra_rules); } else { this.rules = Array.array_merge( this.extra_rules_top, robots_rewrite, default_feeds, root_rewrite, comments_rewrite, search_rewrite, category_rewrite, tag_rewrite, author_rewrite, date_rewrite, post_rewrite, page_rewrite, this.extra_rules); } getIncluded(PluginPage.class, gVars, gConsts).do_action_ref_array("generate_rewrite_rules", new Array<Object>(new ArrayEntry<Object>(this))); this.rules = (Array<Object>) getIncluded(PluginPage.class, gVars, gConsts).apply_filters("rewrite_rules_array", this.rules); return this.rules; } public Array<Object> wp_rewrite_rules() { Object rulesObj = getIncluded(FunctionsPage.class, gVars, gConsts).get_option("rewrite_rules"); if (empty(rulesObj)) { this.matches = "matches"; this.rewrite_rules(); getIncluded(FunctionsPage.class, gVars, gConsts).update_option("rewrite_rules", this.rules); } else { this.rules = (Array<Object>) rulesObj; } return this.rules; } public String mod_rewrite_rules() { Array<String> site_rootArray = new Array<String>(); Array<String> home_rootArray = new Array<String>(); String rules = null; String match = null; String query = null; Array<Object> rewrite = new Array<Object>(); int num_rules = 0; if (!this.using_permalinks()) { return ""; } site_rootArray = URL.parse_url(strval(getIncluded(FunctionsPage.class, gVars, gConsts).get_option("siteurl"))); String site_root = getIncluded(FormattingPage.class, gVars, gConsts).trailingslashit(site_rootArray.getValue("path")); home_rootArray = URL.parse_url(strval(getIncluded(FunctionsPage.class, gVars, gConsts).get_option("home"))); String home_root = getIncluded(FormattingPage.class, gVars, gConsts).trailingslashit(home_rootArray.getValue("path")); rules = "<IfModule mod_rewrite.c>\n"; rules = rules + "RewriteEngine On\n"; rules = rules + "RewriteBase " + home_root + "\n"; //add in the rules that don't redirect to WP's index.php (and thus shouldn't be handled by WP at all) for (Map.Entry javaEntry586 : this.non_wp_rules.entrySet()) { match = strval(javaEntry586.getKey()); query = strval(javaEntry586.getValue()); // Apache 1.3 does not support the reluctant (non-greedy) modifier. match = Strings.str_replace(".+?", ".+", match); // If the match is unanchored and greedy, prepend rewrite conditions // to avoid infinite redirects and eclipsing of real files. if (equal(match, "(.+)/?$") || equal(match, "([^/]+)/?$")) { //nada. } rules = rules + "RewriteRule ^" + match + " " + home_root + query + " [QSA,L]\n"; } if (this.use_verbose_rules) { this.matches = ""; rewrite = this.rewrite_rules(); num_rules = Array.count(rewrite); rules = rules + "RewriteCond %{REQUEST_FILENAME} -f [OR]\n" + "RewriteCond %{REQUEST_FILENAME} -d\n" + "RewriteRule ^.*$ - [S=" + strval(num_rules) + "]\n"; for (Map.Entry javaEntry587 : rewrite.entrySet()) { match = strval(javaEntry587.getKey()); query = strval(javaEntry587.getValue()); // Apache 1.3 does not support the reluctant (non-greedy) modifier. match = Strings.str_replace(".+?", ".+", match); // If the match is unanchored and greedy, prepend rewrite conditions // to avoid infinite redirects and eclipsing of real files. if (equal(match, "(.+)/?$") || equal(match, "([^/]+)/?$")) { //nada. } if (!strictEqual(Strings.strpos(query, this.index), BOOLEAN_FALSE)) { rules = rules + "RewriteRule ^" + match + " " + home_root + query + " [QSA,L]\n"; } else { rules = rules + "RewriteRule ^" + match + " " + site_root + query + " [QSA,L]\n"; } } } else { rules = rules + "RewriteCond %{REQUEST_FILENAME} !-f\n" + "RewriteCond %{REQUEST_FILENAME} !-d\n" + "RewriteRule . " + home_root + this.index + " [L]\n"; } rules = rules + "</IfModule>\n"; rules = strval(getIncluded(PluginPage.class, gVars, gConsts).apply_filters("mod_rewrite_rules", rules)); rules = strval(getIncluded(PluginPage.class, gVars, gConsts).apply_filters("rewrite_rules", rules)); // Deprecated return rules; } /** * Add a straight rewrite rule */ public void add_rule(String regex, String redirect, String after) { int index = 0; String front = null; //get everything up to the first ? index = (equal(Strings.strpos(redirect, "?"), false) ? Strings.strlen(redirect) : Strings.strpos(redirect, "?")); front = Strings.substr(redirect, 0, index); if (!equal(front, this.index)) { //it doesn't redirect to WP's index.php this.add_external_rule(regex, redirect); } else { if (equal("bottom", after)) { this.extra_rules = Array.array_merge(this.extra_rules, new Array<Object>(new ArrayEntry<Object>(regex, redirect))); } else { this.extra_rules_top = Array.array_merge(this.extra_rules_top, new Array<Object>(new ArrayEntry<Object>(regex, redirect))); //$this->extra_rules[$regex] = $redirect; } } } /** * add a rule that doesn't redirect to index.php */ public void add_external_rule(Object regex, Object redirect) { this.non_wp_rules.putValue(regex, redirect); } /** * add an endpoint, like /trackback/, to be inserted after certain URL types * (specified in $places) */ public void add_endpoint(Object name, Object places) { this.endpoints.putValue(new Array<Object>(new ArrayEntry<Object>(places), new ArrayEntry<Object>(name))); gVars.wp.add_query_var(strval(name)); } public void add_permastruct(String name, String struct) { add_permastruct(name, struct, true); } public void add_permastruct(String name, String struct, boolean with_front) { if (with_front) { struct = this.front + struct; } this.extra_permastructs.putValue(name, struct); } public void flush_rules() { getIncluded(FunctionsPage.class, gVars, gConsts).delete_option("rewrite_rules"); this.wp_rewrite_rules(); if (true)/*Modified by Numiton*/ { getIncluded(MiscPage.class, gVars, gConsts).save_mod_rewrite_rules(); } } public void init() { String structure = null; this.extra_rules = this.non_wp_rules = this.endpoints = new Array<Object>(); this.permalink_structure = strval(getIncluded(FunctionsPage.class, gVars, gConsts).get_option("permalink_structure")); this.front = Strings.substr(this.permalink_structure, 0, Strings.strpos(this.permalink_structure, "%")); this.root = ""; if (this.using_index_permalinks()) { this.root = this.index + "/"; } this.category_base = getIncluded(FunctionsPage.class, gVars, gConsts).get_option("category_base"); this.tag_base = getIncluded(FunctionsPage.class, gVars, gConsts).get_option("tag_base"); this.category_structure = null; this.author_structure = null; this.date_structure = null; this.page_structure = null; this.search_structure = null; this.feed_structure = null; this.comment_feed_structure = null; this.use_trailing_slashes = (equal(Strings.substr(this.permalink_structure, -1, 1), "/") ? true : false); // Enable generic rules for pages if permalink structure doesn't begin with a wildcard. structure = Strings.ltrim(this.permalink_structure, "/"); if (this.using_index_permalinks()) { structure = Strings.ltrim(this.permalink_structure, this.index + "/"); } if (strictEqual(0, Strings.strpos(structure, "%postname%")) || strictEqual(0, Strings.strpos(structure, "%category%")) || strictEqual(0, Strings.strpos(structure, "%tag%")) || strictEqual(0, Strings.strpos(structure, "%author%"))) { this.use_verbose_page_rules = true; } else { this.use_verbose_page_rules = false; } } public void set_permalink_structure(Object permalink_structure) { if (!equal(permalink_structure, this.permalink_structure)) { getIncluded(FunctionsPage.class, gVars, gConsts).update_option("permalink_structure", permalink_structure); this.init(); } } public void set_category_base(Object category_base) { if (!equal(category_base, this.category_base)) { getIncluded(FunctionsPage.class, gVars, gConsts).update_option("category_base", category_base); this.init(); } } public void set_tag_base(Object tag_base) { if (!equal(tag_base, this.tag_base)) { getIncluded(FunctionsPage.class, gVars, gConsts).update_option("tag_base", tag_base); this.init(); } } public void setContext(GlobalVariablesContainer javaGlobalVariables, GlobalConstantsInterface javaGlobalConstants) { gConsts = (GlobalConsts) javaGlobalConstants; gVars = (GlobalVars) javaGlobalVariables; gVars.gConsts = gConsts; } public Object clone() throws CloneNotSupportedException { return super.clone(); } public GlobalVariablesContainer getGlobalVars() { return gVars; } }