Tue, 10 Feb 2015 18:12:00 +0100
Import initial revisions of existing project AndroidCaldavSyncAdapater,
forked from upstream repository at 27e8a0f8495c92e0780d450bdf0c7cec77a03a55.
michael@0 | 1 | /** |
michael@0 | 2 | * Copyright (c) 2012, Ben Fortuna |
michael@0 | 3 | * All rights reserved. |
michael@0 | 4 | * |
michael@0 | 5 | * Redistribution and use in source and binary forms, with or without |
michael@0 | 6 | * modification, are permitted provided that the following conditions |
michael@0 | 7 | * are met: |
michael@0 | 8 | * |
michael@0 | 9 | * o Redistributions of source code must retain the above copyright |
michael@0 | 10 | * notice, this list of conditions and the following disclaimer. |
michael@0 | 11 | * |
michael@0 | 12 | * o Redistributions in binary form must reproduce the above copyright |
michael@0 | 13 | * notice, this list of conditions and the following disclaimer in the |
michael@0 | 14 | * documentation and/or other materials provided with the distribution. |
michael@0 | 15 | * |
michael@0 | 16 | * o Neither the name of Ben Fortuna nor the names of any other contributors |
michael@0 | 17 | * may be used to endorse or promote products derived from this software |
michael@0 | 18 | * without specific prior written permission. |
michael@0 | 19 | * |
michael@0 | 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
michael@0 | 24 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
michael@0 | 25 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
michael@0 | 26 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
michael@0 | 27 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
michael@0 | 28 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
michael@0 | 29 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
michael@0 | 30 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 31 | */ |
michael@0 | 32 | package net.fortuna.ical4j.util; |
michael@0 | 33 | |
michael@0 | 34 | import java.net.URI; |
michael@0 | 35 | import java.net.URISyntaxException; |
michael@0 | 36 | import java.util.regex.Pattern; |
michael@0 | 37 | |
michael@0 | 38 | /** |
michael@0 | 39 | * $Id$ |
michael@0 | 40 | * |
michael@0 | 41 | * Created on 11/09/2005 |
michael@0 | 42 | * |
michael@0 | 43 | * Utility methods for working with URIs. |
michael@0 | 44 | * @author Ben Fortuna |
michael@0 | 45 | */ |
michael@0 | 46 | public final class Uris { |
michael@0 | 47 | |
michael@0 | 48 | /** |
michael@0 | 49 | * URI Scheme used when relaxed parsing is enabled and the given input stream lead to an invalid URI. |
michael@0 | 50 | */ |
michael@0 | 51 | public static final String INVALID_SCHEME = "net.fortunal.ical4j.invalid"; |
michael@0 | 52 | |
michael@0 | 53 | private static final Pattern CID_PATTERN = Pattern.compile("(?i)^cid:.*"); |
michael@0 | 54 | private static final Pattern NOTES_CID_REPLACEMENT_PATTERN = Pattern.compile("[<>]"); |
michael@0 | 55 | |
michael@0 | 56 | /** |
michael@0 | 57 | * Constructor made private to enforce static nature. |
michael@0 | 58 | */ |
michael@0 | 59 | private Uris() { |
michael@0 | 60 | } |
michael@0 | 61 | |
michael@0 | 62 | /** |
michael@0 | 63 | * Encodes the specified URI string using the UTF-8 charset. In the event that an exception is thrown, the specifed |
michael@0 | 64 | * URI string is returned unmodified. |
michael@0 | 65 | * @param s a URI string |
michael@0 | 66 | * @return an encoded URI string |
michael@0 | 67 | */ |
michael@0 | 68 | public static String encode(final String s) { |
michael@0 | 69 | /* |
michael@0 | 70 | * try { return URLEncoder.encode(s, ENCODING_CHARSET); } catch (UnsupportedEncodingException use) { |
michael@0 | 71 | * log.error("Error ocurred encoding URI [" + s + "]", use); } |
michael@0 | 72 | */ |
michael@0 | 73 | |
michael@0 | 74 | /* |
michael@0 | 75 | * Lotus Notes does not correctly strip angle brackets from cid uris. From RFC2392: A "cid" URL is converted to |
michael@0 | 76 | * the corresponding Content-ID message header [MIME] by removing the "cid:" prefix, converting the % encoded |
michael@0 | 77 | * character to their equivalent US-ASCII characters, and enclosing the remaining parts with an angle bracket |
michael@0 | 78 | * pair, "<" and ">". For example, "cid:foo4%25foo1@bar.net" corresponds to Content-ID: <foo4%25foo1@bar.net> |
michael@0 | 79 | * Reversing the process and converting URL special characters to their % encodings produces the original cid. A |
michael@0 | 80 | * "mid" URL is converted to a Message-ID or Message-ID/Content-ID pair in a similar fashion. |
michael@0 | 81 | */ |
michael@0 | 82 | if (CompatibilityHints.isHintEnabled(CompatibilityHints.KEY_NOTES_COMPATIBILITY) |
michael@0 | 83 | && CID_PATTERN.matcher(s).matches()) { |
michael@0 | 84 | |
michael@0 | 85 | return NOTES_CID_REPLACEMENT_PATTERN.matcher(s).replaceAll(""); |
michael@0 | 86 | } |
michael@0 | 87 | return s; |
michael@0 | 88 | } |
michael@0 | 89 | |
michael@0 | 90 | /** |
michael@0 | 91 | * Decodes the specified URI string using the UTF-8 charset. In the event that an exception is thrown, the specifed |
michael@0 | 92 | * URI string is returned unmodified. |
michael@0 | 93 | * @param s a URI string |
michael@0 | 94 | * @return an encoded URI string |
michael@0 | 95 | */ |
michael@0 | 96 | public static String decode(final String s) { |
michael@0 | 97 | /* |
michael@0 | 98 | * try { return URLDecoder.decode(s, ENCODING_CHARSET); } catch (UnsupportedEncodingException use) { |
michael@0 | 99 | * log.error("Error ocurred decoding URI [" + s + "]", use); } |
michael@0 | 100 | */ |
michael@0 | 101 | return s; |
michael@0 | 102 | } |
michael@0 | 103 | |
michael@0 | 104 | /** |
michael@0 | 105 | * Attempts to create a URI instance and will optionally swallow any resulting URISyntaxException depending on |
michael@0 | 106 | * configured {@link CompatibilityHints}. Will also automatically attempt encoding of the string representation for |
michael@0 | 107 | * greater compatibility. |
michael@0 | 108 | * <p>When relaxed parsing is enabled and if the string representation is not valid, a second URI creation attempt is made |
michael@0 | 109 | * by extracting the scheme from the scheme specific part and URI encoding that later part. For example, |
michael@0 | 110 | * "mailto: joe smith@example.com" becomes "mailto:joe%20smith@example.com".<p> |
michael@0 | 111 | * <p>If the second attempts also leads to a {@code URISyntaxException}, an opaque URI is constructed with a scheme |
michael@0 | 112 | * of {@code Uris.INVALID_SCHEME} and a value corresponding to the initial representation.</p> |
michael@0 | 113 | * |
michael@0 | 114 | * @param s a string representation of a URI. |
michael@0 | 115 | * @return a URI instance, which may not correspond to the URI string if a valid |
michael@0 | 116 | * URI string is not specified and relaxed parsing is enabled. |
michael@0 | 117 | * @throws URISyntaxException if a valid URI string is not specified and relaxed parsing is disabled |
michael@0 | 118 | */ |
michael@0 | 119 | public static URI create(final String s) throws URISyntaxException { |
michael@0 | 120 | try { |
michael@0 | 121 | return new URI(encode(s)); |
michael@0 | 122 | } |
michael@0 | 123 | catch (URISyntaxException use) { |
michael@0 | 124 | if (CompatibilityHints |
michael@0 | 125 | .isHintEnabled(CompatibilityHints.KEY_RELAXED_PARSING)) { |
michael@0 | 126 | String encoded = encode(s); |
michael@0 | 127 | int index = encoded.indexOf(':'); |
michael@0 | 128 | if (index != -1 && index < encoded.length() -1) { |
michael@0 | 129 | try { |
michael@0 | 130 | return new URI(encoded.substring(0, index), encoded.substring(index + 1), null); |
michael@0 | 131 | } catch (URISyntaxException use2) { |
michael@0 | 132 | } |
michael@0 | 133 | } |
michael@0 | 134 | try { |
michael@0 | 135 | return new URI(INVALID_SCHEME, s, null); |
michael@0 | 136 | } catch (URISyntaxException use2) { |
michael@0 | 137 | // should not happen as we are building an opaque URI |
michael@0 | 138 | throw new IllegalArgumentException("Could not build URI from " + s); |
michael@0 | 139 | } |
michael@0 | 140 | } |
michael@0 | 141 | throw use; |
michael@0 | 142 | } |
michael@0 | 143 | } |
michael@0 | 144 | } |