/**
 * OWASP Enterprise Security API (ESAPI)
 *
 * This file is part of the Open Web Application Security Project (OWASP)
 * Enterprise Security API (ESAPI) project. For details, please see
 * <a href="http://www.owasp.org/index.php/ESAPI">http://www.owasp.org/index.php/ESAPI</a>.
 *
 * Copyright (c) 2007 - The OWASP Foundation
 *
 * The ESAPI is published by OWASP under the BSD license. You should read and accept the
 * LICENSE before you use, modify, and/or redistribute this software.
 *
 * @author Jeff Williams <a href="http://www.aspectsecurity.com">Aspect Security</a>
 * @created 2007
 */
package org.owasp.esapi.reference;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

import org.owasp.esapi.*;
import org.owasp.esapi.errors.ValidationException;
import org.owasp.esapi.filters.SecurityWrapperRequest;
import org.owasp.esapi.http.MockHttpServletRequest;
import org.owasp.esapi.http.MockHttpServletResponse;
import org.owasp.esapi.reference.validation.HTMLValidationRule;
import org.owasp.esapi.reference.validation.StringValidationRule;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;

/**
 * The Class ValidatorTest.
 *
 * @author Mike Fauzy (mike.fauzy@aspectsecurity.com)
 * @author Jeff Williams (jeff.williams@aspectsecurity.com)
 */
public class ValidatorTest extends TestCase {

    private static final String PREFERRED_ENCODING = "UTF-8";

    public static Test suite() {
        return new TestSuite(ValidatorTest.class);
    }

    /**
     * Instantiates a new HTTP utilities test.
     *
     * @param testName the test name
     */
    public ValidatorTest(String testName) {
        super(testName);
    }

    /**
     * {@inheritDoc}
     *
     * @throws Exception
     */
    protected void setUp() throws Exception {
        // none
    }

    /**
     * {@inheritDoc}
     *
     * @throws Exception
     */
    protected void tearDown() throws Exception {
        // none
    }

    public void testAddRule() {
        Validator validator = ESAPI.validator();
        ValidationRule rule = new StringValidationRule("ridiculous");
        validator.addRule(rule);
        assertEquals(rule, validator.getRule("ridiculous"));
    }

    public void testAssertValidFileUpload() {
        //		assertValidFileUpload(String, String, String, byte[], int, boolean, ValidationErrorList)
    }

    public void testGetPrintable1() {
        //		getValidPrintable(String, char[], int, boolean, ValidationErrorList)
    }

    public void testGetPrintable2() {
        //		getValidPrintable(String, String, int, boolean, ValidationErrorList)
    }

    public void testGetRule() {
        Validator validator = ESAPI.validator();
        ValidationRule rule = new StringValidationRule("rule");
        validator.addRule(rule);
        assertEquals(rule, validator.getRule("rule"));
        assertFalse(rule == validator.getRule("ridiculous"));
    }

    public void testGetValidCreditCard() {
        System.out.println("getValidCreditCard");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();

        assertTrue(instance.isValidCreditCard("cctest1", "1234 9876 0000 0008", false));
        assertTrue(instance.isValidCreditCard("cctest2", "1234987600000008", false));
        assertFalse(instance.isValidCreditCard("cctest3", "12349876000000081", false));
        assertFalse(instance.isValidCreditCard("cctest4", "4417 1234 5678 9112", false));

        instance.getValidCreditCard("cctest5", "1234 9876 0000 0008", false, errors);
        assertEquals(0, errors.size());
        instance.getValidCreditCard("cctest6", "1234987600000008", false, errors);
        assertEquals(0, errors.size());
        instance.getValidCreditCard("cctest7", "12349876000000081", false, errors);
        assertEquals(1, errors.size());
        instance.getValidCreditCard("cctest8", "4417 1234 5678 9112", false, errors);
        assertEquals(2, errors.size());

        assertTrue(instance.isValidCreditCard("cctest1", "1234 9876 0000 0008", false, errors));
        assertTrue(errors.size()==2);
        assertTrue(instance.isValidCreditCard("cctest2", "1234987600000008", false, errors));
        assertTrue(errors.size()==2);
        assertFalse(instance.isValidCreditCard("cctest3", "12349876000000081", false, errors));
        assertTrue(errors.size()==3);
        assertFalse(instance.isValidCreditCard("cctest4", "4417 1234 5678 9112", false, errors));
        assertTrue(errors.size()==4);
    }

    public void testGetValidDate() throws Exception {
    	System.out.println("getValidDate");
    	Validator instance = ESAPI.validator();
    	ValidationErrorList errors = new ValidationErrorList();
    	assertTrue(instance.getValidDate("datetest1", "June 23, 1967", DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.US), false) != null);
    	instance.getValidDate("datetest2", "freakshow", DateFormat.getDateInstance(), false, errors);
    	assertEquals(1, errors.size());

    	// TODO: This test case fails due to an apparent bug in SimpleDateFormat
    	// Note: This seems to be fixed in JDK 6. Will leave it commented out since
    	//		 we only require JDK 5. -kww
    	instance.getValidDate("test", "June 32, 2008", DateFormat.getDateInstance(), false, errors);
    	// assertEquals( 2, errors.size() );
    }
    
    // FIXME: Should probably use SecurityConfigurationWrapper and force
    //		  Validator.AcceptLenientDates to be false.
    public void testLenientDate() {
    	System.out.println("testLenientDate");
    	boolean acceptLenientDates = ESAPI.securityConfiguration().getLenientDatesAccepted();
    	if ( acceptLenientDates ) {
    		assertTrue("Lenient date test skipped because Validator.AcceptLenientDates set to true", true);
    		return;
    	}

    	Date lenientDateTest = null;
    	try {
    		// lenientDateTest will be null when Validator.AcceptLenientDates
    		// is set to false (the default).
    		Validator instance = ESAPI.validator();
    		lenientDateTest = instance.getValidDate("datatest3-lenient", "15/2/2009 11:83:00",
    				                                DateFormat.getDateInstance(DateFormat.SHORT, Locale.US),
    				                                false);
    		fail("Failed to throw expected ValidationException when Validator.AcceptLenientDates set to false.");
    	} catch (ValidationException ve) {
    		assertNull( lenientDateTest );
    		Throwable cause = ve.getCause();
    		assertTrue( cause.getClass().getName().equals("java.text.ParseException") );
    	} catch (Exception e) {
    		fail("Caught unexpected exception: " + e.getClass().getName() + "; msg: " + e);
    	}
    }

    public void testGetValidDirectoryPath() throws Exception {
        System.out.println("getValidDirectoryPath");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        // find a directory that exists
        File parent = new File("/");
        String path = ESAPI.securityConfiguration().getResourceFile("ESAPI.properties").getParentFile().getCanonicalPath();
        instance.getValidDirectoryPath("dirtest1", path, parent, true, errors);
        assertEquals(0, errors.size());
        instance.getValidDirectoryPath("dirtest2", null, parent, false, errors);
        assertEquals(1, errors.size());
        instance.getValidDirectoryPath("dirtest3", "ridicul%00ous", parent, false, errors);
        assertEquals(2, errors.size());
    }

    public void testGetValidDouble() {
        System.out.println("getValidDouble");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        instance.getValidDouble("dtest1", "1.0", 0, 20, true, errors);
        assertEquals(0, errors.size());
        instance.getValidDouble("dtest2", null, 0, 20, true, errors);
        assertEquals(0, errors.size());
        instance.getValidDouble("dtest3", null, 0, 20, false, errors);
        assertEquals(1, errors.size());
        instance.getValidDouble("dtest4", "ridiculous", 0, 20, true, errors);
        assertEquals(2, errors.size());
        instance.getValidDouble("dtest5", "" + (Double.MAX_VALUE), 0, 20, true, errors);
        assertEquals(3, errors.size());
        instance.getValidDouble("dtest6", "" + (Double.MAX_VALUE + .00001), 0, 20, true, errors);
        assertEquals(4, errors.size());
    }

    public void testGetValidFileContent() {
        System.out.println("getValidFileContent");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        byte[] bytes = null;
        try {
            bytes = "12345".getBytes(PREFERRED_ENCODING);
        }
        catch (UnsupportedEncodingException e) {
            fail(PREFERRED_ENCODING + " not a supported encoding?!?!!");
        }
        instance.getValidFileContent("test", bytes, 5, true, errors);
        assertEquals(0, errors.size());
        instance.getValidFileContent("test", bytes, 4, true, errors);
        assertEquals(1, errors.size());
    }

    public void testGetValidFileName() throws Exception {
        System.out.println("getValidFileName");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        String testName = "aspe%20ct.jar";
        assertEquals("Percent encoding is not changed", testName, instance.getValidFileName("test", testName, ESAPI.securityConfiguration().getAllowedFileExtensions(), false, errors));
    }

    public void testGetValidInput() {
        System.out.println("getValidInput");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        // instance.getValidInput(String, String, String, int, boolean, ValidationErrorList)
    }

    public void testGetValidInteger() {
        System.out.println("getValidInteger");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        // instance.getValidInteger(String, String, int, int, boolean, ValidationErrorList)
    }

    public void testGetValidListItem() {
        System.out.println("getValidListItem");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        // instance.getValidListItem(String, String, List, ValidationErrorList)
    }

    public void testGetValidNumber() {
        System.out.println("getValidNumber");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        // instance.getValidNumber(String, String, long, long, boolean, ValidationErrorList)
    }

    public void testGetValidRedirectLocation() {
        System.out.println("getValidRedirectLocation");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        // instance.getValidRedirectLocation(String, String, boolean, ValidationErrorList)
    }

    public void testGetValidSafeHTML() throws Exception {
        System.out.println("getValidSafeHTML");
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();

        // new school test case setup
        HTMLValidationRule rule = new HTMLValidationRule("test");
        ESAPI.validator().addRule(rule);

        assertEquals("Test.", ESAPI.validator().getRule("test").getValid("test", "Test. <script>alert(document.cookie)</script>"));

        String test1 = "<b>Jeff</b>";
        String result1 = instance.getValidSafeHTML("test", test1, 100, false, errors);
        assertEquals(test1, result1);

        String test2 = "<a href=\"http://www.aspectsecurity.com\">Aspect Security</a>";
        String result2 = instance.getValidSafeHTML("test", test2, 100, false, errors);
        assertEquals(test2, result2);

        String test3 = "Test. <script>alert(document.cookie)</script>";
        assertEquals("Test.", rule.getSafe("test", test3));

        assertEquals("Test. &lt;<div>load=alert()</div>", rule.getSafe("test", "Test. <<div on<script></script>load=alert()"));
        assertEquals("Test. <div>b</div>", rule.getSafe("test", "Test. <div style={xss:expression(xss)}>b</div>"));
        assertEquals("Test.", rule.getSafe("test", "Test. <s%00cript>alert(document.cookie)</script>"));
        assertEquals("Test. alert(document.cookie)", rule.getSafe("test", "Test. <s\tcript>alert(document.cookie)</script>"));
        assertEquals("Test. alert(document.cookie)", rule.getSafe("test", "Test. <s\tcript>alert(document.cookie)</script>"));
        // TODO: ENHANCE waiting for a way to validate text headed for an attribute for scripts
        // This would be nice to catch, but just looks like text to AntiSamy
        // assertFalse(instance.isValidSafeHTML("test", "\" onload=\"alert(document.cookie)\" "));
        // String result4 = instance.getValidSafeHTML("test", test4);
        // assertEquals("", result4);
    }

    public void testIsInvalidFilename() {
        System.out.println("testIsInvalidFilename");
        Validator instance = ESAPI.validator();
        char invalidChars[] = "/\\:*?\"<>|".toCharArray();
        for (int i = 0; i < invalidChars.length; i++) {
            assertFalse(invalidChars[i] + " is an invalid character for a filename",
                    instance.isValidFileName("test", "as" + invalidChars[i] + "pect.jar", false));
        }
        assertFalse("Files must have an extension", instance.isValidFileName("test", "", false));
        assertFalse("Files must have a valid extension", instance.isValidFileName("test.invalidExtension", "", false));
        assertFalse("Filennames cannot be the empty string", instance.isValidFileName("test", "", false));
    }

    public void testIsValidDate() {
        System.out.println("isValidDate");
        Validator instance = ESAPI.validator();
        DateFormat format = SimpleDateFormat.getDateInstance();
        assertTrue(instance.isValidDate("datetest1", "September 11, 2001", format, true));
        assertFalse(instance.isValidDate("datetest2", null, format, false));
        assertFalse(instance.isValidDate("datetest3", "", format, false));

        ValidationErrorList errors = new ValidationErrorList();
        assertTrue(instance.isValidDate("datetest1", "September 11, 2001", format, true, errors));
        assertTrue(errors.size()==0);
        assertFalse(instance.isValidDate("datetest2", null, format, false, errors));
        assertTrue(errors.size()==1);
        assertFalse(instance.isValidDate("datetest3", "", format, false, errors));
        assertTrue(errors.size()==2);

    }

    public void testIsValidDirectoryPath() throws IOException {
        System.out.println("isValidDirectoryPath");

        // get an encoder with a special list of codecs and make a validator out of it
        List list = new ArrayList();
        list.add("HTMLEntityCodec");
        Encoder encoder = new DefaultEncoder(list);
        Validator instance = new DefaultValidator(encoder);

        boolean isWindows = (System.getProperty("os.name").indexOf("Windows") != -1) ? true : false;
        File parent = new File("/");

        ValidationErrorList errors = new ValidationErrorList();

        if (isWindows) {
            String sysRoot = new File(System.getenv("SystemRoot")).getCanonicalPath();
            // Windows paths that don't exist and thus should fail
            assertFalse(instance.isValidDirectoryPath("test", "c:\\ridiculous", parent, false));
            assertFalse(instance.isValidDirectoryPath("test", "c:\\jeff", parent, false));
            assertFalse(instance.isValidDirectoryPath("test", "c:\\temp\\..\\etc", parent, false));

            // Windows paths
            assertTrue(instance.isValidDirectoryPath("test", "C:\\", parent, false));                        // Windows root directory
            assertTrue(instance.isValidDirectoryPath("test", sysRoot, parent, false));                  // Windows always exist directory
            assertFalse(instance.isValidDirectoryPath("test", sysRoot + "\\System32\\cmd.exe", parent, false));      // Windows command shell

            // Unix specific paths should not pass
            assertFalse(instance.isValidDirectoryPath("test", "/tmp", parent, false));      // Unix Temporary directory
            assertFalse(instance.isValidDirectoryPath("test", "/bin/sh", parent, false));   // Unix Standard shell
            assertFalse(instance.isValidDirectoryPath("test", "/etc/config", parent, false));

            // Unix specific paths that should not exist or work
            assertFalse(instance.isValidDirectoryPath("test", "/etc/ridiculous", parent, false));
            assertFalse(instance.isValidDirectoryPath("test", "/tmp/../etc", parent, false));

            assertFalse(instance.isValidDirectoryPath("test1", "c:\\ridiculous", parent, false, errors));
            assertTrue(errors.size()==1);
            assertFalse(instance.isValidDirectoryPath("test2", "c:\\jeff", parent, false, errors));
            assertTrue(errors.size()==2);
            assertFalse(instance.isValidDirectoryPath("test3", "c:\\temp\\..\\etc", parent, false, errors));
            assertTrue(errors.size()==3);

            // Windows paths
            assertTrue(instance.isValidDirectoryPath("test4", "C:\\", parent, false, errors));                        // Windows root directory
            assertTrue(errors.size()==3);
            assertTrue(instance.isValidDirectoryPath("test5", sysRoot, parent, false, errors));                  // Windows always exist directory
            assertTrue(errors.size()==3);
            assertFalse(instance.isValidDirectoryPath("test6", sysRoot + "\\System32\\cmd.exe", parent, false, errors));      // Windows command shell
            assertTrue(errors.size()==4);

            // Unix specific paths should not pass
            assertFalse(instance.isValidDirectoryPath("test7", "/tmp", parent, false, errors));      // Unix Temporary directory
            assertTrue(errors.size()==5);
            assertFalse(instance.isValidDirectoryPath("test8", "/bin/sh", parent, false, errors));   // Unix Standard shell
            assertTrue(errors.size()==6);
            assertFalse(instance.isValidDirectoryPath("test9", "/etc/config", parent, false, errors));
            assertTrue(errors.size()==7);

            // Unix specific paths that should not exist or work
            assertFalse(instance.isValidDirectoryPath("test10", "/etc/ridiculous", parent, false, errors));
            assertTrue(errors.size()==8);
            assertFalse(instance.isValidDirectoryPath("test11", "/tmp/../etc", parent, false, errors));
            assertTrue(errors.size()==9);

        } else {
            // Windows paths should fail
            assertFalse(instance.isValidDirectoryPath("test", "c:\\ridiculous", parent, false));
            assertFalse(instance.isValidDirectoryPath("test", "c:\\temp\\..\\etc", parent, false));

            // Standard Windows locations should fail
            assertFalse(instance.isValidDirectoryPath("test", "c:\\", parent, false));                        // Windows root directory
            assertFalse(instance.isValidDirectoryPath("test", "c:\\Windows\\temp", parent, false));               // Windows temporary directory
            assertFalse(instance.isValidDirectoryPath("test", "c:\\Windows\\System32\\cmd.exe", parent, false));   // Windows command shell

            // Unix specific paths should pass
            assertTrue(instance.isValidDirectoryPath("test", "/", parent, false));         // Root directory
            assertTrue(instance.isValidDirectoryPath("test", "/bin", parent, false));      // Always exist directory

            // Unix specific paths that should not exist or work
            assertFalse(instance.isValidDirectoryPath("test", "/bin/sh", parent, false));   // Standard shell, not dir
            assertFalse(instance.isValidDirectoryPath("test", "/etc/ridiculous", parent, false));
            assertFalse(instance.isValidDirectoryPath("test", "/tmp/../etc", parent, false));

            // Windows paths should fail
            assertFalse(instance.isValidDirectoryPath("test1", "c:\\ridiculous", parent, false, errors));
            assertTrue(errors.size()==1);
            assertFalse(instance.isValidDirectoryPath("test2", "c:\\temp\\..\\etc", parent, false, errors));
            assertTrue(errors.size()==2);

            // Standard Windows locations should fail
            assertFalse(instance.isValidDirectoryPath("test3", "c:\\", parent, false, errors));                        // Windows root directory
            assertTrue(errors.size()==3);
            assertFalse(instance.isValidDirectoryPath("test4", "c:\\Windows\\temp", parent, false, errors));               // Windows temporary directory
            assertTrue(errors.size()==4);
            assertFalse(instance.isValidDirectoryPath("test5", "c:\\Windows\\System32\\cmd.exe", parent, false, errors));   // Windows command shell
            assertTrue(errors.size()==5);

            // Unix specific paths should pass
            assertTrue(instance.isValidDirectoryPath("test6", "/", parent, false, errors));         // Root directory
            assertTrue(errors.size()==5);
            assertTrue(instance.isValidDirectoryPath("test7", "/bin", parent, false, errors));      // Always exist directory
            assertTrue(errors.size()==5);

            // Unix specific paths that should not exist or work
            assertFalse(instance.isValidDirectoryPath("test8", "/bin/sh", parent, false, errors));   // Standard shell, not dir
            assertTrue(errors.size()==6);
            assertFalse(instance.isValidDirectoryPath("test9", "/etc/ridiculous", parent, false, errors));
            assertTrue(errors.size()==7);
            assertFalse(instance.isValidDirectoryPath("test10", "/tmp/../etc", parent, false, errors));
            assertTrue(errors.size()==8);
        }
    }

    public void TestIsValidDirectoryPath() {
        // isValidDirectoryPath(String, String, boolean)
    }

    public void testIsValidDouble() {
        // isValidDouble(String, String, double, double, boolean)
    	Validator instance = ESAPI.validator();
    	ValidationErrorList errors = new ValidationErrorList();
    	//testing negative range
        assertFalse(instance.isValidDouble("test1", "-4", 1, 10, false, errors));
        assertTrue(errors.size() == 1);
        assertTrue(instance.isValidDouble("test2", "-4", -10, 10, false, errors));
        assertTrue(errors.size() == 1);
        //testing null value
        assertTrue(instance.isValidDouble("test3", null, -10, 10, true, errors));
        assertTrue(errors.size() == 1);
        assertFalse(instance.isValidDouble("test4", null, -10, 10, false, errors));
        assertTrue(errors.size() == 2);
        //testing empty string
        assertTrue(instance.isValidDouble("test5", "", -10, 10, true, errors));
        assertTrue(errors.size() == 2);
        assertFalse(instance.isValidDouble("test6", "", -10, 10, false, errors));
        assertTrue(errors.size() == 3);
        //testing improper range
        assertFalse(instance.isValidDouble("test7", "50.0", 10, -10, false, errors));
        assertTrue(errors.size() == 4);
        //testing non-integers
        assertTrue(instance.isValidDouble("test8", "4.3214", -10, 10, true, errors));
        assertTrue(errors.size() == 4);
        assertTrue(instance.isValidDouble("test9", "-1.65", -10, 10, true, errors));
        assertTrue(errors.size() == 4);
        //other testing
        assertTrue(instance.isValidDouble("test10", "4", 1, 10, false, errors));
        assertTrue(errors.size() == 4);
        assertTrue(instance.isValidDouble("test11", "400", 1, 10000, false, errors));
        assertTrue(errors.size() == 4);
        assertTrue(instance.isValidDouble("test12", "400000000", 1, 400000000, false, errors));
        assertTrue(errors.size() == 4);
        assertFalse(instance.isValidDouble("test13", "4000000000000", 1, 10000, false, errors));
        assertTrue(errors.size() == 5);
        assertFalse(instance.isValidDouble("test14", "alsdkf", 10, 10000, false, errors));
        assertTrue(errors.size() == 6);
        assertFalse(instance.isValidDouble("test15", "--10", 10, 10000, false, errors));
        assertTrue(errors.size() == 7);
        assertFalse(instance.isValidDouble("test16", "14.1414234x", 10, 10000, false, errors));
        assertTrue(errors.size() == 8);
        assertFalse(instance.isValidDouble("test17", "Infinity", 10, 10000, false, errors));
        assertTrue(errors.size() == 9);
        assertFalse(instance.isValidDouble("test18", "-Infinity", 10, 10000, false, errors));
        assertTrue(errors.size() == 10);
        assertFalse(instance.isValidDouble("test19", "NaN", 10, 10000, false, errors));
        assertTrue(errors.size() == 11);
        assertFalse(instance.isValidDouble("test20", "-NaN", 10, 10000, false, errors));
        assertTrue(errors.size() == 12);
        assertFalse(instance.isValidDouble("test21", "+NaN", 10, 10000, false, errors));
        assertTrue(errors.size() == 13);
        assertTrue(instance.isValidDouble("test22", "1e-6", -999999999, 999999999, false, errors));
        assertTrue(errors.size() == 13);
        assertTrue(instance.isValidDouble("test23", "-1e-6", -999999999, 999999999, false, errors));
        assertTrue(errors.size() == 13);
    }

    public void testIsValidFileContent() {
        System.out.println("isValidFileContent");
        byte[] content = null;
        try {
            content = "This is some file content".getBytes(PREFERRED_ENCODING);
        }
        catch (UnsupportedEncodingException e) {
            fail(PREFERRED_ENCODING + " not a supported encoding?!?!!!");
        }
        Validator instance = ESAPI.validator();
        assertTrue(instance.isValidFileContent("test", content, 100, false));
    }

    public void testIsValidFileName() {
        System.out.println("isValidFileName");
        Validator instance = ESAPI.validator();
        assertTrue("Simple valid filename with a valid extension", instance.isValidFileName("test", "aspect.jar", false));
        assertTrue("All valid filename characters are accepted", instance.isValidFileName("test", "!@#$%^&{}[]()_+-=,.~'` abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.jar", false));
        assertTrue("Legal filenames that decode to legal filenames are accepted", instance.isValidFileName("test", "aspe%20ct.jar", false));

        ValidationErrorList errors = new ValidationErrorList();
        assertTrue("Simple valid filename with a valid extension", instance.isValidFileName("test", "aspect.jar", false, errors));
        assertTrue("All valid filename characters are accepted", instance.isValidFileName("test", "!@#$%^&{}[]()_+-=,.~'` abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890.jar", false, errors));
        assertTrue("Legal filenames that decode to legal filenames are accepted", instance.isValidFileName("test", "aspe%20ct.jar", false, errors));
        assertTrue(errors.size() == 0);
    }

    public void testIsValidFileUpload() throws IOException {
        System.out.println("isValidFileUpload");
        String filepath = new File(System.getProperty("user.dir")).getCanonicalPath();
        String filename = "aspect.jar";
        File parent = new File("/").getCanonicalFile();
        ValidationErrorList errors = new ValidationErrorList();
        byte[] content = null;
        try {
            content = "This is some file content".getBytes(PREFERRED_ENCODING);
        }
        catch (UnsupportedEncodingException e) {
            fail(PREFERRED_ENCODING + " not a supported encoding?!?!!!");
        }
        Validator instance = ESAPI.validator();
        assertTrue(instance.isValidFileUpload("test", filepath, filename, parent, content, 100, false));
        assertTrue(instance.isValidFileUpload("test", filepath, filename, parent, content, 100, false, errors));
        assertTrue(errors.size() == 0);

        filepath = "/ridiculous";
        filename = "aspect.jar";
        try {
            content = "This is some file content".getBytes(PREFERRED_ENCODING);
        }
        catch (UnsupportedEncodingException e) {
            fail(PREFERRED_ENCODING + " not a supported encoding?!?!!!");
        }
        assertFalse(instance.isValidFileUpload("test", filepath, filename, parent, content, 100, false));
        assertFalse(instance.isValidFileUpload("test", filepath, filename, parent, content, 100, false, errors));
        assertTrue(errors.size() == 1);
    }

    public void testIsValidHTTPRequestParameterSet() {
        //		isValidHTTPRequestParameterSet(String, Set, Set)
    }

    public void testisValidInput() {
        System.out.println("isValidInput");
        Validator instance = ESAPI.validator();
        assertTrue(instance.isValidInput("test", "jeff.williams@aspectsecurity.com", "Email", 100, false));
        assertFalse(instance.isValidInput("test", "jeff.williams@@aspectsecurity.com", "Email", 100, false));
        assertFalse(instance.isValidInput("test", "jeff.williams@aspectsecurity", "Email", 100, false));
        assertTrue(instance.isValidInput("test", "jeff.wil'liams@aspectsecurity.com", "Email", 100, false));
        assertTrue(instance.isValidInput("test", "jeff.wil''liams@aspectsecurity.com", "Email", 100, false));
        assertTrue(instance.isValidInput("test", "123.168.100.234", "IPAddress", 100, false));
        assertTrue(instance.isValidInput("test", "192.168.1.234", "IPAddress", 100, false));
        assertFalse(instance.isValidInput("test", "..168.1.234", "IPAddress", 100, false));
        assertFalse(instance.isValidInput("test", "10.x.1.234", "IPAddress", 100, false));
        assertTrue(instance.isValidInput("test", "http://www.aspectsecurity.com", "URL", 100, false));
        assertFalse(instance.isValidInput("test", "http:///www.aspectsecurity.com", "URL", 100, false));
        assertFalse(instance.isValidInput("test", "http://www.aspect security.com", "URL", 100, false));
        assertTrue(instance.isValidInput("test", "078-05-1120", "SSN", 100, false));
        assertTrue(instance.isValidInput("test", "078 05 1120", "SSN", 100, false));
        assertTrue(instance.isValidInput("test", "078051120", "SSN", 100, false));
        assertFalse(instance.isValidInput("test", "987-65-4320", "SSN", 100, false));
        assertFalse(instance.isValidInput("test", "000-00-0000", "SSN", 100, false));
        assertFalse(instance.isValidInput("test", "(555) 555-5555", "SSN", 100, false));
        assertFalse(instance.isValidInput("test", "test", "SSN", 100, false));
        assertTrue(instance.isValidInput("test", "jeffWILLIAMS123", "HTTPParameterValue", 100, false));
        assertTrue(instance.isValidInput("test", "jeff .-/+=@_ WILLIAMS", "HTTPParameterValue", 100, false));
        // Removed per Issue 116 - The '*' character is valid as a parameter character
//        assertFalse(instance.isValidInput("test", "jeff*WILLIAMS", "HTTPParameterValue", 100, false));
        assertFalse(instance.isValidInput("test", "jeff^WILLIAMS", "HTTPParameterValue", 100, false));
        assertFalse(instance.isValidInput("test", "jeff\\WILLIAMS", "HTTPParameterValue", 100, false));

        assertTrue(instance.isValidInput("test", null, "Email", 100, true));
        assertFalse(instance.isValidInput("test", null, "Email", 100, false));

        ValidationErrorList errors = new ValidationErrorList();

        assertTrue(instance.isValidInput("test1", "jeff.williams@aspectsecurity.com", "Email", 100, false, errors));
        assertTrue(errors.size()==0);
        assertFalse(instance.isValidInput("test2", "jeff.williams@@aspectsecurity.com", "Email", 100, false, errors));
        assertTrue(errors.size()==1);
        assertFalse(instance.isValidInput("test3", "jeff.williams@aspectsecurity", "Email", 100, false, errors));
        assertTrue(errors.size()==2);
        assertTrue(instance.isValidInput("test4", "jeff.wil'liams@aspectsecurity.com", "Email", 100, false, errors));
        assertTrue(errors.size()==2);
        assertTrue(instance.isValidInput("test5", "jeff.wil''liams@aspectsecurity.com", "Email", 100, false, errors));
        assertTrue(errors.size()==2);
        assertTrue(instance.isValidInput("test6", "123.168.100.234", "IPAddress", 100, false, errors));
        assertTrue(errors.size()==2);
        assertTrue(instance.isValidInput("test7", "192.168.1.234", "IPAddress", 100, false, errors));
        assertTrue(errors.size()==2);
        assertFalse(instance.isValidInput("test8", "..168.1.234", "IPAddress", 100, false, errors));
        assertTrue(errors.size()==3);
        assertFalse(instance.isValidInput("test9", "10.x.1.234", "IPAddress", 100, false, errors));
        assertTrue(errors.size()==4);
        assertTrue(instance.isValidInput("test10", "http://www.aspectsecurity.com", "URL", 100, false, errors));
        assertTrue(errors.size()==4);
        assertFalse(instance.isValidInput("test11", "http:///www.aspectsecurity.com", "URL", 100, false, errors));
        assertTrue(errors.size()==5);
        assertFalse(instance.isValidInput("test12", "http://www.aspect security.com", "URL", 100, false, errors));
        assertTrue(errors.size()==6);
        assertTrue(instance.isValidInput("test13", "078-05-1120", "SSN", 100, false, errors));
        assertTrue(errors.size()==6);
        assertTrue(instance.isValidInput("test14", "078 05 1120", "SSN", 100, false, errors));
        assertTrue(errors.size()==6);
        assertTrue(instance.isValidInput("test15", "078051120", "SSN", 100, false, errors));
        assertTrue(errors.size()==6);
        assertFalse(instance.isValidInput("test16", "987-65-4320", "SSN", 100, false, errors));
        assertTrue(errors.size()==7);
        assertFalse(instance.isValidInput("test17", "000-00-0000", "SSN", 100, false, errors));
        assertTrue(errors.size()==8);
        assertFalse(instance.isValidInput("test18", "(555) 555-5555", "SSN", 100, false, errors));
        assertTrue(errors.size()==9);
        assertFalse(instance.isValidInput("test19", "test", "SSN", 100, false, errors));
        assertTrue(errors.size()==10);
        assertTrue(instance.isValidInput("test20", "jeffWILLIAMS123", "HTTPParameterValue", 100, false, errors));
        assertTrue(errors.size()==10);
        assertTrue(instance.isValidInput("test21", "jeff .-/+=@_ WILLIAMS", "HTTPParameterValue", 100, false, errors));
        assertTrue(errors.size()==10);
        // Removed per Issue 116 - The '*' character is valid as a parameter character
//        assertFalse(instance.isValidInput("test", "jeff*WILLIAMS", "HTTPParameterValue", 100, false));
        assertFalse(instance.isValidInput("test22", "jeff^WILLIAMS", "HTTPParameterValue", 100, false, errors));
        assertTrue(errors.size()==11);
        assertFalse(instance.isValidInput("test23", "jeff\\WILLIAMS", "HTTPParameterValue", 100, false, errors));
        assertTrue(errors.size()==12);

        assertTrue(instance.isValidInput("test", null, "Email", 100, true, errors));
        assertFalse(instance.isValidInput("test", null, "Email", 100, false, errors));
    }

    public void testIsValidInteger() {
        System.out.println("isValidInteger");
        Validator instance = ESAPI.validator();
        //testing negative range
        assertFalse(instance.isValidInteger("test", "-4", 1, 10, false));
        assertTrue(instance.isValidInteger("test", "-4", -10, 10, false));
        //testing null value
        assertTrue(instance.isValidInteger("test", null, -10, 10, true));
        assertFalse(instance.isValidInteger("test", null, -10, 10, false));
        //testing empty string
        assertTrue(instance.isValidInteger("test", "", -10, 10, true));
        assertFalse(instance.isValidInteger("test", "", -10, 10, false));
        //testing improper range
        assertFalse(instance.isValidInteger("test", "50", 10, -10, false));
        //testing non-integers
        assertFalse(instance.isValidInteger("test", "4.3214", -10, 10, true));
        assertFalse(instance.isValidInteger("test", "-1.65", -10, 10, true));
        //other testing
        assertTrue(instance.isValidInteger("test", "4", 1, 10, false));
        assertTrue(instance.isValidInteger("test", "400", 1, 10000, false));
        assertTrue(instance.isValidInteger("test", "400000000", 1, 400000000, false));
        assertFalse(instance.isValidInteger("test", "4000000000000", 1, 10000, false));
        assertFalse(instance.isValidInteger("test", "alsdkf", 10, 10000, false));
        assertFalse(instance.isValidInteger("test", "--10", 10, 10000, false));
        assertFalse(instance.isValidInteger("test", "14.1414234x", 10, 10000, false));
        assertFalse(instance.isValidInteger("test", "Infinity", 10, 10000, false));
        assertFalse(instance.isValidInteger("test", "-Infinity", 10, 10000, false));
        assertFalse(instance.isValidInteger("test", "NaN", 10, 10000, false));
        assertFalse(instance.isValidInteger("test", "-NaN", 10, 10000, false));
        assertFalse(instance.isValidInteger("test", "+NaN", 10, 10000, false));
        assertFalse(instance.isValidInteger("test", "1e-6", -999999999, 999999999, false));
        assertFalse(instance.isValidInteger("test", "-1e-6", -999999999, 999999999, false));

        ValidationErrorList errors = new ValidationErrorList();
        //testing negative range
        assertFalse(instance.isValidInteger("test1", "-4", 1, 10, false, errors));
        assertTrue(errors.size() == 1);
        assertTrue(instance.isValidInteger("test2", "-4", -10, 10, false, errors));
        assertTrue(errors.size() == 1);
        //testing null value
        assertTrue(instance.isValidInteger("test3", null, -10, 10, true, errors));
        assertTrue(errors.size() == 1);
        assertFalse(instance.isValidInteger("test4", null, -10, 10, false, errors));
        assertTrue(errors.size() == 2);
        //testing empty string
        assertTrue(instance.isValidInteger("test5", "", -10, 10, true, errors));
        assertTrue(errors.size() == 2);
        assertFalse(instance.isValidInteger("test6", "", -10, 10, false, errors));
        assertTrue(errors.size() == 3);
        //testing improper range
        assertFalse(instance.isValidInteger("test7", "50", 10, -10, false, errors));
        assertTrue(errors.size() == 4);
        //testing non-integers
        assertFalse(instance.isValidInteger("test8", "4.3214", -10, 10, true, errors));
        assertTrue(errors.size() == 5);
        assertFalse(instance.isValidInteger("test9", "-1.65", -10, 10, true, errors));
        assertTrue(errors.size() == 6);
        //other testing
        assertTrue(instance.isValidInteger("test10", "4", 1, 10, false, errors));
        assertTrue(errors.size() == 6);
        assertTrue(instance.isValidInteger("test11", "400", 1, 10000, false, errors));
        assertTrue(errors.size() == 6);
        assertTrue(instance.isValidInteger("test12", "400000000", 1, 400000000, false, errors));
        assertTrue(errors.size() == 6);
        assertFalse(instance.isValidInteger("test13", "4000000000000", 1, 10000, false, errors));
        assertTrue(errors.size() == 7);
        assertFalse(instance.isValidInteger("test14", "alsdkf", 10, 10000, false, errors));
        assertTrue(errors.size() == 8);
        assertFalse(instance.isValidInteger("test15", "--10", 10, 10000, false, errors));
        assertTrue(errors.size() == 9);
        assertFalse(instance.isValidInteger("test16", "14.1414234x", 10, 10000, false, errors));
        assertTrue(errors.size() == 10);
        assertFalse(instance.isValidInteger("test17", "Infinity", 10, 10000, false, errors));
        assertTrue(errors.size() == 11);
        assertFalse(instance.isValidInteger("test18", "-Infinity", 10, 10000, false, errors));
        assertTrue(errors.size() == 12);
        assertFalse(instance.isValidInteger("test19", "NaN", 10, 10000, false, errors));
        assertTrue(errors.size() == 13);
        assertFalse(instance.isValidInteger("test20", "-NaN", 10, 10000, false, errors));
        assertTrue(errors.size() == 14);
        assertFalse(instance.isValidInteger("test21", "+NaN", 10, 10000, false, errors));
        assertTrue(errors.size() == 15);
        assertFalse(instance.isValidInteger("test22", "1e-6", -999999999, 999999999, false, errors));
        assertTrue(errors.size() == 16);
        assertFalse(instance.isValidInteger("test23", "-1e-6", -999999999, 999999999, false, errors));
        assertTrue(errors.size() == 17);

    }

    public void testIsValidListItem() {
        System.out.println("isValidListItem");
        Validator instance = ESAPI.validator();
        List list = new ArrayList();
        list.add("one");
        list.add("two");
        assertTrue(instance.isValidListItem("test", "one", list));
        assertFalse(instance.isValidListItem("test", "three", list));

        ValidationErrorList errors = new ValidationErrorList();
        assertTrue(instance.isValidListItem("test1", "one", list, errors));
        assertTrue(errors.size()==0);
        assertFalse(instance.isValidListItem("test2", "three", list, errors));
        assertTrue(errors.size()==1);
    }

    public void testIsValidNumber() {
        System.out.println("isValidNumber");
        Validator instance = ESAPI.validator();
        //testing negative range
        assertFalse(instance.isValidNumber("test", "-4", 1, 10, false));
        assertTrue(instance.isValidNumber("test", "-4", -10, 10, false));
        //testing null value
        assertTrue(instance.isValidNumber("test", null, -10, 10, true));
        assertFalse(instance.isValidNumber("test", null, -10, 10, false));
        //testing empty string
        assertTrue(instance.isValidNumber("test", "", -10, 10, true));
        assertFalse(instance.isValidNumber("test", "", -10, 10, false));
        //testing improper range
        assertFalse(instance.isValidNumber("test", "5", 10, -10, false));
        //testing non-integers
        assertTrue(instance.isValidNumber("test", "4.3214", -10, 10, true));
        assertTrue(instance.isValidNumber("test", "-1.65", -10, 10, true));
        //other testing
        assertTrue(instance.isValidNumber("test", "4", 1, 10, false));
        assertTrue(instance.isValidNumber("test", "400", 1, 10000, false));
        assertTrue(instance.isValidNumber("test", "400000000", 1, 400000000, false));
        assertFalse(instance.isValidNumber("test", "4000000000000", 1, 10000, false));
        assertFalse(instance.isValidNumber("test", "alsdkf", 10, 10000, false));
        assertFalse(instance.isValidNumber("test", "--10", 10, 10000, false));
        assertFalse(instance.isValidNumber("test", "14.1414234x", 10, 10000, false));
        assertFalse(instance.isValidNumber("test", "Infinity", 10, 10000, false));
        assertFalse(instance.isValidNumber("test", "-Infinity", 10, 10000, false));
        assertFalse(instance.isValidNumber("test", "NaN", 10, 10000, false));
        assertFalse(instance.isValidNumber("test", "-NaN", 10, 10000, false));
        assertFalse(instance.isValidNumber("test", "+NaN", 10, 10000, false));
        assertTrue(instance.isValidNumber("test", "1e-6", -999999999, 999999999, false));
        assertTrue(instance.isValidNumber("test", "-1e-6", -999999999, 999999999, false));

        ValidationErrorList errors = new ValidationErrorList();
      //testing negative range
        assertFalse(instance.isValidNumber("test1", "-4", 1, 10, false, errors));
        assertTrue(errors.size()==1);
        assertTrue(instance.isValidNumber("test2", "-4", -10, 10, false, errors));
        assertTrue(errors.size()==1);
        //testing null value
        assertTrue(instance.isValidNumber("test3", null, -10, 10, true, errors));
        assertTrue(errors.size()==1);
        assertFalse(instance.isValidNumber("test4", null, -10, 10, false, errors));
        assertTrue(errors.size()==2);
        //testing empty string
        assertTrue(instance.isValidNumber("test5", "", -10, 10, true, errors));
        assertTrue(errors.size()==2);
        assertFalse(instance.isValidNumber("test6", "", -10, 10, false, errors));
        assertTrue(errors.size()==3);
        //testing improper range
        assertFalse(instance.isValidNumber("test7", "5", 10, -10, false, errors));
        assertTrue(errors.size()==4);
        //testing non-integers
        assertTrue(instance.isValidNumber("test8", "4.3214", -10, 10, true, errors));
        assertTrue(errors.size()==4);
        assertTrue(instance.isValidNumber("test9", "-1.65", -10, 10, true, errors));
        assertTrue(errors.size()==4);
        //other testing
        assertTrue(instance.isValidNumber("test10", "4", 1, 10, false, errors));
        assertTrue(errors.size()==4);
        assertTrue(instance.isValidNumber("test11", "400", 1, 10000, false, errors));
        assertTrue(errors.size()==4);
        assertTrue(instance.isValidNumber("test12", "400000000", 1, 400000000, false, errors));
        assertTrue(errors.size()==4);
        assertFalse(instance.isValidNumber("test13", "4000000000000", 1, 10000, false, errors));
        assertTrue(errors.size()==5);
        assertFalse(instance.isValidNumber("test14", "alsdkf", 10, 10000, false, errors));
        assertTrue(errors.size()==6);
        assertFalse(instance.isValidNumber("test15", "--10", 10, 10000, false, errors));
        assertTrue(errors.size()==7);
        assertFalse(instance.isValidNumber("test16", "14.1414234x", 10, 10000, false, errors));
        assertTrue(errors.size()==8);
        assertFalse(instance.isValidNumber("test17", "Infinity", 10, 10000, false, errors));
        assertTrue(errors.size()==9);
        assertFalse(instance.isValidNumber("test18", "-Infinity", 10, 10000, false, errors));
        assertTrue(errors.size()==10);
        assertFalse(instance.isValidNumber("test19", "NaN", 10, 10000, false, errors));
        assertTrue(errors.size()==11);
        assertFalse(instance.isValidNumber("test20", "-NaN", 10, 10000, false, errors));
        assertTrue(errors.size()==12);
        assertFalse(instance.isValidNumber("test21", "+NaN", 10, 10000, false, errors));
        assertTrue(errors.size()==13);
        assertTrue(instance.isValidNumber("test22", "1e-6", -999999999, 999999999, false, errors));
        assertTrue(errors.size()==13);
        assertTrue(instance.isValidNumber("test23", "-1e-6", -999999999, 999999999, false, errors));
        assertTrue(errors.size()==13);
    }

    public void testIsValidParameterSet() {
        System.out.println("isValidParameterSet");
        Set requiredNames = new HashSet();
        requiredNames.add("p1");
        requiredNames.add("p2");
        requiredNames.add("p3");
        Set optionalNames = new HashSet();
        optionalNames.add("p4");
        optionalNames.add("p5");
        optionalNames.add("p6");
        MockHttpServletRequest request = new MockHttpServletRequest();
        MockHttpServletResponse response = new MockHttpServletResponse();
        request.addParameter("p1", "value");
        request.addParameter("p2", "value");
        request.addParameter("p3", "value");
        ESAPI.httpUtilities().setCurrentHTTP(request, response);
        Validator instance = ESAPI.validator();
        ValidationErrorList errors = new ValidationErrorList();
        assertTrue(instance.isValidHTTPRequestParameterSet("HTTPParameters", request, requiredNames, optionalNames));
        assertTrue(instance.isValidHTTPRequestParameterSet("HTTPParameters", request, requiredNames, optionalNames,errors));
        assertTrue(errors.size()==0);
        request.addParameter("p4", "value");
        request.addParameter("p5", "value");
        request.addParameter("p6", "value");
        assertTrue(instance.isValidHTTPRequestParameterSet("HTTPParameters", request, requiredNames, optionalNames));
        assertTrue(instance.isValidHTTPRequestParameterSet("HTTPParameters", request, requiredNames, optionalNames, errors));
        assertTrue(errors.size()==0);
        request.removeParameter("p1");
        assertFalse(instance.isValidHTTPRequestParameterSet("HTTPParameters", request, requiredNames, optionalNames));
        assertFalse(instance.isValidHTTPRequestParameterSet("HTTPParameters", request, requiredNames, optionalNames, errors));
        assertTrue(errors.size() ==1);
    }

    public void testIsValidPrintable() {
        System.out.println("isValidPrintable");
        Validator instance = ESAPI.validator();
        assertTrue(instance.isValidPrintable("name", "abcDEF", 100, false));
        assertTrue(instance.isValidPrintable("name", "!@#R()*$;><()", 100, false));
        char[] chars = {0x60, (char) 0xFF, 0x10, 0x25};
        assertFalse(instance.isValidPrintable("name", chars, 100, false));
        assertFalse(instance.isValidPrintable("name", "%08", 100, false));

        ValidationErrorList errors = new ValidationErrorList();
        assertTrue(instance.isValidPrintable("name1", "abcDEF", 100, false, errors));
        assertTrue(errors.size()==0);
        assertTrue(instance.isValidPrintable("name2", "!@#R()*$;><()", 100, false, errors));
        assertTrue(errors.size()==0);
        assertFalse(instance.isValidPrintable("name3", chars, 100, false, errors));
        assertTrue(errors.size()==1);
        assertFalse(instance.isValidPrintable("name4", "%08", 100, false, errors));
        assertTrue(errors.size()==2);

    }

    public void testIsValidRedirectLocation() {
        //		isValidRedirectLocation(String, String, boolean)
    }

    public void testIsValidSafeHTML() {
        System.out.println("isValidSafeHTML");
        Validator instance = ESAPI.validator();

        assertTrue(instance.isValidSafeHTML("test", "<b>Jeff</b>", 100, false));
        assertTrue(instance.isValidSafeHTML("test", "<a href=\"http://www.aspectsecurity.com\">Aspect Security</a>", 100, false));
        assertTrue(instance.isValidSafeHTML("test", "Test. <script>alert(document.cookie)</script>", 100, false));
        assertTrue(instance.isValidSafeHTML("test", "Test. <div style={xss:expression(xss)}>", 100, false));
        assertTrue(instance.isValidSafeHTML("test", "Test. <s%00cript>alert(document.cookie)</script>", 100, false));
        assertTrue(instance.isValidSafeHTML("test", "Test. <s\tcript>alert(document.cookie)</script>", 100, false));
        assertTrue(instance.isValidSafeHTML("test", "Test. <s\r\n\0cript>alert(document.cookie)</script>", 100, false));

        // TODO: waiting for a way to validate text headed for an attribute for scripts
        // This would be nice to catch, but just looks like text to AntiSamy
        // assertFalse(instance.isValidSafeHTML("test", "\" onload=\"alert(document.cookie)\" "));
        ValidationErrorList errors = new ValidationErrorList();
        assertTrue(instance.isValidSafeHTML("test1", "<b>Jeff</b>", 100, false, errors));
        assertTrue(instance.isValidSafeHTML("test2", "<a href=\"http://www.aspectsecurity.com\">Aspect Security</a>", 100, false, errors));
        assertTrue(instance.isValidSafeHTML("test3", "Test. <script>alert(document.cookie)</script>", 100, false, errors));
        assertTrue(instance.isValidSafeHTML("test4", "Test. <div style={xss:expression(xss)}>", 100, false, errors));
        assertTrue(instance.isValidSafeHTML("test5", "Test. <s%00cript>alert(document.cookie)</script>", 100, false, errors));
        assertTrue(instance.isValidSafeHTML("test6", "Test. <s\tcript>alert(document.cookie)</script>", 100, false, errors));
        assertTrue(instance.isValidSafeHTML("test7", "Test. <s\r\n\0cript>alert(document.cookie)</script>", 100, false, errors));
        assertTrue(errors.size() == 0);

    }

    public void testSafeReadLine() {
        System.out.println("safeReadLine");

        byte[] bytes = null;
        try {
            bytes = "testString".getBytes(PREFERRED_ENCODING);
        }
        catch (UnsupportedEncodingException e1) {
            fail(PREFERRED_ENCODING + " not a supported encoding?!?!!!");
        }
        ByteArrayInputStream s = new ByteArrayInputStream(bytes);
        Validator instance = ESAPI.validator();
        try {
            instance.safeReadLine(s, -1);
            fail();
        }
        catch (ValidationException e) {
            // Expected
        }
        s.reset();
        try {
            instance.safeReadLine(s, 4);
            fail();
        }
        catch (ValidationException e) {
            // Expected
        }
        s.reset();
        try {
            String u = instance.safeReadLine(s, 20);
            assertEquals("testString", u);
        }
        catch (ValidationException e) {
            fail();
        }

        // This sub-test attempts to validate that BufferedReader.readLine() and safeReadLine() are similar in operation
        // for the nominal case
        try {
            s.reset();
            InputStreamReader isr = new InputStreamReader(s);
            BufferedReader br = new BufferedReader(isr);
            String u = br.readLine();
            s.reset();
            String v = instance.safeReadLine(s, 20);
            assertEquals(u, v);
        }
        catch (IOException e) {
            fail();
        }
        catch (ValidationException e) {
            fail();
        }
    }

    public void testIssue82_SafeString_Bad_Regex() {
        Validator instance = ESAPI.validator();
        try {
            instance.getValidInput("address", "55 main st. pasadena ak", "SafeString", 512, false);
        }
        catch (ValidationException e) {
            fail(e.getLogMessage());
        }
    }

    public void testGetParameterMap() {
//testing Validator.HTTPParameterName and Validator.HTTPParameterValue
        MockHttpServletRequest request = new MockHttpServletRequest();
        SecurityWrapperRequest safeRequest = new SecurityWrapperRequest(request);
//an example of a parameter from displaytag, should pass
        request.addParameter("d-49653-p", "pass");
        request.addParameter("<img ", "fail");
        request.addParameter(generateStringOfLength(32), "pass");
        request.addParameter(generateStringOfLength(33), "fail");
        assertEquals(safeRequest.getParameterMap().size(), 2);
        assertNull(safeRequest.getParameterMap().get("<img"));
        assertNull(safeRequest.getParameterMap().get(generateStringOfLength(33)));
    }

    public void testGetParameterNames() {
//testing Validator.HTTPParameterName
        MockHttpServletRequest request = new MockHttpServletRequest();
        SecurityWrapperRequest safeRequest = new SecurityWrapperRequest(request);
//an example of a parameter from displaytag, should pass
        request.addParameter("d-49653-p", "pass");
        request.addParameter("<img ", "fail");
        request.addParameter(generateStringOfLength(32), "pass");
        request.addParameter(generateStringOfLength(33), "fail");
        assertEquals(Collections.list(safeRequest.getParameterNames()).size(), 2);
    }

    public void testGetParameter() {
//testing Validator.HTTPParameterValue
        MockHttpServletRequest request = new MockHttpServletRequest();
        SecurityWrapperRequest safeRequest = new SecurityWrapperRequest(request);
        request.addParameter("p1", "Alice");
        request.addParameter("p2", "bob@alice.com");//mail-address from a submit-form
        request.addParameter("p3", ESAPI.authenticator().generateStrongPassword());
        request.addParameter("p4", new String(EncoderConstants.CHAR_PASSWORD_SPECIALS));
        //TODO - I think this should fair request.addParameter("p5", "�������?����"); //some special characters from european languages;
        request.addParameter("f1", "<SCRIPT SRC=http://ha.ckers.org/xss.js></SCRIPT>");
        request.addParameter("f2", "<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>");
        request.addParameter("f3", "<IMG SRC=&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;&#58;&#97;&#108;&#101;&#114;&#116;&#40;&#39;&#88;&#83;&#83;&#39;&#41;>");
        for (int i = 1; i <= 4; i++) {
            assertTrue(safeRequest.getParameter("p" + i).equals(request.getParameter("p" + i)));
        }
        for (int i = 1; i <= 2; i++) {
        	boolean testResult = false;
        	try {
        		testResult = safeRequest.getParameter("f" + i).equals(request.getParameter("f" + i));
        	} catch (NullPointerException npe) {
        		//the test is this block SHOULD fail. a NPE is an acceptable failure state
        		testResult = false; //redundant, just being descriptive here
        	}
        	assertFalse(testResult);
        }
        assertNull(safeRequest.getParameter("e1"));

        //This is revealing problems with Jeff's original SafeRequest
        //mishandling of the AllowNull parameter. I'm adding a new Google code
        //bug to track this.
        //
        //assertNotNull(safeRequest.getParameter("e1", false));
    }

    public void testGetCookies() {
//testing Validator.HTTPCookieName and Validator.HTTPCookieValue
        MockHttpServletRequest request = new MockHttpServletRequest();
        SecurityWrapperRequest safeRequest = new SecurityWrapperRequest(request);
//should support a base64-encode value
        request.setCookie("p1", "34=VJhjv7jiDu7tsdLrQQ2KcUwpfWUM2_mBae6UA8ttk4wBHdxxQ-1IBxyCOn3LWE08SDhpnBcJ7N5Vze48F2t8a1R_hXt7PX1BvgTM0pn-T4JkqGTm_tlmV4RmU3GT-dgn");
        request.setCookie("f1", "<A HREF=\"http://66.102.7.147/\">XSS</A>");
        request.setCookie("load-balancing", "pass");
        request.setCookie("'bypass", "fail");
        Cookie[] cookies = safeRequest.getCookies();
        assertEquals(cookies[0].getValue(), request.getCookies()[0].getValue());
        assertEquals(cookies[1].getName(), request.getCookies()[2].getName());
        assertTrue(cookies.length == 2);
    }

    public void testGetHeader() {
//testing Validator.HTTPHeaderValue
        MockHttpServletRequest request = new MockHttpServletRequest();
        SecurityWrapperRequest safeRequest = new SecurityWrapperRequest(request);
        request.addHeader("p1", "login");
        request.addHeader("f1", "<A HREF=\"http://0x42.0x0000066.0x7.0x93/\">XSS</A>");
        request.addHeader("p2", generateStringOfLength(150));
        request.addHeader("f2", generateStringOfLength(151));
        assertEquals(safeRequest.getHeader("p1"), request.getHeader("p1"));
        assertEquals(safeRequest.getHeader("p2"), request.getHeader("p2"));
        assertFalse(safeRequest.getHeader("f1").equals(request.getHeader("f1")));
        assertFalse(safeRequest.getHeader("f2").equals(request.getHeader("f2")));
        assertNull(safeRequest.getHeader("p3"));
    }

    public void testGetHeaderNames() {
//testing Validator.HTTPHeaderName
        MockHttpServletRequest request = new MockHttpServletRequest();
        SecurityWrapperRequest safeRequest = new SecurityWrapperRequest(request);
        request.addHeader("d-49653-p", "pass");
        request.addHeader("<img ", "fail");
        request.addHeader(generateStringOfLength(32), "pass");
        request.addHeader(generateStringOfLength(33), "fail");
        assertEquals(Collections.list(safeRequest.getHeaderNames()).size(), 2);
    }

    public void testGetQueryString() {
//testing Validator.HTTPQueryString
        MockHttpServletRequest request = new MockHttpServletRequest();
        SecurityWrapperRequest safeRequest = new SecurityWrapperRequest(request);
        request.setQueryString("mail=bob@alice.com&passwd=" + new String(EncoderConstants.CHAR_PASSWORD_SPECIALS));// TODO, fix this + "&special=�����");
        assertEquals(safeRequest.getQueryString(), request.getQueryString());
        request.setQueryString("mail=<IMG SRC=\"jav\tascript:alert('XSS');\">");
        assertFalse(safeRequest.getQueryString().equals(request.getQueryString()));
        request.setQueryString("mail=bob@alice.com-passwd=johny");
        assertTrue(safeRequest.getQueryString().equals(request.getQueryString()));
        request.setQueryString("mail=bob@alice.com-passwd=johny&special"); //= is missing!
        assertFalse(safeRequest.getQueryString().equals(request.getQueryString()));
    }

    public void testGetRequestURI() {
//testing Validator.HTTPURI
        MockHttpServletRequest request = new MockHttpServletRequest();
        SecurityWrapperRequest safeRequest = new SecurityWrapperRequest(request);
        try {
            request.setRequestURI("/app/page.jsp");
        } catch (UnsupportedEncodingException ignored) {
        }
        assertEquals(safeRequest.getRequestURI(), request.getRequestURI());
    }

    private String generateStringOfLength(int length) {
        StringBuilder longString = new StringBuilder();
        for (int i = 0; i < length; i++) {
            longString.append("a");
        }
        return longString.toString();
    }

    public void testGetContextPath() {
        // Root Context Path ("")
        assertTrue(ESAPI.validator().isValidInput("HTTPContextPath", "", "HTTPContextPath", 512, true));
        // Deployed Context Path ("/context")
        assertTrue(ESAPI.validator().isValidInput("HTTPContextPath", "/context", "HTTPContextPath", 512, true));
        // Fail-case - URL Splitting
        assertFalse(ESAPI.validator().isValidInput("HTTPContextPath", "/\\nGET http://evil.com", "HTTPContextPath", 512, true));
    }
}
