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;
}
