All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.util.URIUtil Maven / Gradle / Ivy

There is a newer version: 12.0.13
Show newest version
//
//  ========================================================================
//  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.CharsetDecoder;
import java.nio.charset.StandardCharsets;

import org.eclipse.jetty.util.Utf8Appendable.NotUtf8Exception;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;



/* ------------------------------------------------------------ */
/** URI Utility methods.
 * 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 { private static final Logger LOG = Log.getLogger(URIUtil.class); 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=StandardCharsets.UTF_8 ; 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 ' ': case '[': 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; } if (bytes!=null) { for (int i=0;i': buf.append("%3E"); continue; case ' ': buf.append("%20"); continue; case '[': buf.append("%5B"); continue; case ']': buf.append("%5D"); 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; case '[': buf.append("%5B"); continue; case ']': buf.append("%5D"); 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 */ public static String decodePath(String path) { return decodePath(path,0,path.length()); } /* ------------------------------------------------------------ */ /* Decode a URI path and strip parameters of UTF-8 path */ public static String decodePath(String path, int offset, int length) { try { Utf8StringBuilder builder=null; int end=offset+length; for (int i=offset;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; } /* ------------------------------------------------------------ */ /** * Create a new URI from the arguments, handling IPv6 host encoding and default ports * @param scheme * @param server * @param port * @param path * @param query * @return A String URI */ public static String newURI(String scheme,String server, int port,String path,String query) { StringBuilder builder = newURIBuilder(scheme, server, port); builder.append(path); if (query!=null && query.length()>0) builder.append('?').append(query); return builder.toString(); } /* ------------------------------------------------------------ */ /** * Create a new URI StringBuilder from the arguments, handling IPv6 host encoding and default ports * @param scheme * @param server * @param port * @return a StringBuilder containing URI prefix */ public static StringBuilder newURIBuilder(String scheme,String server, int port) { StringBuilder builder = new StringBuilder(); appendSchemeHostPort(builder, scheme, server, port); return builder; } /* ------------------------------------------------------------ */ /** * Append scheme, host and port URI prefix, handling IPv6 address encoding and default ports

* @param url StringBuilder to append to * @param scheme * @param server * @param port */ 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) { switch(scheme) { case "http": if (port!=80) url.append(':').append(port); break; case "https": if (port!=443) url.append(':').append(port); break; default: url.append(':').append(port); } } } /* ------------------------------------------------------------ */ /** * Append scheme, host and port URI prefix, handling IPv6 address encoding and default ports

* @param url StringBuffer to append to * @param scheme * @param server * @param 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) { switch(scheme) { case "http": if (port!=80) url.append(':').append(port); break; case "https": if (port!=443) url.append(':').append(port); break; default: url.append(':').append(port); } } } } public static boolean equalsIgnoreEncodings(String uriA, String uriB) { int lenA=uriA.length(); int lenB=uriB.length(); int a=0; int b=0; while (a




© 2015 - 2024 Weber Informatics LLC | Privacy Policy