X-Git-Url: https://code.wpia.club/?a=blobdiff_plain;ds=sidebyside;f=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Futil%2FURIUtil.java;fp=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Futil%2FURIUtil.java;h=f333fc3b5f2f2106877540ac25f330907d069763;hb=73ef54a38e3930a1a789cdc6b5fa23cdd4c9d086;hp=0000000000000000000000000000000000000000;hpb=515007c7c1351045420669d65b59c08fa46850f2;p=gigi.git diff --git a/lib/jetty/org/eclipse/jetty/util/URIUtil.java b/lib/jetty/org/eclipse/jetty/util/URIUtil.java new file mode 100644 index 00000000..f333fc3b --- /dev/null +++ b/lib/jetty/org/eclipse/jetty/util/URIUtil.java @@ -0,0 +1,694 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.util; + +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; + + + +/* ------------------------------------------------------------ */ +/** URI Holder. + * This class assists with the decoding and encoding or HTTP URI's. + * It differs from the java.net.URL class as it does not provide + * communications ability, but it does assist with query string + * formatting. + *

UTF-8 encoding is used by default for % encoded characters. This + * may be overridden with the org.eclipse.jetty.util.URI.charset system property. + * @see UrlEncoded + * + */ +public class URIUtil + implements Cloneable +{ + public static final String SLASH="/"; + public static final String HTTP="http"; + public static final String HTTP_COLON="http:"; + public static final String HTTPS="https"; + public static final String HTTPS_COLON="https:"; + + // Use UTF-8 as per http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars + public static final Charset __CHARSET; + + static + { + String charset = System.getProperty("org.eclipse.jetty.util.URI.charset"); + __CHARSET = charset == null ? StandardCharsets.UTF_8 : Charset.forName(charset); + } + + private URIUtil() + {} + + /* ------------------------------------------------------------ */ + /** Encode a URI path. + * This is the same encoding offered by URLEncoder, except that + * the '/' character is not encoded. + * @param path The path the encode + * @return The encoded path + */ + public static String encodePath(String path) + { + if (path==null || path.length()==0) + return path; + + StringBuilder buf = encodePath(null,path); + return buf==null?path:buf.toString(); + } + + /* ------------------------------------------------------------ */ + /** Encode a URI path. + * @param path The path the encode + * @param buf StringBuilder to encode path into (or null) + * @return The StringBuilder or null if no substitutions required. + */ + public static StringBuilder encodePath(StringBuilder buf, String path) + { + byte[] bytes=null; + if (buf==null) + { + loop: + for (int i=0;i': + case ' ': + buf=new StringBuilder(path.length()*2); + break loop; + default: + if (c>127) + { + bytes=path.getBytes(URIUtil.__CHARSET); + buf=new StringBuilder(path.length()*2); + break loop; + } + + } + } + if (buf==null) + return null; + } + + synchronized(buf) + { + if (bytes!=null) + { + for (int i=0;i': + buf.append("%3E"); + continue; + case ' ': + buf.append("%20"); + continue; + default: + if (c<0) + { + buf.append('%'); + TypeUtil.toHex(c,buf); + } + else + buf.append((char)c); + continue; + } + } + + } + else + { + for (int i=0;i': + buf.append("%3E"); + continue; + case ' ': + buf.append("%20"); + continue; + default: + buf.append(c); + continue; + } + } + } + } + + return buf; + } + + /* ------------------------------------------------------------ */ + /** Encode a URI path. + * @param path The path the encode + * @param buf StringBuilder to encode path into (or null) + * @param encode String of characters to encode. % is always encoded. + * @return The StringBuilder or null if no substitutions required. + */ + public static StringBuilder encodeString(StringBuilder buf, + String path, + String encode) + { + if (buf==null) + { + loop: + for (int i=0;i=0) + { + buf=new StringBuilder(path.length()<<1); + break loop; + } + } + if (buf==null) + return null; + } + + synchronized(buf) + { + for (int i=0;i=0) + { + buf.append('%'); + StringUtil.append(buf,(byte)(0xff&c),16); + } + else + buf.append(c); + } + } + + return buf; + } + + /* ------------------------------------------------------------ */ + /* Decode a URI path and strip parameters + * @param path The path the encode + * @param buf StringBuilder to encode path into + */ + public static String decodePath(String path) + { + if (path==null) + return null; + // Array to hold all converted characters + char[] chars=null; + int n=0; + // Array to hold a sequence of %encodings + byte[] bytes=null; + int b=0; + + int len=path.length(); + + for (int i=0;i0) + { + String s=new String(bytes,0,b,__CHARSET); + s.getChars(0,s.length(),chars,n); + n+=s.length(); + b=0; + } + + chars[n++]=c; + } + + if (chars==null) + return path; + + // if we have a remaining sequence of bytes + if (b>0) + { + String s=new String(bytes,0,b,__CHARSET); + s.getChars(0,s.length(),chars,n); + n+=s.length(); + } + + return new String(chars,0,n); + } + + /* ------------------------------------------------------------ */ + /* Decode a URI path and strip parameters. + * @param path The path the encode + * @param buf StringBuilder to encode path into + */ + public static String decodePath(byte[] buf, int offset, int length) + { + byte[] bytes=null; + int n=0; + + for (int i=0;i=0) + return p.substring(0,slash+1); + return null; + } + + /* ------------------------------------------------------------ */ + /** Convert a path to a cananonical form. + * All instances of "." and ".." are factored out. Null is returned + * if the path tries to .. above its root. + * @param path + * @return path or null. + */ + public static String canonicalPath(String path) + { + if (path==null || path.length()==0) + return path; + + int end=path.length(); + int start = path.lastIndexOf('/', end); + + search: + while (end>0) + { + switch(end-start) + { + case 2: // possible single dot + if (path.charAt(start+1)!='.') + break; + break search; + case 3: // possible double dot + if (path.charAt(start+1)!='.' || path.charAt(start+2)!='.') + break; + break search; + } + + end=start; + start=path.lastIndexOf('/',end-1); + } + + // If we have checked the entire string + if (start>=end) + return path; + + StringBuilder buf = new StringBuilder(path); + int delStart=-1; + int delEnd=-1; + int skip=0; + + while (end>0) + { + switch(end-start) + { + case 2: // possible single dot + if (buf.charAt(start+1)!='.') + { + if (skip>0 && --skip==0) + { + delStart=start>=0?start:0; + if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.') + delStart++; + } + break; + } + + if(start<0 && buf.length()>2 && buf.charAt(1)=='/' && buf.charAt(2)=='/') + break; + + if(delEnd<0) + delEnd=end; + delStart=start; + if (delStart<0 || delStart==0&&buf.charAt(delStart)=='/') + { + delStart++; + if (delEnd=0 && buf.charAt(start)!='/') + start--; + continue; + + case 3: // possible double dot + if (buf.charAt(start+1)!='.' || buf.charAt(start+2)!='.') + { + if (skip>0 && --skip==0) + { delStart=start>=0?start:0; + if(delStart>0 && delEnd==buf.length() && buf.charAt(delEnd-1)=='.') + delStart++; + } + break; + } + + delStart=start; + if (delEnd<0) + delEnd=end; + + skip++; + end=start--; + while (start>=0 && buf.charAt(start)!='/') + start--; + continue; + + default: + if (skip>0 && --skip==0) + { + delStart=start>=0?start:0; + if(delEnd==buf.length() && buf.charAt(delEnd-1)=='.') + delStart++; + } + } + + // Do the delete + if (skip<=0 && delStart>=0 && delEnd>=delStart) + { + buf.delete(delStart,delEnd); + delStart=delEnd=-1; + if (skip>0) + delEnd=end; + } + + end=start--; + while (start>=0 && buf.charAt(start)!='/') + start--; + } + + // Too many .. + if (skip>0) + return null; + + // Do the delete + if (delEnd>=0) + buf.delete(delStart,delEnd); + + return buf.toString(); + } + + /* ------------------------------------------------------------ */ + /** Convert a path to a compact form. + * All instances of "//" and "///" etc. are factored out to single "/" + * @param path + * @return path + */ + public static String compactPath(String path) + { + if (path==null || path.length()==0) + return path; + + int state=0; + int end=path.length(); + int i=0; + + loop: + while (i='a'&&c<='z' || + c>='A'&&c<='Z' || + (i>0 &&(c>='0'&&c<='9' || + c=='.' || + c=='+' || + c=='-')) + )) + break; + } + return false; + } + + public static void appendSchemeHostPort(StringBuilder url,String scheme,String server, int port) + { + if (server.indexOf(':')>=0&&server.charAt(0)!='[') + url.append(scheme).append("://").append('[').append(server).append(']'); + else + url.append(scheme).append("://").append(server); + + if (port > 0 && (("http".equalsIgnoreCase(scheme) && port != 80) || ("https".equalsIgnoreCase(scheme) && port != 443))) + url.append(':').append(port); + } + + public static void appendSchemeHostPort(StringBuffer url,String scheme,String server, int port) + { + synchronized (url) + { + if (server.indexOf(':')>=0&&server.charAt(0)!='[') + url.append(scheme).append("://").append('[').append(server).append(']'); + else + url.append(scheme).append("://").append(server); + + if (port > 0 && (("http".equalsIgnoreCase(scheme) && port != 80) || ("https".equalsIgnoreCase(scheme) && port != 443))) + url.append(':').append(port); + } + } +} + + +