2017-11-06 3 views
2

http://google.com/search/q=<%= name %>のような文字列があります。私は制御することはできませんJavascriptのエスケープのように動作するJava URIエスケープ

第三者JSライブラリは、Javascriptが

unescape("http://google.com/search/q=%3C%=%20name%20%%3E") 

と元の文字列に成功したアンエスケープすることができますが、JavaのURLDecode.decode("http://google.com/search/q=%3C%=%20name%20%%3E")が原因のIllegalArgumentExceptionをスロー"http://google.com/search/q=%3C%=%20name%20%%3E"

にこれを脱出されます文字列内の文字ではありません。もちろん、仕様通りです。しかし、これはサーバー側の処理を複雑にします。

正規表現を使用してサーバーサイドで悪いJSエスケープを修正しようとする前に(前述のようにJSサイドを変更できないため)、より許容的なJava URL/URIがあるかどうかを知りたいと思いますJavascriptのunescapeと同じように動作する、つまりスタンドアロンの '%'文字を無視し、デコード可能なものだけをデコードするAPIをデコードします。

答えて

1

私はいくつかのApacheライブラリをすばやく見て、同じ問題に対処しました。興味深いことに、EMCAScript言語仕様をフォローアップしたところ、unescape()関数の疑似コードが見つかりました。あなたはそれが一緒に、この単純化の実装(下記参照)と少なくとも例えばあなたの質問では、出力の一致を置くことは簡単ですhttps://tc39.github.io/ecma262/#sec-unescape-string

でこれを見ることができます。

このコードは最適化されていませんが、文字エンコーディングが関連するかどうかについては考えていませんが、Regexを使って物事を取り締まるよりもあまり苦労しないかもしれません。

public static String unescape(String s) { 
    StringBuilder r = new StringBuilder(); 
    for (int i = 0; i < s.length();) { 
     if (s.charAt(i) == '%') { 
      if (looksLikeUnicode(s, i)) { 
       r.append((char) fromHex(s, i + 2, i + 5)); 
       i += 6; 
       continue; 
      } 
      if (looksLikeAscii(s, i)) { 
       r.append((char) fromHex(s, i + 1, i + 2)); 
       i += 3; 
       continue; 
      } 
     } 
     r.append(s.charAt(i)); 
     i += 1; 
    } 
    return r.toString(); 
} 

private static boolean looksLikeUnicode(String s, int i) { 
    return (i + 5 < s.length()) && (s.charAt(i + 1) == 'u') && areHexDigits(s, i + 2, i + 5); 
} 

private static boolean looksLikeAscii(String s, int i) { 
    return (i + 2 < s.length()) && areHexDigits(s, i + 1, i + 2); 
} 

private static boolean areHexDigits(String s, int from, int to) { 
    for (int i = from; i <= to; ++i) { 
     if (isNotHexDigit(s.charAt(i))) { 
      return false; 
     } 
    } 
    return true; 
} 

private static boolean isHexDigit(char c) { 
    return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); 
} 

private static boolean isNotHexDigit(char c) { 
    return !isHexDigit(c); 
} 

private static int fromHex(String s, int from, int to) { 
    return Integer.parseInt(s.substring(from, to + 1), 16); 
} 
+1

ブリリアント!どうもありがとうございます! ECMAScriptについて言及したら、実際にはJavaのネイティブScriptingEngineを使用して、JSスタイルのエスケープを行うことができることに気付きました。つまり、 'new ScriptEngineManager()。getEngineByName(" nashorn ")eval(" unescape(\ "%3C%=%20name %20 %% 3E \ ")") '、しかしそれはスクリプトエンジンをインスタンス化するための不必要なオーバヘッドをもたらすので、これを受け入れられた答えとしてマークしています。 – ccpizza

+0

ニース。私はスクリプティングエンジンを考えていたはずです。より強力なソリューションですが、少し重いです。 –

関連する問題