/* URLEncoder.java -- Class to convert strings to a properly encoded URL
   Copyright (C) 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package java.net;

import gnu.java.lang.CPStringBuilder;

import java.io.UnsupportedEncodingException;


/*
 * Written using on-line Java Platform 1.2/1.4 API Specification, as well
 * as "The Java Class Libraries", 2nd edition (Addison-Wesley, 1998).
 * Status:  Believed complete and correct.
 */

/**
 * This utility class contains static methods that converts a
 * string into a fully encoded URL string in x-www-form-urlencoded
 * format.  This format replaces certain disallowed characters with
 * encoded equivalents.  All upper case and lower case letters in the
 * US alphabet remain as is, the space character (' ') is replaced with
 * '+' sign, and all other characters are converted to a "%XX" format
 * where XX is the hexadecimal representation of that character in a
 * certain encoding (by default, the platform encoding, though the
 * standard is "UTF-8").
 * <p>
 * This method is very useful for encoding strings to be sent to CGI scripts
 *
 * @author Aaron M. Renn (arenn@urbanophile.com)
 * @author Warren Levy (warrenl@cygnus.com)
 * @author Mark Wielaard (mark@klomp.org)
 */
public class URLEncoder
{
  /**
   * This method translates the passed in string into x-www-form-urlencoded
   * format using the default encoding.  The standard encoding is
   * "UTF-8", and the two-argument form of this method should be used
   * instead.
   *
   * @param s The String to convert
   *
   * @return The converted String
   *
   * @deprecated
   */
  public static String encode(String s)
  {
    try
      {
        // We default to 8859_1 for compatibility with the same
        // default elsewhere in the library.
        return encode(s, System.getProperty("file.encoding", "8859_1"));
      }
    catch (UnsupportedEncodingException uee)
      {
        // Should never happen since default should always be supported
        return s;
      }
  }

  /**
   * This method translates the passed in string into x-www-form-urlencoded
   * format using the character encoding to hex-encode the unsafe characters.
   *
   * @param s The String to convert
   * @param encoding The encoding to use for unsafe characters
   *
   * @return The converted String
   *
   * @exception UnsupportedEncodingException If the named encoding is not
   * supported
   *
   * @since 1.4
   */
  public static String encode(String s, String encoding)
    throws UnsupportedEncodingException
  {
    int length = s.length();
    int start = 0;
    int i = 0;

    CPStringBuilder result = new CPStringBuilder(length);
    while (true)
      {
        while (i < length && isSafe(s.charAt(i)))
          i++;

        // Safe character can just be added
        result.append(s.substring(start, i));

        // Are we done?
        if (i >= length)
          return result.toString();
        else if (s.charAt(i) == ' ')
          {
            result.append('+'); // Replace space char with plus symbol.
            i++;
          }
        else
          {
            // Get all unsafe characters
            start = i;
            char c;
            while (i < length && (c = s.charAt(i)) != ' ' && ! isSafe(c))
              i++;

            // Convert them to %XY encoded strings
            String unsafe = s.substring(start, i);
            byte[] bytes = unsafe.getBytes(encoding);
            for (int j = 0; j < bytes.length; j++)
              {
                result.append('%');
                int val = bytes[j];
                result.append(hex.charAt((val & 0xf0) >> 4));
                result.append(hex.charAt(val & 0x0f));
              }
          }
        start = i;
      }
  }

  /**
   * Private static method that returns true if the given char is either
   * a uppercase or lowercase letter from 'a' till 'z', or a digit froim
   * '0' till '9', or one of the characters '-', '_', '.' or '*'. Such
   * 'safe' character don't have to be url encoded.
   */
  private static boolean isSafe(char c)
  {
    return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
           || (c >= '0' && c <= '9') || c == '-' || c == '_' || c == '.'
           || c == '*');
  }

  /**
   * Private constructor that does nothing. Included to avoid a default
   * public constructor being created by the compiler.
   */
  private URLEncoder()
  {
  }

  /**
   * Used to convert to hex.  We don't use Integer.toHexString, since
   * it converts to lower case (and the Sun docs pretty clearly
   * specify upper case here), and because it doesn't provide a
   * leading 0.
   */
  private static final String hex = "0123456789ABCDEF";
}
