var lowercase  = "abcdefghijklmnopqrstuvwxyz";
var uppercase  = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
var letters    = lowercase + uppercase;
var digits     = "0123456789";
var octdigits  = "01234567";
var hexdigits  = "0123456789abcdefABCDEF";
var whitespace = " \t\n\r\f\v";

var rfc822_specials = "()<>@,;L\\\"[]";

var validUserNameCharacters = letters + digits + "_";
var validNameCharacters     = letters + " ,.-";

function isTextFieldValid(form, field, required)
{
    var i, str;

    str = document.forms[form].elements[field].value;
    if (required && !str.length)
        return false;

    for (i = 0;  i < str.length;  i++)
        if (str.charCodeAt(i) < 32 || str.charCodeAt(i) > 126)
            return false;

    return true;
}

function isMultiLineFieldValid(form, field, required)
{
    var c, i, str;

    str = document.forms[form].elements[field].value;
    if (required && !str.length)
        return false;

    for (i = 0;  i < str.length;  i++)
    {
        c = str.charCodeAt(i);
        if (c != 9 && c != 10 && c != 13 && (c < 32 || c > 126))
            return false;
    }

    return true;
}

function isUserNameValid(str)
{
    var i;

    if (str.length < 3 || str.length > 32)
        return false;
    for (i = 0;  i < str.length;  i++)
        if (validUserNameCharacters.indexOf(str.charAt(i)) == -1)
            return false;
    return true;
}

function isPasswordValid(str)
{
    var i;

    if (str.length < 6 || str.length > 128)
        return false;
    for (i = 0;  i < str.length;  i++)
        if (str.charCodeAt(i) < 32 || str.charCodeAt(i) > 126)
            return false;
    return true;
}

function isNameValid(str)
{
    var i, nonblank;

    while (str.indexOf('  ') != -1)
        str.replace('  ', ' ');
    for (i = nonblank = 0;  i < str.length;  i++)
    {
        if (validNameCharacters.indexOf(str.charAt(i)) == -1)
            return false;
        if (str.charAt(i) != ' ')
            nonblank++;
    }
    if (str.length < 5 || nonblank < str.length / 2)
        return false;
    return true;
}

// Ported from Recipe 3.9 in Secure Programming Cookbook for C and C++ by
// John Viega and Matt Messier (O'Reilly 2003)
function isEmailAddressValid(str)
{
    var c, count, domain;

    for (c = 0;  c < str.length;  c++)
    {
        if (str.charAt(c) == "\"" && (!c || str.charAt(c - 1) == "." || str.charAt(c - 1) == "\""))
        {
            while (++c < str.length)
            {
                if (str.charAt(c) == "\"") break;
                if (str.charAt(c) == "\\" && (str.charAt(++c) == ' ')) continue;
                if (str.charCodeAt(c) < 32 || str.charCodeAt(c) >= 127) return false;
            }
            if (c++ >= str.length) return false;
            if (str.charAt(c) == "@") break;
            if (str.charAt(c) != ".") return false;
            continue;
        }
        if (str.charAt(c) == "@") break;
        if (str.charCodeAt(c) <= 32 || str.charCodeAt(c) >= 127) return false;
        if (rfc822_specials.indexOf(str.charAt(c)) != -1) return false;
    }
    if (!c || str.charAt(c - 1) == ".") return false;

    if ((domain = ++c) >= str.length) return false;
    count = 0;
    do
    {
        if (str.charAt(c) == ".")
        {
            if (c == domain || str.charAt(c - 1) == ".") return false;
            count++;
        }
        if (str.charCodeAt(c) <= 32 || str.charCodeAt(c) >= 127) return false;
        if (rfc822_specials.indexOf(str.charAt(c)) != -1) return false;
    } while (++c < str.length);

    return (count >= 1 ? true : false);
}

function removeAntiSpamNonsense(str)
{
    var c, count, domain;

    for (c = 0;  c < str.length;  c++)
    {
        if (str.charAt(c) == "\"" && (!c || str.charAt(c - 1) == "." || str.charAt(c - 1) == "\""))
        {
            while (++c < str.length)
            {
                if (str.charAt(c) == "\"") break;
                if (str.charAt(c) == "\\" && (str.charAt(++c) == ' ')) continue;
                if (str.charCodeAt(c) < 32 || str.charCodeAt(c) >= 127) return false;
            }
            if (c++ >= str.length) return false;
            if (str.substr(c, 4).toLowerCase() == " at ")
                str = str.substring(0, c) + "@" + str.substring(c + 4, str.length);
            if (str.charAt(c) == "@") break;
            if (str.charAt(c) != ".") return false;
            continue;
        }
        if (str.substr(c, 4).toLowerCase() == " at ")
            str = str.substring(0, c) + "@" + str.substring(c + 4, str.length);
        if (str.charAt(c) == "@") break;
        if (str.charCodeAt(c) <= 32 || str.charCodeAt(c) >= 127) return false;
        if (rfc822_specials.indexOf(str.charAt(c)) != -1) return false;
    }
    if (!c || str.charAt(c - 1) == ".") return false;

    if ((domain = ++c) >= str.length) return false;
    if (str.substr(c, 7) == "NOSPAM.")
        str = str.substring(0, c) + str.substring(c + 7, str.length);
    if (str.substr(c, 7) == "NOSPAM " && str.substr(c + 7, 4).toLowerCase() == "dot ")
        str = str.substring(0, c) + str.substring(c + 11, str.length);
    count = 0;
    do
    {
        if (str.substr(c, 5).toLowerCase() == " dot ")
            str = str.substring(0, c) + "." + str.substring(c + 5, str.length);
        if (str.charAt(c) == ".")
        {
            if (c == domain || str.charAt(c - 1) == ".") return false;
            count++;
        }
        if (str.charCodeAt(c) <= 32 || str.charCodeAt(c) >= 127) return false;
        if (rfc822_specials.indexOf(str.charAt(c)) != -1) return false;
    } while (++c < str.length);

    return (count >= 1 ? str : false);
}

function isSettingsFormValid()
{
    var ciphertext, email, exponent, form, modulus, password;

    form = document.forms["settings"];
    if (!isNameValid(form.elements["name"].value))
    {
        form.elements["name"].focus();
        alert("The name you\'ve entered is not valid.");
        return false;
    }

    email = removeAntiSpamNonsense(form.elements["email"].value);
    if (!email)
    {
        form.elements["email"].focus();
        alert("The email address you\'ve entered is not valid.");
        return false;
    }
    form.elements["email"].value = email;

    if (form.elements["password"].value.length || form.elements["again"].value.length)
    {
        if (!isPasswordValid(form.elements["password"].value))
        {
            form.elements["password"].focus();
            form.elements["password"].value = form.elements["again"].value = "";
            alert("The password you\'ve entered is not valid.");
            return false;
        }
        if (form.elements["password"].value != form.elements["again"].value)
        {
            form.elements["password"].focus();
            form.elements["password"].value = form.elements["again"].value = "";
            alert("The passwords you\'ve entered do not match.");
            return false;
        }

        exponent = form.elements["rsa_exponent"].value;
        modulus  = form.elements["rsa_modulus"].value;
        password = hex_sha1(form.elements["password"].value);
        cipher   = rsa_encrypt(modulus, exponent, password);

        form.elements["password"].value = "";
        form.elements["again"].value = "";
        form.elements["rsa_password"].value = cipher;
    }

    return true;
}

function isNewUserFormValid()
{
    var ciphertext, email, exponent, form, modulus, password;

    form = document.forms["newuser"];
    if (!isUserNameValid(form.elements["username"].value))
    {
        form.elements["username"].focus();
        alert("The username you\'ve entered is not valid.");
        return false;
    }
    if (!isPasswordValid(form.elements["password"].value))
    {
        form.elements["password"].focus();
        form.elements["password"].value = form.elements["again"].value = "";
        alert("The password you\'ve entered is not valid.");
        return false;
    }
    if (form.elements["password"].value != form.elements["again"].value)
    {
        form.elements["password"].focus();
        form.elements["password"].value = form.elements["again"].value = "";
        alert("The passwords you\'ve entered do not match.");
        return false;
    }
    if (!isNameValid(form.elements["name"].value))
    {
        form.elements["name"].focus();
        alert("The name you\'ve entered is not valid.");
        return false;
    }

    email = removeAntiSpamNonsense(form.elements["email"].value);
    if (!email)
    {
        form.elements["email"].focus();
        alert("The email address you\'ve entered is not valid.");
        return false;
    }
    form.elements["email"].value = email;

    exponent = form.elements["rsa_exponent"].value;
    modulus  = form.elements["rsa_modulus"].value;
    password = hex_sha1(form.elements["password"].value);
    cipher   = rsa_encrypt(modulus, exponent, password);

    form.elements["password"].value = "";
    form.elements["again"].value = "";
    form.elements["rsa_password"].value = cipher;

    return true;
}

function isLoginFormValid()
{
    var challenge, form, password, username;

    form = document.forms["login"];
    if (isUserNameValid(form.elements["username"].value) &&
        isPasswordValid(form.elements["password"].value))
    {
        challenge = form.elements["session_challenge"].value;
        username  = form.elements["username"].value;
        password  = hex_sha1(form.elements["password"].value);
        form.elements["session_response"].value = 
                    hex_sha1(username + password + challenge);
        form.elements["password"].value = "";
        return true;
    }

    alert("You entered an invalid username or password.");
    return false;
}

function isSearchFormValid(name)
{
    var form;

    form = document.forms[name];
    if (form.elements["query"].value.length < 1)
        return false;
    return true;
}
