Commit 8dbead16 authored by Leigh B. Stoller's avatar Leigh B. Stoller

First try at solving the problem of validating user input for the

zillions of DB fields that we have to set. My solution was to add a
meta table that describes what is a legal value for each table/slot
for which we take from user input. The table looks like this right
now, but is likely to adapt as we get more experience with this
approach (or it might get tossed if it turns out to be a pain in the
ass!).

	CREATE TABLE table_regex (
	  table_name varchar(64) NOT NULL default '',
	  column_name varchar(64) NOT NULL default '',
	  column_type enum('text','int','float') default NULL,
	  check_type enum('regex','function','redirect') default NULL,
	  check tinytext NOT NULL,
	  min int(11) NOT NULL default '0',
	  max int(11) NOT NULL default '0',
	  comment tinytext,
	  UNIQUE KEY table_name (table_name,column_name)
	) TYPE=MyISAM;

Entries in this table look like this:

	('virt_nodes','vname','text','regex','^[-\\w]+$',1,32,NULL);

Which says that the vname slot of the virt_nodes table (which we trust the
user to give us in some form) is a text field to be checked with the given
regex (perlre of course), and that the min/max length of the text field is
1 and 32 chars respectively.

Now, you wouldn't want to write the same regex over and over, and since we
use the same fields in many tables (like pid, eid, vname, etc) there is an
option to redirect to another entry (recursively). So, for "PID" I do this:

        ('eventlist','pid','text','redirect','projects:pid',0,0,NULL);

which redirects to:

	('projects','pid','text','regex','^[a-zA-Z][-\\w]+$',2,12,NULL);

And, for many fields you just want to describe generically what could go
into it. For that I have defined some default fields. For example, a user
description:

        ('experiment,'usr_name','text','redirect','default:tinytext',0,0,NULL);

which redirects to:

	('default','tinytext','text','regex','^[\\040-\\176]*$',0,256,NULL);

and this says that a tinytext (in our little corner of the database
universe) field can have printable characters (but not a newline), and
since its a tinytext field, its maxlen is 256 chars.

You also have integer fields, but these are little more irksome in the
details.

	('default','tinyint,'int,'regex','^[\\d]+$',-128,127,NULL);

and you would use this anyplace you do not care about the min/max values
being something specific in the tinyint range. The range for a float is of
course stated as an integer, and thats kinda bogus, but we do not have many
floats, and they generally do not take on specific values anyway.

A note about the min/max fields and redirecting. If the initial entry has
non-zero min/max fields, those are the min mac fields used. Otherwise they
come from the default. So for example, you can do this:

    ('experiments','mem_usage','int','redirect','default:tinyint',0,5,NULL);

So, you can redirect to the standard "tinyint" regular expression, but you
still get to define min/max for the specific field.

Isn't this is really neat and really obtuse too? Sure, you can say it.

Anyway, xmlconvert now sends all of its input through these checks (its
all wrapped up in library calls), and if a slot does not have an entry, it
throws an error so that we are forced to define entries for new slots as we
add them.

In the web page, I have changed all of the public pages (login, join
project, new project, and a couple of others) to also use these checks.
As with the perl code, its all wrapped up in a library. Lots more code
needs to be changed of course, but this is a start.
parent da4a4125
......@@ -175,7 +175,8 @@ use Exporter;
TBDB_ROUTERTYPE_NONE TBDB_ROUTERTYPE_OSPF
TBDB_ROUTERTYPE_STATIC TBDB_ROUTERTYPE_MANUAL
TBDB_EVENTKEY
max min
TBDB_CHECKDBSLOT_NOFLAGS TBDB_CHECKDBSLOT_WARN TBDB_CHECKDBSLOT_ERROR
max min TBcheck_dbslot
);
# Must come after package declaration!
......@@ -555,6 +556,11 @@ sub TBDB_ROUTERTYPE_MANUAL() { "manual"; }
# Event Stuff
sub TBDB_EVENTKEY($$) { TBExptUserDir($_[0],$_[1]) . "/tbdata/eventkey"; }
# Regex stuff
sub TBDB_CHECKDBSLOT_NOFLAGS() { 0x0; }
sub TBDB_CHECKDBSLOT_WARN() { 0x1; }
sub TBDB_CHECKDBSLOT_ERROR() { 0x2; }
#
# Auth stuff.
#
......@@ -3759,6 +3765,150 @@ sub min ( $$ ) {
return ($_[0] < $_[1] ? $_[0] : $_[1]);
}
#
# Support for checking field values against what is specified.
#
my %DBFieldData;
my $DBFieldErrstr = "";
sub TBFieldErrorString() { return $DBFieldErrstr; }
#
# Download all data from the DB and store in hash for latter access.
#
sub TBGrabFieldData()
{
$DBFieldData = ();
my $query_result =
DBQueryFatal("select * from table_regex");
while (my %row = $query_result->fetchhash()) {
my $table_name = $row{"table_name"};
my $column_name = $row{"column_name"};
$DBFieldData{$table_name . ":" . $column_name} =
{ "check" => $row{"check"},
"check_type" => $row{"check_type"},
"column_type" => $row{"column_type"},
"min" => $row{"min"},
"max" => $row{"max"}
};
}
}
#
# Return the field data for a specific table/slot. If none, return the default
# entry.
#
# The top level entry defines some stuff that is not to be overidden by the
# redirected entries. For example, the top level entry is the only place we
# can specify a field is optional when inserting a record. We could do this
# with default entries in the DB table defintion, but I do not like that idea.
# The min/max lengths also override, unless they are both zero in which case
# let the first non-zero defs set them.
#
sub TBFieldData($$;$)
{
my ($table, $column, $flag) = @_;
my $toplevel;
my $fielddata;
if (! defined($DBFieldData)) {
TBGrabFieldData();
}
my $key = $table . ":" . $column;
while (exists($DBFieldData{$key})) {
$fielddata = $DBFieldData{$key};
#
# See if a redirect to another entry.
#
if ($fielddata->{"check_type"} eq "redirect") {
if (!defined($toplevel)) {
$toplevel = $fielddata;
}
$key = $fielddata->{"check"};
#print STDERR "Redirecting to $key for $table/$column!\n";
next;
}
last;
}
# Resort to a default entry.
if (!defined($fielddata)) {
if (defined($flag)) {
if ($flag & TBDB_CHECKDBSLOT_WARN()) {
print STDERR "*** $0:\n" .
" WARNING: No slot data for $table/$column!\n";
}
return undef
if ($flag & TBDB_CHECKDBSLOT_ERROR());
}
$fielddata = $DBFieldData{"default:default"};
}
# Overwrite final entry with toplevel data.
if (defined($toplevel) &&
($toplevel->{"min"} || $toplevel->{"max"})) {
$fielddata->{"min"} = $toplevel->{"min"};
$fielddata->{"max"} = $toplevel->{"max"};
}
return $fielddata;
}
#
# Generic wrapper to check a slot.
#
sub TBcheck_dbslot($$$;$)
{
my ($token, $table, $column, $flag) = @_;
my $fielddata = TBFieldData($table, $column, $flag);
return 0
if (!defined($fielddata));
my $check = $fielddata->{"check"};
my $check_type = $fielddata->{"check_type"};
my $column_type = $fielddata->{"column_type"};
my $min = $fielddata->{"min"};
my $max = $fielddata->{"max"};
# print STDERR "Using $check/$check_type/$column_type for $table/$column\n";
#
# Functional checks not implemented yet.
#
if ($check_type eq "function") {
die("*** $0:\n" .
" Functional DB checks not implemented: $table/$column!\n");
}
# Check regex.
return 0
if (! ("$token" =~ /$check/));
# Check min/max.
if ($column_type eq "text") {
return 1
if ((!$min && !$max) ||
(length($token) >= $min &&
length($token) <= $max));
}
elsif ($column_type eq "int" ||
$column_type eq "float") {
# If both min/max are zero, then skip check; allow anything.
return 1
if ((!$min && !$max) || ($token >= $min && $token <= $max));
}
else {
die("*** $0:\n" .
" Unrecognized column_type $column_type\n");
}
return 0;
}
# _Always_ make sure that this 1 is at the end of the file...
1;
......
......@@ -235,18 +235,19 @@ sub readXML($$$) {
foreach my $key (keys(%experiments_table)) {
my $val = $experiments_table{$key};
if ($val eq "NULL") {
push(@setlist, "$key=NULL");
}
else {
# Sanity check. The particular set of fields should not need
# anything more than alphanumeric.
if ($val =~ /^[-\d\w]+$/) {
# Sanity check the fields.
if (TBcheck_dbslot($val, "experiments", $key,
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR)) {
push(@setlist, "$key='$val'");
}
else {
fatal("Illegal characters in table data: $key/$val");
fatal("Illegal characters in table data: ".
"experiments:$key - $val");
}
}
}
......@@ -294,9 +295,20 @@ sub readXML($$$) {
if ($val eq "NULL") {
push(@values, "NULL");
}
elsif ($val eq "") {
push(@values, "''");
}
else {
push(@values, DBQuoteSpecial($val));
}
# Sanity check the fields.
if (TBcheck_dbslot($val, $table, $key,
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR)) {
push(@values, DBQuoteSpecial($val));
}
else {
fatal("Illegal characters in table data: ".
"$table:$key - $val");
}
}
push(@fields, $key);
}
$query = "insert into $table (" . join(",", @fields) . ") ".
......
<?php
#
# Stuff to support checking field data before we insert it into the DB.
#
define("TBDB_CHECKDBSLOT_NOFLAGS", 0x0);
define("TBDB_CHECKDBSLOT_WARN", 0x1);
define("TBDB_CHECKDBSLOT_ERROR", 0x2);
$DBFieldData = 0;
$DBFieldErrstr = "";
function TBFieldErrorString() { global $DBFieldErrstr; return $DBFieldErrstr; }
#
# Download all data from the DB and store in hash for latter access.
#
function TBGrabFieldData()
{
global $DBFieldData;
$DBFieldData = array();
$query_result =
DBQueryFatal("select * from table_regex");
while ($row = mysql_fetch_assoc($query_result)) {
$table_name = $row["table_name"];
$column_name = $row["column_name"];
$DBFieldData[$table_name . ":" . $column_name] =
array("check" => $row["check"],
"check_type" => $row["check_type"],
"column_type" => $row["column_type"],
"min" => $row["min"],
"max" => $row["max"]);
}
}
#
# Return the field data for a specific table/slot. If none, return the default
# entry.
#
function TBFieldData($table, $column, $flag = 0)
{
global $DBFieldData;
if (! $DBFieldData) {
TBGrabFieldData();
}
$key = $table . ":" . $column;
unset($toplevel);
unset($fielddate);
while (isset($DBFieldData[$key])) {
$fielddata = $DBFieldData[$key];
#
# See if a redirect to another entry.
#
if ($fielddata["check_type"] == "redirect") {
if (!isset($toplevel))
$toplevel = $fielddata;
$key = $fielddata["check"];
continue;
}
break;
}
if (!isset($fielddata)) {
if ($flag) {
if ($flag & TBDB_CHECKDBSLOT_WARN) {
# Warn TBOPS
TBERROR("TBFieldData: No slot data for $table/$column!", 0);
}
if ($flag & TBDB_CHECKDBSLOT_ERROR)
return 0;
}
$fielddata = $DBFieldData["default:default"];
}
# Overwrite final entry with toplevel data.
if (isset($toplevel) &&
($toplevel["min"] || $toplevel["max"])) {
$fielddata["min"] = $toplevel["min"];
$fielddata["max"] = $toplevel["max"];
}
return $fielddata;
}
#
# Generic wrapper to check a slot. It is unfortunate that PHP
# does not allow pass by reference args to be optional.
#
function TBcheck_dbslot($token, $table, $column, $flag = 0)
{
global $DBFieldErrstr;
$fielddata = TBFieldData($table, $column, $flag);
if (! $fielddata) {
return 0;
}
$check = $fielddata["check"];
$check_type = $fielddata["check_type"];
$column_type = $fielddata["column_type"];
$min = $fielddata["min"];
$max = $fielddata["max"];
#
# Functional checks not implemented yet.
#
if ($check_type == "function") {
TBERROR("Functional DB checks not implemented! ".
"$token, $table, $column", 1);
}
if (!preg_match("/$check/", "$token")) {
$DBFieldErrstr = "Illegal characters";
return 0;
}
switch ($column_type) {
case "text":
if ((!$min && !max) ||
(strlen("$token") >= $min && strlen("$token") <= $max))
return 1;
break;
case "int":
case "float":
# If both min/max are zero, then skip check; allow anything.
if ((!$min && !max) || ($token >= $min && $token <= $max))
return 1;
break;
default:
TBERROR("TBcheck_dbslot: Unrecognized column_type $column_type", 1);
}
#
# Else fill in error string.
#
switch ($column_type) {
case "text":
if (strlen($token) < $min)
$DBFieldErrstr = "too short - $min chars minimum";
else
$DBFieldErrstr = "too long - $max chars maximum";
break;
case "int":
case "float":
if ($token < $min)
$DBFieldErrstr = "too small - $min minimum value";
else
$DBFieldErrstr = "too large - $max maximum value";
default:
TBERROR("TBcheck_dbslot: Unrecognized column_type $column_type", 1);
}
return 0;
}
# Handy wrappers for checking various fields.
function TBvalid_uid($token) {
return TBcheck_dbslot($token, "users", "uid",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
function TBvalid_pid($token) {
return TBcheck_dbslot($token, "projects", "pid",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
function TBvalid_gid($token) {
return TBcheck_dbslot($token, "groups", "gid",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
function TBvalid_eid($token) {
return TBcheck_dbslot($token, "experiments", "eid",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
function TBvalid_phone($token) {
return TBcheck_dbslot($token, "users", "usr_phone",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
function TBvalid_usrname($token) {
return TBcheck_dbslot($token, "users", "usr_name",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
function TBvalid_email($token) {
return TBcheck_dbslot($token, "users", "usr_email",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
function TBvalid_userdata($token) {
return TBcheck_dbslot($token, "default", "tinytext",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
function TBvalid_title($token) {
return TBvalid_userdata($token);
}
function TBvalid_affiliation($token) {
return TBvalid_userdata($token);
}
function TBvalid_addr($token) {
return TBvalid_userdata($token);
}
function TBvalid_city($token) {
return TBvalid_userdata($token);
}
function TBvalid_state($token) {
return TBvalid_userdata($token);
}
function TBvalid_zip($token) {
return TBvalid_userdata($token);
}
function TBvalid_country($token) {
return TBvalid_userdata($token);
}
function TBvalid_description($token) {
return TBvalid_userdata($token);
}
function TBvalid_integer($token) {
return TBcheck_dbslot($token, "default", "int",
TBDB_CHECKDBSLOT_WARN|TBDB_CHECKDBSLOT_ERROR);
}
\ No newline at end of file
......@@ -2,10 +2,13 @@
#
# Database Constants
#
require("dbcheck.php3");
$TBDBNAME = "@TBDBNAME@";
$TBOPSPID = "emulab-ops";
$TBDB_MINLEN = 2;
# All these constants need to go at some point, replaced by data from
# the regex table.
$TBDB_UIDLEN = 8;
$TBDB_PIDLEN = 12;
$TBDB_GIDLEN = 12;
......@@ -141,66 +144,6 @@ define("TBDB_USER_INTERFACE_PLAB", "plab");
$TBDB_USER_INTERFACE_LIST = array(TBDB_USER_INTERFACE_EMULAB,
TBDB_USER_INTERFACE_PLAB);
# Some regex functions to check various arguments
function TBvalid_uid($uid) {
global $TBDB_UIDLEN, $TBDB_MINLEN;
return (strlen($uid) <= $TBDB_UIDLEN) && (strlen($uid) >= $TBDB_MINLEN) &&
preg_match("/^[a-zA-Z][-\w]+$/", $uid);
}
function TBvalid_pid($pid) {
global $TBDB_PIDLEN, $TBDB_MINLEN;
return (strlen($pid) <= $TBDB_PIDLEN) && (strlen($pid) >= $TBDB_MINLEN) &&
preg_match("/^[a-zA-Z][-\w]+$/", $pid);
}
function TBvalid_gid($gid) {
global $TBDB_GIDLEN, $TBDB_MINLEN;
return (strlen($gid) <= $TBDB_GIDLEN) && (strlen($gid) >= $TBDB_MINLEN) &&
preg_match("/^[a-zA-Z][-\w]+$/", $gid);
}
function TBvalid_eid($eid) {
global $TBDB_EIDLEN, $TBDB_MINLEN;
return (strlen($eid) <= $TBDB_EIDLEN) && (strlen($eid) >= $TBDB_MINLEN) &&
preg_match("/^[a-zA-Z][-\w]+$/", $eid);
}
function TBvalid_phone($phone) {
global $TBDB_PHONELEN;
return (strlen($phone) <= $TBDB_PHONELEN) &&
preg_match("/^[-\d\(\)\+\.x ]+$/", $phone);
}
function TBvalid_usrname($name) {
global $TBDB_USRNAMELEN;
return (strlen($name) <= $TBDB_USRNAMELEN) &&
preg_match("/^[-\w\. ]+$/", $name);
}
function TBvalid_description($token) {
return (strlen($token) <= 256) &&
preg_match("/^[\\040-\\176]*$/", $token);
}
function TBvalid_email($email)
{
global $TBDB_EMAILLEN, $TBDB_MINLEN;
if (strlen($email) < $TBDB_MINLEN || strlen($email) > $TBDB_EMAILLEN)
return 0;
$parts = preg_split("/\@/", $email);
if (!isset($parts[0]) ||
!isset($parts[1]) ||
count($parts) != 2 ||
!preg_match("/^[-\w\+\.]+$/", $parts[0]) ||
!preg_match("/^[-\w\.]+$/", $parts[1]))
return 0;
return 1;
}
#
# Convert a trust string to the above numeric values.
#
......@@ -1974,13 +1917,12 @@ function DBWarn($message)
#
function DBFatal($message)
{
global $TBMAILADDR;
global $PHP_SELF, $DBErrorString;
DBWarn($message);
$text = "$message - In $PHP_SELF\n" .
"$DBErrorString\n";
PAGEERROR("<p><p>".
"Unexpected Error. Could not continue. ".
"Please contact $TBMAILADDR\n");
TBERROR($text, 1);
}
#
......
......@@ -98,7 +98,7 @@ function SPITFORM($formfields, $returning, $errors)
# UserName:
#
echo "<tr>
<td colspan=2>*Username (no blanks, lowercase):</td>
<td colspan=2>*Username (alphanumeric, lowercase):</td>
<td class=left>
<input type=text
name=\"formfields[joining_uid]\"
......@@ -277,7 +277,7 @@ function SPITFORM($formfields, $returning, $errors)
# Project Name:
#
echo "<tr>
<td colspan=2>*Project Name (no blanks):</td>
<td colspan=2>*Project Name:</td>
<td class=left>
<input type=text
name=\"formfields[pid]\"
......@@ -410,42 +410,36 @@ if (! $returning) {
strcmp($formfields[joining_uid], "") == 0) {
$errors["Username"] = "Missing Field";
}
else {
if (! TBvalid_uid($formfields[joining_uid])) {
$errors["UserName"] =
"Must be lowercase alphanumeric only<br>".
"and must begin with a lowercase alpha";
}
elseif (strlen($formfields[joining_uid]) > $TBDB_UIDLEN) {
$errors["UserName"] =
"Too long! Must be less than or to $TBDB_UIDLEN";
}
elseif (TBCurrentUser($formfields[joining_uid])) {
$errors["UserName"] =
"Already in use. Select another";
}
elseif (!TBvalid_uid($formfields[joining_uid])) {
$errors["UserName"] = TBFieldErrorString();
}
if (!isset($formfields[usr_title]) ||
strcmp($formfields[usr_title], "") == 0) {
$errors["Title/Position"] = "Missing Field";
}
elseif (! TBvalid_title($formfields[usr_title])) {
$errors["Title/Position"] = TBFieldErrorString();
}
if (!isset($formfields[usr_name]) ||
strcmp($formfields[usr_name], "") == 0) {
$errors["Full Name"] = "Missing Field";
}
elseif (! TBvalid_usrname($formfields[usr_name])) {
$errors["Full Name"] = "Invalid characters";
$errors["Full Name"] = TBFieldErrorString();
}
if (!isset($formfields[usr_affil]) ||
strcmp($formfields[usr_affil], "") == 0) {
$errors["Affiliation"] = "Missing Field";
}
elseif (! TBvalid_affiliation($formfields[usr_affil])) {
$errors["Affiliation"] = TBFieldErrorString();
}
if (!isset($formfields[usr_email]) ||
strcmp($formfields[usr_email], "") == 0) {
$errors["Email Address"] = "Missing Field";
}
elseif (! TBvalid_email($formfields[usr_email])) {
$errors["Email Address"] = "Looks invalid!";
$errors["Email Address"] = TBFieldErrorString();
}
if (isset($formfields[usr_URL]) &&
strcmp($formfields[usr_URL], "") &&
......@@ -457,28 +451,48 @@ if (! $returning) {
strcmp($formfields[usr_addr], "") == 0) {
$errors["Address 1"] = "Missing Field";
}
elseif (! TBvalid_addr($formfields[usr_addr])) {
$errors["Address 1"] = TBFieldErrorString();
}
# Optional
if (isset($formfields[usr_addr2]) &&
!TBvalid_addr($formfields[usr_addr2])) {
$errors["Address 2"] = TBFieldErrorString();
}
if (!isset($formfields[usr_city]) ||
strcmp($formfields[usr_city], "") == 0) {
$errors["City"] = "Missing Field";
}
elseif (! TBvalid_city($formfields[usr_city])) {
$errors["City"] = TBFieldErrorString();
}
if (!isset($formfields[usr_state]) ||
strcmp($formfields[usr_state], "") == 0) {
$errors["State"] = "Missing Field";
}
elseif (! TBvalid_state($formfields[usr_state])) {
$errors["State"] = TBFieldErrorString();
}
if (!isset($formfields[usr_zip]) ||
strcmp($formfields[usr_zip], "") == 0) {
$errors["ZIP/Postal Code"] = "Missing Field";
}
elseif (! TBvalid_zip($formfields[usr_zip])) {
$errors["Zip/Postal Code"] = TBFieldErrorString();
}
if (!isset($formfields[usr_country]) ||
strcmp($formfields[usr_country], "") == 0) {
$errors["Country"] = "Missing Field";
}
elseif (! TBvalid_country($formfields[usr_country])) {
$errors["Country"] = TBFieldErrorString();
}
if (!isset($formfields[usr_phone]) ||
strcmp($formfields[usr_phone], "") == 0) {
$errors["Phone #"] = "Missing Field";
}
elseif (!TBvalid_phone($formfields[usr_phone])) {
$errors["Phone"] = "Invalid characters";
$errors["Phone #"] = TBFieldErrorString();
}
if (!isset($formfields[password1]) ||
strcmp($formfields[password1], "") == 0) {
......
......@@ -372,7 +372,7 @@ $defaults = array();
# Construct a defaults array based on current DB info. Used for the initial
# form, and to determine if any changes were made. This is to avoid churning
# the passwd file for no reason, given that most people use this page
# simply yo change their password.
# simply to change their password.
#
$row = mysql_fetch_array($query_result);
$defaults[target_uid] = $target_uid;
......@@ -413,17 +413,23 @@ if (!isset($formfields[usr_title]) ||
strcmp($formfields[usr_title], "") == 0) {
$errors["Title/Position"] = "Missing Field";
}
elseif (! TBvalid_title($formfields[usr_title])) {
$errors["Title/Position"] = TBFieldErrorString();
}
if (!isset($formfields[usr_name]) ||
strcmp($formfields[usr_name], "") == 0) {
$errors["Full Name"] = "Missing Field";
}
elseif (! TBvalid_usrname($formfields[usr_name])) {
$errors["Full Name"] = "Invalid characters";
$errors["Full Name"] = TBFieldErrorString();
}
if (!isset($formfields[usr_affil]) ||
strcmp($formfields[usr_affil], "") == 0) {
$errors["Affiliation"] = "Missing Field";
}
elseif (! TBvalid_affiliation($formfields[usr_affil])) {
$errors["Affiliation"] = TBFieldErrorString();
}
if (!isset($formfields[usr_shell]) ||
!in_array($formfields[usr_shell], $shelllist)) {
$errors["Shell"] = "Invalid Shell";
......@@ -433,7 +439,7 @@ if (!isset($formfields[usr_email]) ||
$errors["Email Address"] = "Missing Field";
}
elseif (! TBvalid_email($formfields[usr_email])) {
$errors["Email Address"] = "Looks invalid!";
$errors["Email Address"] = TBFieldErrorString();
}
if (isset($formfields[usr_URL]) &&
strcmp($formfields[usr_URL], "") &&
......@@ -445,7 +451,7 @@ if (!$isadmin) {
# Admins can leave these fields blank, but must error check them anyway.
if (!isset($formfields[usr_addr]) ||
strcmp($formfields[usr_addr], "") == 0) {
$errors["Postal Address"] = "Missing Field";
$errors["Postal Address 1"] = "Missing Field";
}
if (!isset($formfields[usr_city]) ||
strcmp($formfields[usr_city], "") == 0) {
......@@ -468,9 +474,34 @@ if (!$isadmin) {
$errors["Phone #"] = "Missing Field";
}
}
if (isset($formfields[usr_addr]) &&
!TBvalid_addr($formfields[usr_addr])) {
$errors["Postal Address 1"] = TBFieldErrorString();
}
# Optional
if (isset($formfields[usr_addr2]) &&
!TBvalid_addr($formfields[usr_addr2])) {
$errors["Postal Address 2"] = TBFieldErrorString();
}
if (isset($formfields[usr_city]) &&
!TBvalid_city($formfields[usr_city])) {
$errors["City"] = TBFieldErrorString();
}
if (isset($formfields[usr_state]) &&
!TBvalid_state($formfields[usr_state])) {
$errors["State"] = TBFieldErrorString();
}
if (isset($formfields[usr_zip]) &&
!TBvalid_zip($formfields[usr_zip])) {
$errors["Zip/Postal Code"] = TBFieldErrorString();
}
if (isset($formfields[usr_country]) &&
!TBvalid_country($formfields[usr_zip])) {
$errors["Zip/Postal Code"] = TBFieldErrorString();
}