| /******************************************************************************* |
| * Copyright (c) 2000, 2008 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * James D Miles (IBM Corp.) - bug 191368, Policy URL doesn't support UTF-8 characters |
| *******************************************************************************/ |
| package org.eclipse.update.internal.core; |
| |
| |
| import java.io.UnsupportedEncodingException; |
| import java.net.MalformedURLException; |
| import java.net.URL; |
| import java.net.URLDecoder; |
| import java.util.StringTokenizer; |
| |
| import org.eclipse.core.runtime.Assert; |
| /** |
| * Encodes a <code>URL</code> into an <code>ASCII</code> readable |
| * <code>URL</code> that is safe for transport. Encoded |
| * <code>URL</code>s can be decoded using the <code>URLDecoder</code>. |
| * |
| * @see URLDecoder |
| */ |
| public final class URLEncoder { |
| /** |
| * Prevents instances from being created. |
| */ |
| private URLEncoder() { |
| } |
| /** |
| * Encodes the given file and reference parts of a <code>URL</code> into |
| * an <code>ASCII</code> readable <code>String</code> that is safe for |
| * transport. Returns the result. |
| * |
| * @return the result of encoding the given file and reference parts of |
| * a <code>URL</code> into an <code>ASCII</code> readable |
| * <code>String</code> that is safe for transport |
| */ |
| public static String encode(String file, String query, String ref) { |
| StringBuffer buf = new StringBuffer(); |
| StringTokenizer tokenizer = new StringTokenizer(file, "/", true); //$NON-NLS-1$ |
| |
| while (tokenizer.hasMoreTokens()) { |
| String token = tokenizer.nextToken(); |
| if (token.equals("/")) { //$NON-NLS-1$ |
| buf.append(token); |
| } else { |
| buf.append(encodeSegment(token)); |
| } |
| } |
| |
| if (query != null){ |
| buf.append('?'); |
| buf.append(query); |
| } |
| |
| if (ref != null) { |
| buf.append('#'); |
| buf.append(encodeSegment(ref)); |
| } |
| |
| return buf.toString(); |
| } |
| /** |
| * Encodes the given <code>URL</code> into an <code>ASCII</code> |
| * readable <code>URL</code> that is safe for transport. Returns the |
| * result. |
| * |
| * @return the result of encoding the given <code>URL</code> into an |
| * <code>ASCII</code> readable <code>URL</code> that is safe for |
| * transport |
| */ |
| public static URL encode(URL url) throws MalformedURLException { |
| // encode the path not the file as the URL may contain a query |
| String file = url.getPath(); |
| String query = url.getQuery(); |
| String ref = url.getRef(); |
| String auth = url.getAuthority(); |
| String host = url.getHost(); |
| int port = url.getPort(); |
| String userinfo = url.getUserInfo(); |
| |
| // do not encode if there is an authority, such as in |
| // ftp://user:password@host:port/path |
| // because the URL constructor does not allow it |
| URL result = url; |
| if (auth == null || auth.equals("") || userinfo == null) // $NON-NLS-1$ $NON-NLS-2$ //$NON-NLS-1$ |
| result = new URL(url.getProtocol(), host, port, encode(file, query, ref)); |
| return result; |
| } |
| private static String encodeSegment(String segment) { |
| |
| // if we find a '%' in the string, consider the URL to be already encoded |
| if (segment.indexOf('%')!=-1) return segment; |
| |
| StringBuffer result = new StringBuffer(segment.length()); |
| |
| for (int i = 0; i < segment.length(); ++i) { |
| char c = segment.charAt(i); |
| if (mustEncode(c)) { |
| byte[] bytes = null; |
| try { |
| bytes = new Character(c).toString().getBytes("UTF8"); //$NON-NLS-1$ |
| } catch (UnsupportedEncodingException e) { |
| Assert.isTrue(false, e.getMessage()); |
| } |
| for (int j = 0; j < bytes.length; ++j) { |
| result.append('%'); |
| result.append(Integer.toHexString((bytes[j] >> 4) & 0x0F)); |
| result.append(Integer.toHexString(bytes[j] & 0x0F)); |
| } |
| } else { |
| result.append(c); |
| } |
| } |
| |
| return result.toString(); |
| } |
| |
| private static boolean mustEncode(char c) { |
| if (c >= 'a' && c <= 'z') { |
| return false; |
| } |
| |
| if (c >= 'A' && c <= 'Z') { |
| return false; |
| } |
| |
| if (c >= '0' && c <= '9') { |
| return false; |
| } |
| |
| if (c >= '\'' && c <= '.') { |
| return false; |
| } |
| |
| if (c == '!' || c == '$' || c == '_' || c == '[' || c == ']') { |
| return false; |
| } |
| |
| // needed otherwise file:///c:/file/ becomes file:///C%3a/file/ |
| if (c ==':'){ |
| return false; |
| } |
| return true; |
| } |
| } |