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

com.phloc.css.utils.CSSURLHelper Maven / Gradle / Ivy

There is a newer version: 3.7.7
Show newest version
/**
 * Copyright (C) 2006-2014 phloc systems
 * http://www.phloc.com
 * office[at]phloc[dot]com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phloc.css.utils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.concurrent.Immutable;

import com.phloc.commons.annotations.Nonempty;
import com.phloc.commons.annotations.PresentForCodeCoverage;
import com.phloc.commons.string.StringHelper;
import com.phloc.commons.url.ISimpleURL;
import com.phloc.css.parser.ParseUtils;
import com.phloc.css.propertyvalue.CCSSValue;

/**
 * Provides URL handling sanity methods.
 * 
 * @author Philip Helger
 */
@Immutable
public final class CSSURLHelper
{
  /** For compatibility reasons, this is set to false */
  public static final boolean DEFAULT_QUOTE_URLS = false;

  @SuppressWarnings ("unused")
  @PresentForCodeCoverage
  private static final CSSURLHelper s_aInstance = new CSSURLHelper ();

  private CSSURLHelper ()
  {}

  /**
   * Check if the passed CSS value is an URL value. This is either a URL
   * starting with "url(" or it is the string "none".
   * 
   * @param sValue
   *        The value to be checked.
   * @return true if the passed value starts with "url(" and ends
   *         with ")" - false otherwise.
   */
  public static boolean isURLValue (@Nullable final String sValue)
  {
    final String sRealValue = StringHelper.trim (sValue);
    if (StringHelper.hasNoText (sRealValue))
      return false;

    if (sRealValue.equals (CCSSValue.NONE))
      return true;

    // 5 = "url(".length () + ")".length
    return sRealValue.length () > 5 &&
           sRealValue.startsWith (CCSSValue.PREFIX_URL_OPEN) &&
           sRealValue.endsWith (CCSSValue.SUFFIX_URL_CLOSE);
  }

  /**
   * Extract the real URL contained in a CSS URL value.
   * 
   * @param sValue
   *        The value containing the CSS value
   * @return null if the passed value is not an URL value
   * @see #isURLValue
   */
  @Nullable
  public static String getURLValue (@Nullable final String sValue)
  {
    if (isURLValue (sValue))
    {
      return ParseUtils.trimUrl (sValue);
    }
    return null;
  }

  /**
   * Surround the passed URL with the CSS "url(...)"
   * 
   * @param aURL
   *        URL to be wrapped. May not be null.
   * @param bQuoteURL
   *        if true single quotes are added around the URL
   * @return url(sURL) or url('sURL')
   */
  @Nonnull
  @Nonempty
  public static String getAsCSSURL (@Nonnull final ISimpleURL aURL, final boolean bQuoteURL)
  {
    if (aURL == null)
      throw new NullPointerException ("URL");
    return getAsCSSURL (aURL.getAsString (), bQuoteURL);
  }

  /**
   * Check if the passed character is a valid character inside a URL. Characters
   * for which this method returns false must be escaped!
   * 
   * @param c
   *        The character to be checked.
   * @return true if the passed character can be directly contained
   *         inside a URL, false otherwise if the character needs
   *         to be escaped.
   */
  public static boolean isValidCSSURLChar (final char c)
  {
    return c == '!' ||
           c == '#' ||
           c == '$' ||
           c == '%' ||
           c == '&' ||
           (c >= '*' && c <= '[') ||
           (c >= ']' && c <= '~') ||
           (c >= '\u0080' && c <= '\uffff');
  }

  /**
   * Check if any character inside the passed URL needs escaping.
   * 
   * @param sURL
   *        The URL to be checked. May not be null.
   * @return true if any of the contained characters needs
   *         escaping, false if the URL can be used as is.
   */
  public static boolean isCSSURLRequiringQuotes (@Nonnull final String sURL)
  {
    if (sURL == null)
      throw new NullPointerException ("passed URL is null!");

    for (final char c : sURL.toCharArray ())
      if (!isValidCSSURLChar (c))
        return true;
    return false;
  }

  /**
   * Internal method to escape a CSS URL. Because this method is only called for
   * quoted URLs, only the quote character itself needs to be quoted.
   * 
   * @param sURL
   *        The URL to be escaped. May not be null.
   * @param cQuoteChar
   *        The quote char that is used. Either '\'' or '"'
   * @return The escaped string. Never null.
   */
  @Nonnull
  @Nonempty
  public static String getEscapedCSSURL (@Nonnull final String sURL, final char cQuoteChar)
  {
    if (sURL == null)
      throw new NullPointerException ("URL");

    if (sURL.indexOf (cQuoteChar) < 0 && sURL.indexOf (ParseUtils.URL_ESCAPE_CHAR) < 0)
    {
      // Found nothing to quote
      return sURL;
    }

    final StringBuilder aSB = new StringBuilder (sURL.length () * 2);
    for (final char c : sURL.toCharArray ())
    {
      // Escape the quote char and the escape char itself
      if (c == cQuoteChar || c == ParseUtils.URL_ESCAPE_CHAR)
        aSB.append (ParseUtils.URL_ESCAPE_CHAR);
      aSB.append (c);
    }
    return aSB.toString ();
  }

  /**
   * Surround the passed URL with the CSS "url(...)". When the passed URL
   * contains characters that require quoting, quotes are automatically added!
   * 
   * @param sURL
   *        URL to be wrapped. May neither be null nor empty.
   * @param bForceQuoteURL
   *        if true single quotes are added around the URL
   * @return url(sURL) or url('sURL')
   */
  @Nonnull
  @Nonempty
  public static String getAsCSSURL (@Nonnull @Nonempty final String sURL, final boolean bForceQuoteURL)
  {
    if (StringHelper.hasNoText (sURL))
      throw new IllegalArgumentException ("passed URL is empty!");

    final StringBuilder aSB = new StringBuilder (CCSSValue.PREFIX_URL_OPEN);
    final boolean bAreQuotesRequired = bForceQuoteURL || isCSSURLRequiringQuotes (sURL);
    if (bAreQuotesRequired)
    {
      // Determine the best quote char to use - default to '\'' for backwards
      // compatibility
      final int nIndexSingleQuote = sURL.indexOf ('\'');
      final int nIndexDoubleQuote = sURL.indexOf ('"');
      final char cQuote = nIndexSingleQuote >= 0 && nIndexDoubleQuote < 0 ? '"' : '\'';
      // Append the quoted and escaped URL
      aSB.append (cQuote).append (getEscapedCSSURL (sURL, cQuote)).append (cQuote);
    }
    else
    {
      // No quotes needed
      aSB.append (sURL);
    }
    return aSB.append (CCSSValue.SUFFIX_URL_CLOSE).toString ();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy