/*************************************************************************************************
Intelligent Escaper-Unescaper by NeoEGM

Copyright (C) 2009 Ezequiel Gastón Miravalles

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 3 of the License, or
(at your option) any later version.

This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
*************************************************************************************************/

/*************************************************************************************************
Software: Intelligent Escaper-Unescaper by NeoEGM
Author: Ezequiel Gastón Miravalles
Website: http://www.neoegm.com/software/intelligent-escaper-unescaper/
License: GNU GPL v3 (read above)

Available functions:
	Escape(str [String], forced [Boolean])
	EscapeURL(str [String], forced [Boolean], forcehost [Boolean])
	IntelligentEscape(str [String])
	IntelligentUnescape(str [String])
	ParseURLParameters(str [String])
	MakeURLWithParameters(str [String])
	EscapeChar(str [String], char [String])

Unwrapped functions:
	unescape(str [String])
	encodeURI(str [String])
	encodeURIComponent(str [String])
	decodeURI(str [String])
	decodeURIComponent(str [String])
	
Available helper functions:
	ForcedEscape(str [String])
	EscapeParameter(str [String], forced [Boolean])
	UnescapeURLSpecialChars(str [String])
	UnescapeHostSpecialChars(str [String])
	ReverseString(str [String])
	LastOccurrenceOfChar(str [String], char [String])
	CharToEncoded(char [String])
*************************************************************************************************/

function ReverseString(str)	//Helper Function
{
	var newstr = "";
	
	for (var i = str.length - 1; i >= 0; i--)
		newstr += str.charAt(i);

	return newstr;
}

function LastOccurrenceOfChar(str, char)	//Helper Function
{
	var found = ReverseString(str).indexOf(char);
	
	if (found != -1)
		return str.length - 1 - found;
	else
		return -1;
}

function CharToEncoded(char)	//Helper Function
{
	var tmpstr = char.charCodeAt(0).toString(16).toUpperCase();
	var newstr = "";
		
	if (tmpstr.length < 2)
		newstr = "%0" + tmpstr;
	else if (tmpstr.length == 2)
		newstr = "%" + tmpstr;
	else
		newstr = "%u" + tmpstr;

	return newstr;
}

function Escape(str, forced)
{
	if (forced == null)
		forced = false;
	
	if (forced)
		return ForcedEscape(str);
	else
		return escape(str);
}

function ForcedEscape(str)
{
	var newstr = "";
	var tmpstr;

	for (var i = 0; i < str.length; i++)
		newstr += CharToEncoded(str.charAt(i));
	
	return newstr;
}

function ParseURLParameters(str)
{
	var anchortext = "";
	var anchorfound = LastOccurrenceOfChar(str, "#");
	
	if (anchorfound != -1)
	{
		anchortext = str.substr(anchorfound);
		str = str.substr(0, anchorfound);
	}
	
	var paramsfound = str.indexOf("?");
	
	if (paramsfound != -1)
		str = str.substr(0, paramsfound) + "\n\n" + str.substr(paramsfound+1);
	
	return unescape(str.replace(/&/g, "\n").replace(/\+/g, " ")) + (anchortext==""?"":"\n\n" + anchortext);
}

function UnescapeURLSpecialChars(str)
{
	str = str.replace(/%2F/g, "/");
	
	return str;
}

function UnescapeHostSpecialChars(str)
{
	str = str.replace(/%2E/g, ".");
	
	var colon = str.indexOf("%3A");		//%3A = :
	
	if (colon != -1)
		str = str.substr(0, colon) + unescape(str.substr(colon));
	
	return str;
}

function EscapeURL(str, forced, forcehost)
{
	if (forced == null)
		forced = false;
		
	if (forcehost == null)
		forcehost = false;
	
	var anchortext = "";
	var anchorfound = LastOccurrenceOfChar(str, "#");
	
	if (anchorfound != -1)
	{
		anchortext = str.substr(anchorfound);
		str = str.substr(0, anchorfound);
	}
	
	var newstr = "";
	var processed = 0;
	
	var protocol = str.indexOf("//");
	
	if (protocol != -1)
	{
		newstr += str.substr(processed, protocol + 2);
		processed += protocol + 2;
	}
	
	var firstslash = str.substr(processed).indexOf("/");
	
	if (firstslash != -1)
	{
		if (forcehost)
			newstr += UnescapeHostSpecialChars(Escape(str.substr(processed, firstslash + 1), true));
		else
			newstr += str.substr(processed, firstslash + 1);

		processed += firstslash + 1;
	}
	
	var paramsbegin = str.substr(processed).indexOf("?");
	
	if (paramsbegin != -1)
	{
		if (firstslash != -1)
		{
			newstr += Escape(str.substr(processed, paramsbegin), forced);
			processed += paramsbegin;
		}
		else
		{
			if (forcehost)
				newstr += UnescapeHostSpecialChars(Escape(str.substr(processed, paramsbegin), true));
			else
				newstr += str.substr(processed, paramsbegin);

			processed += paramsbegin;
		}
		
		newstr += "?";
		
		var params_str = str.substr(processed + 1);
		
		var params = params_str.split("&");
		
		for (var i = 0; i < params.length; i++)
		{
			var param = params[i];
			
			if (i != 0)
				newstr += "&";
			
			newstr += EscapeParameter(param, forced);
		}
	}
	else
		if (firstslash != -1)
			newstr += Escape(str.substr(processed), forced);
		else
		{
			if (forcehost)
				newstr += UnescapeHostSpecialChars(Escape(str.substr(processed), true));
			else
				newstr += str.substr(processed);
		}
	
	if (forced)
		newstr = UnescapeURLSpecialChars(newstr);
	
	return newstr + anchortext;
}

function EscapeParameter(str, forced)
{
	if (forced == null)
		forced = false;

	var equal = str.indexOf("=");
	
	if (equal != -1)
		return Escape(str.substr(0, equal), forced) + "=" + Escape(str.substr(equal+1), forced);
	else
		return Escape(str, forced);
}

function MakeURLWithParameters(str)
{
	var newstr = "";
	
	var lines = str.split("\n");
	var params = 0;
	
	for (var i = 0; i < lines.length; i++)
		if (i == 0)
			newstr += EscapeURL(lines[i]);
		else
		{
			var line = lines[i];
			
			if (line != "")
			{
				if (i == (lines.length-1) && line.charAt(0) == "#")
					newstr += line;
				else
				{
					if (params == 0)
						newstr += "?";
					else
						newstr += "&";
					
					newstr += EscapeParameter(line);
					
					params++;
				}
			}
		}
	
	return newstr;
}

function IntelligentUnescape(str)
{
	var laststr;
	var newstr = str;
	
	do
	{
		laststr = newstr;
		newstr = unescape(newstr);
	} while (laststr != newstr);
	
	return newstr;
}

function IntelligentEscape(str)
{
	return escape(IntelligentUnescape(str));
}

function EscapeChar(str, char)
{
	if (char.length > 0)
	{
		var newstr = "";
		
		var fchar = char.charAt(0);
		var fcharenc = CharToEncoded(fchar);
		
		var tmpchr;
		
		for (var i = 0; i < str.length; i++)
		{
			tmpchr = str.charAt(i);
			
			if (tmpchr != fchar)
				newstr += tmpchr;
			else
				newstr += fcharenc;
		}
		
		return newstr;
	}
	else
		return str;
}

