目前共有2篇帖子。
字體大小:較小 - 100% (默認)  內容轉換:不轉換
 
點擊 回復
25 1
新旧网址跳转类
巨大八爪鱼
武林盟主 二十一級
回復
1樓 發表於:2026-7-12 16:29
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;
    }

巨大八爪鱼
武林盟主 二十一級
回復
2樓 發表於:2026-7-12 16:30

    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;
    }
}
回覆帖子
內容:
用戶名: 您目前是匿名發表。
驗證碼:
看不清?換一張
(快捷鍵:Ctrl+Enter)
本帖信息
點擊數:25 回複數:1
作者:巨大八爪鱼
最後回覆:巨大八爪鱼
最後回復時間:2026-7-12 16:30
本吧熱門帖子
本吧精品帖子
公告板