/***************************************************************************
    Copyright          : (C) 2002 by Neoworks Limited. All rights reserved
    URL                : http://www.neoworks.com
 ***************************************************************************/
/***************************************************************************
 *                                                                         *
 *   This program 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 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

package com.neoworks.util;

import org.apache.log4j.Category;

/**
 * Escaper contains methods to escape text and sql.
 *
 * @author Nigel Atkinson <a href="mailto:nigel@neoworks.com">nigel@neoworks.com</a>
 * @version 0.1
 */
public class Escaper
{
	/**
	 * Private constructor to prevent construction
	 */
	private Escaper()
	{
	}
	
	/**
	 * lookup table for special characters
	 */
	static boolean[] specialChars;
	
	/**
	 * create look-up table for ASCII characters that need special treatment
	 */
	static
	{
		specialChars = new boolean[128];
		for (int i=0; i<128; i++) specialChars[i] = false;
		specialChars['<'] = true;
		specialChars['>'] = true;
		specialChars['&'] = true;
		specialChars['\''] = true;
		specialChars['\"'] = true;
	}
	
	/**
	 * Escape special characters for display.
	 * @return The XML/HTML representation of the string<br>
	 * This static method converts a Unicode string to a string containing
	 * only ASCII characters, in which non-ASCII characters are represented
	 * by the usual XML/HTML escape conventions (for example, "&lt;" becomes "&amp;lt;").
	 * Note: if the input consists solely of ASCII or Latin-1 characters,
	 * the output will be equally valid in XML and HTML. Otherwise it will be valid
	 * only in XML.
	 * The escaped characters are written to the dest array starting at position 0; the
	 * number of positions used is returned as the result
	 * @param out The output array
	 * @param ch The character array containing the string
	 * @param start The start position of the input string within the character array
	 * @param length The length of the input string within the character array
	 */
	private static int XMLEscape(char ch[], int start, int length, char[] out)
	{
		// Use a character array for performance reasons;
		// allocate size on the basis that it might be all non-ASCII
		
		//char[] out = new char[length*8]; // allow for worst case
		int o = 0;
		for (int i = start; i < start+length; i++)
		{
			if (ch[i]<=0x7f && !specialChars[ch[i]])
			{
				out[o]=ch[i];
				o++;
			} 
			else
			{
				if (ch[i]=='<')
				{
					("&lt;").getChars(0,4,out,o); o+=4;
				}
				else if (ch[i]=='>')
				{
					("&gt;").getChars(0,4,out,o); o+=4;
				}
				else if (ch[i]=='&') {("&amp;").getChars(0,5,out,o); o+=5;}
				else if (ch[i]=='\"') {("&quot;").getChars(0,6,out,o); o+=6;}
				else if (ch[i]=='\'') {("&apos;").getChars(0,6,out,o); o+=6;}
				else
				{
					String dec = "&#" + Integer.toString((int)ch[i]) + ';';
					dec.getChars(0, dec.length(), out, o);
					o+=dec.length();
				}
			}
		}
		return o;
	}
	
	/**
	 * Escape special characters in a String value.
	 * @param in The input string
	 * @return The XML representation of the string<br>
	 * This static method converts a Unicode string to a string containing
	 * only ASCII characters, in which non-ASCII characters are represented
	 * by the usual XML/HTML escape conventions (for example, "&lt;" becomes
	 * "&amp;lt;").<br>
	 * Note: if the input consists solely of ASCII or Latin-1 characters,
	 * the output will be equally valid in XML and HTML. Otherwise it will be valid
	 * only in XML.
	 */
	public static String XMLEscape(String in)
	{
		char[] dest = new char[in.length()*8];
		int newlen = XMLEscape( in.toCharArray(), 0, in.length(), dest);
		return new String(dest, 0, newlen);
	}
	
	/**
	 * Convert a string so it can be included in an SQL statement,
	 * by replacing each apostrophe with a pair of apostrophes
	 * @param s The string to escape
	 * @return The escaped string
	 */
	public static String SQLEscape ( String s )
	{
		if (s == null)
		{
			return null;
		}
		
		s = s.replace('\n', ' ').trim();
		
		if (s.indexOf("\'")==-1) 
		{
			return s;
		}
		
		StringBuffer b = new StringBuffer(s.length()+10);
		int i = 0;
		int j;
		while ((j=s.indexOf("\'", i)) >= 0)
		{
			b.append(s.substring(i, j));
			b.append("\'\'");
			i=j+1;
		}
		
		b.append(s.substring(i));
		return b.toString();
	}

	/**
	 * Escape a String (replace " with \")
	 *
	 * @param in The String to escape
	 * @return The escaped String
	 */
	public static String stringEscape(String in)
	{
		return in.replaceAll("\"","\\\"");
	}
}
