巨大八爪鱼
武林盟主 二十一級
|
package purasbar3.info;
import java.net.URLDecoder; import java.util.Arrays; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap;
import org.apache.commons.lang3.StringUtils;
import purasbar3.AttributeHolder; import purasbar3.Page; import purasbar3.Website; import purasbar3.WebsiteDatabase; import purasbar3.data.Bar; import purasbar3.data.BarCategory; import purasbar3.data.Disambiguation; import purasbar3.data.Post; import purasbar3.data.User; import purasbar3.text.TextUtils;
public class LegacyPageRedirector extends AttributeHolder { public static final String[][] TABLE = { {"/wap/", "/mobile/"}, {"/wap/index.php", "/mobile/"}, {"/wap/list.php", "/mobile/(bar/{b,bi:barName}|topics)[/good[/{i}]@type=good|/best[/{i}]@type=best|/votes@type=vote|/pictures@type=picture][/page/{p}]"}, {"/wap/post.php#convertFloorNumberAnchor", "/mobile/post/{t,i:topicID}[/floor/{i:floorNo}][/author@type=only1F][/page/{p}]"}, {"/wap/settings.php", "/mobile/settings"}, {"/wap/login.php", "/mobile/signin"}, {"/wap/register.php", "/mobile/signup"}, {"/wap/bar_classes.php", "/mobile/category[/{i:categoryName}][/page/{p}]"}, {"/wap/disambiguation.php", "/mobile/disambiguation/{i:disambiguationName}"}, {"/wap/user.php", "/mobile/user/{name,i:userName}[/page/{p}]"}, {"/wap/search.php", "/mobile(/mentions@c=%2Fu%2Fu+%3A%40|/replies@c=%2Fu%2Fu+%3AR|/search/{c}@c!=%2Fu%2Fu|/search@c=%2Fu%2Fu|/search)[/page/{p}]?range=[{b}]&author=[{u}]&sort=(asc@sort=1|desc|)&pagesize=[{page_size}]"}, {"/list.php", "/(bar/{b,bi:barName}|topics)[/good[/{i}]@type=good|/best[/{i}]@type=best|/votes@type=vote|/pictures@type=picture][/page/{p}]"}, {"/post.php#convertFloorNumberAnchor", "/post/{t,i:topicID}[/floor/{i:floorNo}][/author@type=only1F][/page/{p}]"}, {"/search.php", "(/mentions@c=%2Fu%2Fu+%3A%40|/replies@c=%2Fu%2Fu+%3AR|/search/{c}@c!=%2Fu%2Fu|/search@c=%2Fu%2Fu|/search)[/page/{p}]?range=[{b}]&author=[{u}]&sort=(asc@sort=1|desc|)&pagesize=[{page_size}]"}, {"/user.php", "(/mobile/messages/inbox[/{id}]@msg=1%2C1|/mobile/messages/outbox[/{id}]@msg=1%2C2|/mobile/messages/system[/{}]@msg=2%2C1|/user/{name,i:userName})[/page/{p}]"} }; public static final int POST_ID_OFFSET = 43325; private Page page; private String filePath; private String path; private String queryString; private String[][] queryStringArray; private boolean[] queryStringUsed; private String redirection; private String anchorFunctionName; private Map<String, String> generatedQueryStringArray; public LegacyPageRedirector(Page page) { this(page, page.getRequestPathWithQueryString()); } public LegacyPageRedirector(Page page, String path) { this.page = page; this.path = path; int i = path.indexOf('?'); filePath = (i == -1) ? path : path.substring(0, i); queryString = (i == -1) ? "" : path.substring(i + 1); if (!queryString.isEmpty()) { String[] arr = queryString.split("&"); queryStringArray = new String[arr.length][]; for (i = 0; i < arr.length; i++) { queryStringArray[i] = StringUtils.splitPreserveAllTokens(arr[i], '='); } queryStringUsed = new boolean[arr.length]; } try { if (path.startsWith("/wap") || path.contains(".php")) { parseOldPath(); } else if (path.startsWith("/mobile")) { parseNewPath(); } } catch (IllegalArgumentException e) { throw e; } catch (Exception e) { e.printStackTrace(); redirection = null; } }
public String addUnparsedQueryString(String url) { String str = getUnparsedQueryString(); if (str != null) { if (url.indexOf('?') == -1) { url += '?' + str; } else { url += '&' + str; } } return url; } private String convertValue(String operation, String value) throws Exception { WebsiteDatabase db = page.getDatabase(); if (operation.equals("barName")) { int id = Integer.valueOf(value); Bar bar = (Bar)getAttribute("_bar_" + id); if (bar == null) { bar = Bar.forId(db, id); setAttribute("_bar_" + id, bar); } return TextUtils.encodeURL(bar.getName()); } else if (operation.equals("topicID")) { int id = Integer.valueOf(value); id += POST_ID_OFFSET; Post post = (Post)getAttribute("_post_" + id); if (post == null) { post = Post.forId(db, id); setAttribute("_post_" + id, post); } id = post.getTopicId(); return String.valueOf(id); } else if (operation.equals("floorNo")) { int id = Integer.valueOf(value); id += POST_ID_OFFSET; Post post = (Post)getAttribute("_post_" + id); if (post == null) { post = Post.forId(db, id); setAttribute("_post_" + id, post); } int floor = post.getFloor(); if (floor != 1) { return String.valueOf(floor); } } else if (operation.equals("~floorNo")) { int floorNo = Integer.valueOf(value); Post post = (Post)getAttribute("_post_floor_" + floorNo); if (post == null) { String topicIdStr = generatedQueryStringArray.get("t"); if (topicIdStr == null) { throw new Exception("undefined topic id"); } generatedQueryStringArray.remove("t"); int topicId = Integer.valueOf(topicIdStr); post = Post.forTopicId(db, topicId); post = post.getFloorPost(floorNo); setAttribute("_post_floor_" + floorNo, post); } return String.valueOf(post.getId() - POST_ID_OFFSET); } else if (operation.equals("categoryName")) { int id = Integer.valueOf(value); BarCategory category = (BarCategory)getAttribute("_category_" + id); if (category == null) { category = BarCategory.forId(db, id); setAttribute("_category_" + id, category); } return TextUtils.encodeURL(category.getName()); } else if (operation.equals("~categoryName")) { String name = URLDecoder.decode(value, Website.ENCODING); BarCategory category = (BarCategory)getAttribute("_category__" + name); if (category == null) { category = BarCategory.forName(db, name); setAttribute("_category__" + name, category); } return String.valueOf(category.getId()); } else if (operation.equals("disambiguationName")) { int id = Integer.valueOf(value); Disambiguation disambiguation = (Disambiguation)getAttribute("_disambiguation_" + id); if (disambiguation == null) { disambiguation = Disambiguation.forId(db, id); setAttribute("_disambiguation_" + id, disambiguation); } return TextUtils.encodeURL(disambiguation.getName()); } else if (operation.equals("~disambiguationName")) { String name = URLDecoder.decode(value, Website.ENCODING); Disambiguation disambiguation = (Disambiguation)getAttribute("_disambiguation__" + name); if (disambiguation == null) { disambiguation = Disambiguation.forName(db, name); setAttribute("_disambiguation__" + name, disambiguation); } return String.valueOf(disambiguation.getId()); } else if (operation.equals("userName")) { int id = Integer.valueOf(value); User user = (User)getAttribute("_user_" + id); if (user == null) { user = User.forId(db, id); setAttribute("_user_" + id, user); } return TextUtils.encodeURL(user.getName()); } return null; } private String generateNewPath(String pattern, int level) throws Exception { int len = pattern.length(); if (pattern.contains("|")) { int i, j = 0; int n = 0; for (i = 0; i < len; i++) { char c = pattern.charAt(i); if (c == '(' || c == '[') { n++; } else if (c == ')' || c == ']') { n--; } else if (c == '|' && n == 0) { String substr = generateNewPath(pattern.substring(j, i), level + 1); if (substr != null) { return substr; } j = i + 1; } } if (j != 0) { return generateNewPath(pattern.substring(j), level + 1); } } for (int i = 0; i < 2; i++) { char c1 = (i == 0) ? '(' : '['; char c2 = (i == 0) ? ')' : ']'; int j = 0; while ((j = pattern.indexOf(c1, j)) != -1) { int k, n = 0; for (k = j; k < len; k++) { char c = pattern.charAt(k); if (c == c1) { n++; } else if (c == c2) { n--; if (n == 0) { break; } } } if (k == len) { throw new IllegalArgumentException("unclosed " + c1 + c2 + " brackets"); } String substr = generateNewPath(pattern.substring(j + 1, k), level + 1); if (substr == null) { if (c1 == '(') { // (x) is not optional return null; } else if (c1 == '[') { // [x] is optional substr = ""; } } pattern = pattern.substring(0, j) + substr + pattern.substring(k + 1); j += substr.length(); } } int i = pattern.indexOf('@'); if (i != -1) { String condition = pattern.substring(i + 1); pattern = pattern.substring(0, i); i = condition.indexOf('='); if (i != -1) { char op = '='; String paramName = condition.substring(0, i); if (paramName.endsWith("!")) { op = condition.charAt(i - 1); paramName = condition.substring(0, i - 1); } setParameterUsed(paramName); String paramValue = condition.substring(i + 1); String realValue = getParameterRawValue(paramName); if (op == '=') { if (realValue == null || !realValue.equals(paramValue)) { return null; } } else if (op == '!') { if (realValue != null && realValue.equals(paramValue)) { return null; } } } else { String paramName = condition; if (!hasParameter(paramName)) { return null; } setParameterUsed(paramName); String realValue = getParameterRawValue(paramName); if (realValue != null && !realValue.isEmpty()) { return null; } } } i = 0; while ((i = pattern.indexOf('{', i)) != -1) { int j = pattern.indexOf('}', i); if (j == -1) { throw new IllegalArgumentException("unclosed {} brackets"); } String params = pattern.substring(i + 1, j); String[] arr = params.split(","); int k; String paramValue = null; for (k = 0; k < arr.length; k++) { String[] arr2 = arr[k].split(":"); String paramName = arr2[0]; if (hasParameter(paramName)) { paramValue = getParameterRawValue(paramName); setParameterUsed(paramName); if (paramValue == null || paramValue.isEmpty()) { return null; } if (arr2.length >= 2) { paramValue = convertValue(arr2[1], paramValue); if (paramValue == null) { return null; } } break; } } if (k == arr.length) { return null; } if (level == 0) { pattern = pattern.substring(0, i) + paramValue + pattern.substring(j + 1); i += paramValue.length(); } else { pattern = pattern.substring(0, i + 1) + arr[k] + pattern.substring(j); i += arr[k].length() + 2; } } return pattern; } private String generateOldPath(String pattern, String newPath, int level) throws Exception { if (level == 0) { newPath = sortQueryString(pattern, newPath); } int len = pattern.length(); int len2 = newPath.length(); if (pattern.contains("|")) { int i, j = 0; int n = 0; for (i = 0; i < len; i++) { char c = pattern.charAt(i); if (c == '(' || c == '[') { n++; } else if (c == ')' || c == ']') { n--; } else if (c == '|' && n == 0) { String substr = generateOldPath(pattern.substring(j, i), newPath, level + 1); if (substr != null) { return substr; } j = i + 1; } } if (j != 0) { return generateOldPath(pattern.substring(j), newPath, level + 1); } } int quoteStart = -1; int quoteLevel = 0; int j = 0; for (int i = 0; i < len; i++) { char c = pattern.charAt(i); if (quoteStart == -1) { if (c == '(' || c == '[') { quoteStart = i; quoteLevel++; } else if (c == '{') { int k = pattern.indexOf('}', i); if (k == -1) { throw new IllegalArgumentException("unclosed {} brackets"); } String paramName = pattern.substring(i + 1, k); i = k; k = paramName.indexOf(','); if (k != -1) { paramName = paramName.substring(0, k); } String paramConverterName = null; k = paramName.indexOf(':'); if (k != -1) { paramConverterName = paramName.substring(k + 1); paramName = paramName.substring(0, k); } String paramValue; k = newPath.indexOf('/', j); if (k == -1) { k = newPath.indexOf('?', j); } if (k == -1) { k = newPath.indexOf('&', j); } if (k == -1) { paramValue = newPath.substring(j); j = len2; } else { paramValue = newPath.substring(j, k); j = k; } if (paramValue.equals("page")) { if (j + 1 < len2) { String nextSegment; k = newPath.indexOf('/', j + 1); if (k == -1) { k = newPath.indexOf('?', j + 1); } if (k != -1) { nextSegment = newPath.substring(j + 1, k); } else { nextSegment = newPath.substring(j + 1); } if (TextUtils.isNumber(nextSegment)) { return null; } } } if (paramConverterName != null) { paramValue = convertValue('~' + paramConverterName, paramValue); if (paramValue == null) { return null; } } setParameterRawValue(paramName, paramValue); } else { if (c == '@') { // condition String condition = pattern.substring(i + 1); i += condition.length(); int k = condition.indexOf('='); if (k != -1) { String paramName = condition.substring(0, k); String paramValue = condition.substring(k + 1); if (paramName.endsWith("!")) { // != // not implemented } else { // = setParameterRawValue(paramName, paramValue); } } else { setParameterRawValue(condition, null); } } else { if (j == len2) { break; } char d = newPath.charAt(j); if (c == d) { // match j++; } else { // mismatch return null; } } } } else { if (c == '(' || c == '[') { quoteLevel++; } else if (c == ')' || c == ']') { quoteLevel--; if (quoteLevel == 0) { String subpattern = pattern.substring(quoteStart + 1, i); String substr = generateOldPath(subpattern, newPath.substring(j), level + 1); if (substr == null) { if (c == ')') { // (x) is not optional return null; } else if (c == ']') { // [x] is optional substr = ""; } } j += substr.length(); quoteStart = -1; } } } } if (level == 0) { // when level == 0, return the generated query string if (j == len2) { setParameterRawValue("version", "desktop"); return getGeneratedQueryString(); } } else { // when level != 0, only return the parsed part of the URL // the length of the returned string represents the parsed length if (j != 0 || pattern.isEmpty()) { return newPath.substring(0, j); } } return null; }
|
巨大八爪鱼
武林盟主 二十一級
|
public String getAnchorFunctionName() { return anchorFunctionName; }
public String getFilePath() { return filePath; } public String getGeneratedQueryString() { if (generatedQueryStringArray == null) { return ""; } StringBuilder sb = new StringBuilder(); boolean first = true; Set<String> set = generatedQueryStringArray.keySet(); Iterator<String> iter = set.iterator(); while (iter.hasNext()) { String name = iter.next(); if (name.isEmpty()) { continue; } if (first) { first = false; sb.append("?"); } else { sb.append("&"); } sb.append(name); String value = generatedQueryStringArray.get(name); if (value != null) { sb.append("=" + value); } } return sb.toString(); } public String getParameterRawValue(String name) { if (queryStringArray != null && name != null && !name.isEmpty()) { for (int i = 0; i < queryStringArray.length; i++) { if (queryStringArray[i][0].equals(name)) { if (queryStringArray[i].length >= 2) { return queryStringArray[i][1]; } else { return null; } } } } return null; }
public String getPath() { return path; }
public String getQueryString() { return queryString; }
public String getRedirection() { return redirection; } public String getRedirectionString() { return '"' + TextUtils.addSlashes(redirection) + '"'; } public String getUnparsedQueryString() { StringBuilder remainingParams = null; if (queryStringUsed != null) { for (int i = 0; i < queryStringUsed.length; i++) { if (!queryStringUsed[i]) { if (remainingParams == null) { remainingParams = new StringBuilder(); } else { remainingParams.append("&"); } remainingParams.append(queryStringArray[i][0]); if (queryStringArray[i].length >= 2) { remainingParams.append("=" + queryStringArray[i][1]); } } } } if (remainingParams != null) { return remainingParams.toString(); } else { return null; } } public boolean hasParameter(String name) { if (queryStringArray != null && name != null && !name.isEmpty()) { for (int i = 0; i < queryStringArray.length; i++) { if (queryStringArray[i][0].equals(name)) { return true; } } } return false; } public boolean isParameterUsed(String name) { if (queryStringArray != null && name != null && !name.isEmpty()) { for (int i = 0; i < queryStringArray.length; i++) { if (queryStringArray[i][0].equals(name)) { return queryStringUsed[i]; } } } return false; }
private void parseNewPath() throws Exception { for (int i = 0; i < TABLE.length; i++) { String oldPath = generateOldPath(TABLE[i][1], path, 0); if (oldPath != null) { String name = TABLE[i][0]; if (name.startsWith("/wap")) { name = name.substring(4); } int j = name.indexOf('#'); if (j != -1) { name = name.substring(0, j); } oldPath = addUnparsedQueryString(oldPath); redirection = name + oldPath; break; } resetVariables(); } }
private void parseOldPath() throws Exception { for (int i = 0; i < TABLE.length; i++) { String name = TABLE[i][0]; int j = name.indexOf('#'); if (j != -1) { anchorFunctionName = name.substring(j + 1); name = name.substring(0, j); } if (name.equals(filePath) || (name.endsWith("/") && name.equals(filePath + "/"))) { String newPath = generateNewPath(TABLE[i][1], 0); if (newPath != null) { if (Website.isLocalServer(page.getRequest())) { newPath = "/purasbar3" + newPath; } newPath = addUnparsedQueryString(newPath); redirection = newPath; break; } } resetVariables(); } }
private void resetVariables() { if (queryStringUsed != null) { Arrays.fill(queryStringUsed, false); } redirection = null; anchorFunctionName = null; generatedQueryStringArray = null; }
private void setParameterRawValue(String paramName, String paramValue) { setParameterUsed(paramName); if (generatedQueryStringArray == null) { generatedQueryStringArray = new TreeMap<String, String>(); } generatedQueryStringArray.put(paramName, paramValue); } private void setParameterUsed(String name) { if (queryStringArray != null && name != null && !name.isEmpty()) { for (int i = 0; i < queryStringArray.length; i++) { if (queryStringArray[i][0].equals(name)) { queryStringUsed[i] = true; } } } }
// sort the query string of [path] in the same order of [pattern] // if [pattern] does not contain any query string, remove the query string of [path] private String sortQueryString(String pattern, String path) { String[] params = null; int i = pattern.indexOf('?'); if (i != -1) { pattern = pattern.substring(i + 1); params = pattern.split("&"); for (i = 0; i < params.length; i++) { int j = params[i].indexOf('='); if (j != -1) { params[i] = params[i].substring(0, j + 1); // including '=' } } } i = path.indexOf('?'); String queryString = null; if (i != -1) { queryString = path.substring(i + 1); path = path.substring(0, i); } if (pattern.endsWith("/")) { if (!path.endsWith("/")) { path += "/"; } } else { if (path.endsWith("/")) { path = path.substring(0, path.length() - 1); } } Map<String, String> values = new HashMap<String, String>(); if (queryString != null) { String[] arr = queryString.split("&"); for (String str : arr) { i = str.indexOf('='); if (i != -1) { String name = str.substring(0, i); String value = str.substring(i + 1); values.put(name, value); } } } if (params != null) { for (i = 0; i < params.length; i++) { path += (i == 0) ? "?" : "&"; String name = params[i]; if (name.endsWith("=")) { name = name.substring(0, name.length() - 1); } String value = values.get(name); if (value != null) { path += name + "=" + value; } else { path += params[i]; } } } return path; } }
|