From a35e40cb40430caaaba6875ae0b8ee4e4b72dfdc Mon Sep 17 00:00:00 2001
From: "Leigh B. Stoller" <stoller@flux.utah.edu>
Date: Wed, 3 Oct 2007 21:09:10 +0000
Subject: [PATCH] All new and improved form definition support. All forms will
 be implemented declaritively, and then rendered by the support code in
 form_defs.php. The best thing to do is look at newosid.php with this checkin,
 but there is also some good code in form_example.php.

---
 www/form_defs.php    | 446 +++++++++++++++++++++++++++++++++++++++
 www/form_example.php | 136 ++++++++++++
 www/newosid.php3     | 490 +++++++++++++++++--------------------------
 3 files changed, 770 insertions(+), 302 deletions(-)
 create mode 100644 www/form_defs.php
 create mode 100644 www/form_example.php

diff --git a/www/form_defs.php b/www/form_defs.php
new file mode 100644
index 0000000000..ef87d029e1
--- /dev/null
+++ b/www/form_defs.php
@@ -0,0 +1,446 @@
+<?php
+#
+# EMULAB-COPYRIGHT
+# Copyright (c) 2006, 2007 University of Utah and the Flux Group.
+# All rights reserved.
+#
+$footnotes = null;
+
+# The idea behind this is simplify and make all of the form construction
+# coherrent across the entire web interface. Steps to creating a form:
+#
+# 1) Create an array of attributes for the form.
+#
+#   $form = array('#id'	      => 'myform',	# Optional; default: myform
+#	  	  '#action'   => 'foo.php',       # Required
+#		  '#method'   => 'POST',          # Optional; default POST
+#		  '#class'    => 'standard',      # Required; default standard
+#		  '#caption'  => 'A Form',        # Optional; default ''
+#		  '#enctype'  => '');             # Optional
+#
+# 2) Create an array of form fields:
+#
+#     $fields = array();
+#     $fields['Name'] =
+#          array('#type'       => 'textfield',	# Required
+#		 '#label'      => 'Full Name',  # Required
+#		 '#description'=> 'Your Name',  # Optional (extra text)
+#                '#link'       => 'foo.html',   # Optional (link for label).
+#		 '#size'       => 30,           # Optional
+#		 '#maxlength'  => 30,           # Optional
+#		 '#required'   => TRUE,         # Optional
+#                '#mouseover'  => 'Mouse Me',   # Optional string over label
+#		 '#footnote'   => 'See ...',    # Optional footnote section.
+#		 '#javascript' => "...");       # Optional
+#
+# 3) Call FormRender with the above, plus optional $errors and $values
+#    arrays. Both of these are exactly as we use them now:
+#
+#	FormRender($form, $fields, $errors, $values);
+#
+#   which spits the html to the output stream.
+#
+# 4) The 'action' page will get $submit and $formfields as input.
+#
+# * See form_example.php for a good example usage.
+#
+function FormRenderTextField($name, $attrs)
+{
+    $type = ($attrs['#type'] == "password" ? "password" : "text");
+	
+    $html = "<input type=$type name=\"formfields[$name]\" ";
+    if (isset($attrs['#value'])) {
+	$html .= "value=\"" . $attrs['#value'] . "\" ";
+    }
+    if (isset($attrs['#javascript'])) {
+	$html .= $attrs['#javascript'] . " ";
+    }
+    if (isset($attrs['#class'])) {
+	$html .= "class=\"" . $attrs['#class'] . "\" ";
+    }
+    else {
+	$html .= "class=\"form-text\" ";
+    }
+    if (isset($attrs['#size'])) {
+	$html .= "size=" . $attrs['#size'] . " ";
+    }
+    if (isset($attrs['#maxlength'])) {
+	$html .= "maxlength=" . $attrs['#maxlength'] . " ";
+    }
+    $html .= ">";
+    
+    return $html;
+}
+
+function FormRenderCheckBox($name, $attrs)
+{
+    $html = "<input type=checkbox name=\"formfields[$name]\" ";
+    if (isset($attrs['#return_value'])) {
+	$html .= "value=\"" . $attrs['#return_value'] . "\" ";
+	if (isset($attrs['#value']) &&
+	    $attrs['#value'] == $attrs['#return_value']) {
+	    $html .= "checked ";
+	}
+    }
+    if (isset($attrs['#class'])) {
+	$html .= "class=\"" . $attrs['#class'] . "\" ";
+    }
+    else {
+	$html .= "class=\"form-checkbox\" ";
+    }
+    if (isset($attrs['#javascript'])) {
+	$html .= $attrs['#javascript'] . " ";
+    }
+    $html .= ">";
+    
+    return $html;
+}
+
+function FormRenderRadio($name, $attrs)
+{
+    $html = "";
+    
+    while (list ($subname, $subattrs) = each ($attrs['#radios'])) {
+	$html .= "<input type=radio name=\"formfields[$name]\" ";
+	if (isset($attrs['#class'])) {
+	    $html .= "class=\"" . $attrs['#class'] . "\" ";
+	}
+	else {
+	    $html .= "class=\"form-radio\" ";
+	}
+	if (isset($subattrs['#return_value'])) {
+	    $html .= "value=\"" . $subattrs['#return_value'] . "\" ";
+	    if (isset($attrs['#value']) &&
+		$attrs['#value'] == $subattrs['#return_value']) {
+		$html .= "checked ";
+	    }
+	}
+	if (isset($attrs['#javascript'])) {
+	    $html .= $attrs['#javascript'] . " ";
+	}
+	$html .= ">";
+	if (isset($subattrs['#label']))
+	    $html .= $subattrs['#label'] . " &nbsp; ";
+	$html .= "\n";
+    }
+    return $html;
+}
+
+function FormRenderSelect($name, $attrs)
+{
+    $html = "<select name=\"formfields[$name]\" ";
+    if (isset($attrs['#class'])) {
+	$html .= "class=\"" . $attrs['#class'] . "\" ";
+    }
+    else {
+	$html .= "class=\"form-select\" ";
+    }
+    if (isset($attrs['#javascript'])) {
+	$html .= $attrs['#javascript'] . " ";
+    }
+    $html .= ">\n";
+    $html .= "<option value=''>Please Select &nbsp</option>\n";
+
+    if (isset($attrs['#options'])) {
+	while (list ($selectvalue, $selectlabel) = each ($attrs['#options'])) {
+	    $selected = "";	    
+	    if (isset($attrs['#value']) && $attrs['#value'] == $selectvalue) {
+		$selected = "selected";
+	    }
+	    $html .= "<option $selected value='$selectvalue'>";
+	    $html .= "$selectlabel </option>\n";
+	}
+    }
+    $html .= "</select>\n";
+    return $html;
+}
+
+function FormRenderFile($name, $attrs)
+{
+    $html = "<input type=file name=\"$name\" ";
+    if (isset($attrs['#value'])) {
+	$html .= "value=\"" . $attrs['#value'] . "\" ";
+    }
+    if (isset($attrs['#javascript'])) {
+	$html .= $attrs['#javascript'] . " ";
+    }
+    if (isset($attrs['#class'])) {
+	$html .= "class=\"" . $attrs['#class'] . "\" ";
+    }
+    else {
+	$html .= "class=\"form-file\" ";
+    }
+    if (isset($attrs['#size'])) {
+	$html .= "size=" . $attrs['#size'] . " ";
+    }
+    $html .= ">";
+    
+    return $html;
+}
+
+function FormRenderSubmit($name, $attrs)
+{
+    $html = "";
+
+    $html .= "<td align=center colspan=2>";
+    $html .= "<input type=submit name=\"$name\" ";
+    if (isset($attrs['#value'])) {
+	$html .= "value=\"" . $attrs['#value'] . "\" ";
+    }
+    else {
+	$html .= "value=Submit";
+    }
+    if (isset($attrs['#class'])) {
+	$html .= "class=\"" . $attrs['#class'] . "\" ";
+    }
+    else {
+	$html .= "class=\"form-submit\" ";
+    }
+    if (isset($attrs['#javascript'])) {
+	$html .= $attrs['#javascript'] . " ";
+    }
+    $html .= "></td>";
+    
+    return $html;
+}
+
+# Render a subsection (table) of a form.
+function FormRenderTable($name, $attributes, $submitted)
+{
+    $html = "<table align=center border=1>\n";
+    $html .= FormRenderElements($attributes['#fields'], $submitted);
+    $html .= "</table>\n";
+    return $html;
+}
+
+function FormRenderElement($name, $attributes, $submitted)
+{
+    $field_html = null;
+
+    #
+    # The value that was submitted overrides the value in the attributes.
+    # For most things, we just munge the attributes field.
+    #
+    if ($submitted && array_key_exists($name, $submitted)) {
+	$attributes['#value'] = $submitted[$name];
+    }
+    
+    switch ($attributes['#type']) {
+    case "textfield":
+    case "password":
+	$field_html = FormRenderTextField($name, $attributes);
+	break;
+    case "hidden":
+	$value = $attributes['#value'];
+	$field_html .= "<input type=hidden name=$name value=\"$value\">\n";
+	break;
+    case "submit":
+	$field_html = FormRenderSubmit($name, $attributes);
+	break;
+    case "checkbox":
+	$field_html = FormRenderCheckBox($name, $attributes);
+	break;
+    case "radio":
+	$field_html = FormRenderRadio($name, $attributes);
+	break;
+    case "file":
+	$field_html = FormRenderFile($name, $attributes);
+	break;
+    case "checkboxes":
+	while (list ($subname, $subattrs) = each ($attributes['#boxes'])) {
+	    if ($submitted && array_key_exists($subname, $submitted)) {
+		$subattrs['#value'] = $submitted[$subname];
+	    }
+	    $field_html .= FormRenderCheckBox($subname, $subattrs);
+	    if (isset($subattrs['#label']))
+		$field_html .= $subattrs['#label'] . " &nbsp; ";
+	}
+	break;
+    case "select":
+	$field_html = FormRenderSelect($name, $attributes);
+	break;
+    case "table":
+	$field_html = FormRenderTable($name, $attributes, $submitted);
+	break;
+    }
+    return $field_html;
+}
+
+function FormRenderElements($fields, $submitted)
+{
+    global $footnotes;
+    $html = "";
+    
+    while (list ($name, $attributes) = each ($fields)) {
+	$field_html = FormRenderElement($name, $attributes, $submitted);
+
+	if ($field_html) {
+	    if ($attributes['#type'] == "hidden") {
+		$html .= $field_html;
+		continue;
+	    }
+	    $cols  = "";
+	    if ($attributes['#type'] == "table")
+		$cols = "colspan=2";
+
+	    $mouseover = "";
+	    if (isset($attributes['#mouseover'])) {
+		$mouseover = FormRenderMouseOver($attributes['#mouseover']);
+	    }
+
+	    # Record footnote for later.
+	    $footnote = "";
+	    if (isset($attributes['#footnote'])) {
+		$thisnote = 0;
+		
+		#
+		# Slight complication; we want to be able to specify the
+		# same footnote multiple times, but show it only once.
+		#
+		foreach ($footnotes as $i => $note) {
+		    if ($note == $attributes['#footnote']) {
+			$thisnote = $i + 1;
+			break;
+		    }
+		}
+		if (! $thisnote) {
+		    $thisnote = count($footnotes) + 1;
+		    $footnotes[] = $attributes['#footnote'];
+		}
+		$footnote = "[<b>$thisnote</b>]";
+	    }
+		
+	    $html .= "<tr>";
+	    if ($attributes['#type'] != "submit") {
+		$html .= "<td $mouseover $cols>";
+
+		# Required fields mark with *
+		if (isset($attributes['#required']) &&
+		    $attributes['#required'])
+		    $html .= "*";
+
+		$label = $attributes['#label'];
+		if (isset($attributes['#link']))
+		    $label = "<a href=\"" . $attributes['#link'] . "\"" .
+			"target=_blank>$label</a>";
+		$html .= $label . $footnote . ": ";
+		if (isset($attributes['#description']))
+		    $html .= "<br><font size=-2>(" .
+			$attributes['#description'] . ")";
+		if ($attributes['#type'] == "table") {
+		    $html .= "$field_html</td>";
+		}
+		else {
+		    $html .= "</td>";
+		    $html .= "<td>$field_html</td>";
+		}
+	    }
+	    else 
+		$html .= "$field_html";
+	    $html .= "</tr>\n";
+	}
+    }
+    return $html;
+}
+
+function FormRenderMouseOver($string)
+{
+    $string = ereg_replace("\n", "<br>", $string);
+    $string = ereg_replace("\r", "", $string);
+    $string = htmlentities($string);
+    $string = preg_replace("/\'/", "\&\#039;", $string);
+
+    return "onmouseover=\"return escape('$string')\"";
+}
+
+function FormRender($attributes, $errors, $fields, $submitted = null)
+{
+    global $footnotes;
+    
+    $html = "";
+    $footnotes = array();
+
+    $action = $attributes['#action'];
+    $id = "myform";
+    if (array_key_exists('#id', $attributes))
+	$id = $attributes['#id'];
+    $caption = null;
+    if (array_key_exists('#caption', $attributes))
+	$caption = $attributes['#caption'];
+    $method = "POST";
+    if (array_key_exists('#method', $attributes))
+	$method = $attributes['#method'];
+    $enctype = "";
+    if (array_key_exists('#enctype', $attributes))
+	$enctype = "enctype=" . $attributes['#enctype'];
+    $class = "standard";
+    if (array_key_exists('#class', $attributes))
+	$class = $attributes['#class'];
+
+    if ($errors) {
+	$html .= "<table class=nogrid border=0 cellpadding=6 cellspacing=0>";
+	$html .= "<tr><th align=center colspan=2>";
+	$html .= "<font size=+1 color=red>";
+	$html .= "&nbsp;Oops, please fix the following errors!&nbsp;";
+	$html .= "</font></td></tr>\n";
+	
+	while (list ($name, $message) = each ($errors)) {
+	    $html .= "<tr><td align=right>";
+	    $html .= "<font color=red>$name:&nbsp;</font></td>";
+	    $html .= "<td align=left><font color=red>$message</font></td>";
+	    $html .= "</tr>\n";
+	}
+	$html .= "</table><br><br>\n";
+    }
+
+    $html .= "<table align=center border=1>\n";
+    if ($caption)
+	$html .= "<caption>$caption</caption>\n";
+    $html .= "<tr><td align=center colspan=2>";
+    $html .= "<em>(Fields marked with * are required)</em></td></tr>";
+
+    $html .= "<form action='$action' $enctype method=$method id=$id ";
+    $html .= "class='$class'>";
+    $html .= FormRenderElements($fields, $submitted);
+    $html .= "</form>";
+    $html .= "</table>\n";
+
+    if (count($footnotes)) {
+	$html .= "<div align=left><h4><ol>\n";
+	foreach ($footnotes as $i => $note) {
+	    $html .= "<li>$note\n";
+	}
+	$html .= "</ol></h4></div>\n";
+    }
+    
+    echo "$html\n";
+}
+
+function FormValidate($form, &$errors, $fields, $submitted)
+{
+    while (list ($name, $attributes) = each ($fields)) {
+        # Check for required fields not filled out
+	if (isset($attributes['#required']) && $attributes['#required'] &&
+	    !(isset($submitted[$name]) && $submitted[$name] != "")) {
+	    $errors[$attributes['#label']] = "Missing required value";
+	}
+	else if (isset($attributes['#checkslot']) &&
+		 isset($submitted[$name]) && $submitted[$name] != "") {
+	    # Check slot
+	    if (preg_match("/^([-\w]+):([-\w]+)$/",
+			   $attributes['#checkslot'], $matches)) {
+
+		if (!TBcheck_dbslot($submitted[$name],
+				    $matches[1], $matches[2],
+				    TBDB_CHECKDBSLOT_WARN|
+				    TBDB_CHECKDBSLOT_ERROR)) {
+		    $errors[$attributes['#label']] = TBFieldErrorString();
+		}
+	    }
+	    else {
+		TBERROR("Could not parse " . $attributes['#checkslot'], 1);
+	    }
+	}
+    }
+}
+?>
diff --git a/www/form_example.php b/www/form_example.php
new file mode 100644
index 0000000000..a0e27a855c
--- /dev/null
+++ b/www/form_example.php
@@ -0,0 +1,136 @@
+<?php
+#
+# EMULAB-COPYRIGHT
+# Copyright (c) 2000-2007 University of Utah and the Flux Group.
+# All rights reserved.
+#
+include("defs.php3");
+include("form_defs.php");
+
+PAGEHEADER("Silly Forms example");
+
+#
+# Only known and logged in users.
+#
+$this_user = CheckLoginOrDie();
+$uid       = $this_user->uid();
+
+$optargs = OptionalPageArguments("submit",      PAGEARG_STRING,
+				 "formfields",  PAGEARG_ARRAY);
+if (!isset($formfields)) {
+     $formfields = null;
+}
+
+# The form attributes:
+$form = array('#id'	  => 'form1',
+	      '#caption'  => 'My Form',
+	      '#action'   => 'form_example.php');
+
+# A set of form fields.
+$fields = array();
+
+# Text field.
+$fields['slot1'] = array('#type'        => 'textfield',
+			 '#label'       => 'Slot1',
+			 '#value'       => 'Hello World',
+			 '#size'        => 60,
+			 '#maxlength'   => 64,
+			 '#description' => 'Alphanumeric, No Blanks'
+			 );
+
+# Password
+$fields['slot2'] = array('#type'	 => 'password',
+			 '#label'        => 'Password',
+			 '#required'     => TRUE,
+			 '#footnote'     => 'This is a footnote',
+			 '#size'         => 8);
+
+# File Upload. You must set '#entype' in the form array.
+$fields['myfile'] = array('#type'        => 'file',
+			  '#label'       => 'Your File',
+			  '#size'        => 30,
+			  '#description' => 'An NS File'
+			  );
+
+# A plain checkbox
+$fields['slot3']  = array('#type'        => 'checkbox',
+			  '#return_value'=> "Yep",
+			  '#label'       => 'Check this Box',
+			  );
+
+# A list of checkboxes
+$fields['slot4']  = array('#type'        => 'checkboxes',
+			  '#label'       => 'Check some of these',
+			  '#boxes'       =>
+			    array('box1' => array('#return_value' => "Yep",
+						  '#label' => 'L1'
+						  ),
+				  'box2' => array('#return_value' => "Yep",
+						  '#label' => 'L2'
+						  ),
+				  'box3' => array('#return_value' => "Yep",
+						  '#label' => 'L3'
+						  ),
+				  ),
+			  );
+
+# A radio checklist.
+$fields['slot5']  = array('#type'       => 'radio',
+			  '#label'      => 'Check one of these',
+			  '#radios'     =>
+			   array('Rad1' => array('#label' => 'R1',
+						 '#return_value' => "R1v",
+						 ),
+				 'Rad2' => array('#label' => 'R2',
+						 '#return_value' => "R2v",
+						 ),
+				 'Rad3' => array('#label' => 'R3',
+						 '#return_value' => "R3v",
+						 ),
+				 ),
+			  );
+
+# A selection list.
+$fields['slot6']  = array('#type'       => 'select',
+			  '#label'      => 'A selection of items',
+			  '#default_value' => 'B',
+			  '#options'    => array('A' => 'Pick A',
+						 'B' => 'Pick B',
+						 'C' => 'Pick C'),
+			  '#description'=> 'Bla Bla Bla'
+			  );
+
+# A hidden Field.
+$fields['slot7']  = array('#type'  => 'hidden',
+			  '#value' => "69",
+			  );
+
+# A simple subsection (rendered as an inner table).
+$fields['address'] = array('#type'   => 'table',
+			   '#label'  => 'Fill in your addresss',
+			   '#fields' =>
+			    array('part1' => array('#type' => 'textfield',
+						   '#label' => 'Street',
+						   '#size' => 60,
+						   ),
+				  'part2' => array('#type' => 'textfield',
+						   '#label' => 'Town',
+						   '#value' => 'Corvallis',
+						   '#size' => 30,
+						   ),
+				  ),
+			   );
+# The submit button.				
+$fields['submit']  = array('#type'  => 'submit',
+			   '#value' => "Submit This Form",
+			   );
+
+echo "<center>";
+FormRender($form, null, $fields, $formfields);
+echo "</center>";
+
+#
+# Standard Testbed Footer
+# 
+PAGEFOOTER();
+?>
diff --git a/www/newosid.php3 b/www/newosid.php3
index db89f06b90..08b711fe28 100644
--- a/www/newosid.php3
+++ b/www/newosid.php3
@@ -7,6 +7,7 @@
 include("defs.php3");
 include_once("osinfo_defs.php");
 include("osiddefs.php3");
+include("form_defs.php");
 
 #
 # Standard Testbed Header
@@ -36,284 +37,191 @@ if (! count($projlist)) {
     USERERROR("You do not appear to be a member of any Projects in which ".
 	      "you have permission to create new OS Descriptors!", 1);
 }
+$projselection = array();
+while (list($project) = each($projlist)) {
+    $projselection[$project] = $project;
+}
 
 #
-# Spit the form out using the array of data. 
-# 
-function SPITFORM($formfields, $errors)
-{
-    global $this_user, $projlist, $isadmin;
-    global $osid_opmodes, $osid_oslist, $osid_featurelist;
-    global $TBDB_OSID_OSNAMELEN, $TBDB_OSID_OSNAMELEN;
-    global $TBDB_OSID_VERSLEN, $TBDB_OSID_VERSLEN, $TBBASE;
-
-    if ($errors) {
-	echo "<table class=nogrid
-                     align=center border=0 cellpadding=6 cellspacing=0>
-              <tr>
-                 <th align=center colspan=2>
-                   <font size=+1 color=red>
-                      &nbsp;Oops, please fix the following errors!&nbsp;
-                   </font>
-                 </td>
-              </tr>\n";
-
-	while (list ($name, $message) = each ($errors)) {
-	    echo "<tr>
-                     <td align=right>
-                       <font color=red>$name:&nbsp;</font></td>
-                     <td align=left>
-                       <font color=red>$message</font></td>
-                  </tr>\n";
-	}
-	echo "</table><br>\n";
-    }
-
-    echo "<br>
-          <table align=center border=1> 
-          <tr>
-             <td align=center colspan=2>
-                 <em>(Fields marked with * are required)</em>
-             </td>
-          </tr>
-          <form action='newosid.php3' method=post name=idform>\n";
-
-    #
-    # Select Project
-    #
-    echo "<tr>
-              <td>*Select Project:</td>
-              <td><select name=\"formfields[pid]\">
-                      <option value=''>Please Select &nbsp</option>\n";
-    
-    while (list($project) = each($projlist)) {
-	$selected = "";
+# Define the form.
+#
+$form = array('#id'	  => 'myform',
+	      '#action'   => "newosid.php3");
+$fields = array();
 
-	if ($formfields["pid"] == $project)
-	    $selected = "selected";
-	
-	echo "        <option $selected value='$project'>$project </option>\n";
-    }
-    echo "       </select>";
-    echo "    </td>
-          </tr>\n";
+#
+# Project Name:
+#
+$fields['pid'] = array('#type'	     => 'select',
+		       '#label'      => 'Project',
+		       '#options'    => $projselection,
+		       '#checkslot'  => 'os_info:pid',
+		       '#required'   => TRUE);
+#
+# OS Name
+#
+$fields['osname'] = array('#type'	=> 'textfield',
+			  '#label'      => 'Descriptor Name',
+			  '#description'=> 'alphanumeric, no spaces',
+			  '#size'	=> $TBDB_OSID_OSNAMELEN,
+			  '#maxlength'  => $TBDB_OSID_OSNAMELEN,
+			  '#checkslot'  => 'os_info:osname',
+			  '#required'   => TRUE);
 
-    #
-    # OS Name
-    #
-    echo "<tr>
-              <td>*Descriptor Name (no blanks):</td>
-              <td><input type=text
-                         name=\"formfields[osname]\"
-                         value=\"" . $formfields["osname"] . "\"
-                         size=$TBDB_OSID_OSNAMELEN
-                         maxlength=$TBDB_OSID_OSNAMELEN>
-                  </td>
-          </tr>\n";
+#
+# Description
+#
+$fields['description'] =
+    array('#type'	=> 'textfield',
+	  '#label'      => 'Description',
+	  '#description'=> 'a short pithy sentence',
+	  '#size'	=> 50,
+	  '#checkslot'  => 'os_info:description',
+	  '#required'   => TRUE);
 
-    
-    #
-    # Description
-    #
-    echo "<tr>
-              <td>*Description:<br>
-                  (a short pithy sentence)</td>
-              <td class=left>
-                  <input type=text
-                         name=\"formfields[description]\"
-                         value=\"" . $formfields["description"] . "\"
-	                 size=50>
-              </td>
-          </tr>\n";
+#
+# Select an OS
+#
+$OSselection = array();
+while (list ($os, $userokay) = each($osid_oslist)) {
+    if (!$userokay && !$isadmin)
+	continue;
+    $OSselection[$os] = $os;
+}
+$fields['OS'] = array('#type'	    => 'select',
+		      '#label'      => 'Select OS',
+		      '#options'    => $OSselection,
+		      '#checkslot'  => 'os_info:OS',
+		      '#required'   => TRUE);
 
-    #
-    # Select an OS
-    # 
-    echo "<tr>
-              <td>*Select OS:</td>
-              <td><select name=\"formfields[OS]\">\n";
+#
+# Version String
+#
+$fields['version'] =
+    array('#type'	=> 'textfield',
+	  '#label'      => 'Version',
+	  '#size'	=> $TBDB_OSID_VERSLEN,
+	  '#maxlength'	=> $TBDB_OSID_VERSLEN,
+	  '#checkslot'  => 'os_info:version',
+	  '#required'   => TRUE);
 
-    while (list ($os, $userokay) = each($osid_oslist)) {
-        if (!$userokay && !$isadmin)
-	    continue;
+#
+# Path to Multiboot image.
+#
+$fields['path'] =
+    array('#type'	=> 'textfield',
+	  '#label'      => 'Path',
+	  '#checkslot'  => 'os_info:path',
+	  '#size'	=> 40);
 
-	$selected = "";
-	if ($formfields["OS"] == $os)
-	    $selected = "selected";
+#
+# Magic string
+#
+$fields['magic'] =
+    array('#type'	=> 'textfield',
+	  '#label'      => 'Magic',
+	  '#description'=> 'ie: uname -r -s',
+	  '#checkslot'  => 'os_info:magic',
+	  '#size'	=> 30);
 
-	echo "<option $selected value=$os>$os &nbsp; </option>\n";
-    }
-    echo "       </select>
-              </td>
-          </tr>\n";
+#
+# OS Features
+#
+$FeatureBoxes = array();
+while (list ($feature, $userokay) = each($osid_featurelist)) {
+    if (!$userokay && !$isadmin)
+	continue;
+    $FeatureBoxes["os_feature_$feature"] = array('#return_value'=> "checked",
+						 '#label'       => $feature);
+}
+$fields['features'] =
+    array('#type'	=> 'checkboxes',
+	  '#label'      => 'OS Features',
+	  '#boxes'      => $FeatureBoxes);
 
+#
+# Op Mode
+#
+$OpmodeSelection = array();
+while (list ($mode, $userokay) = each($osid_opmodes)) {
+    if (!$userokay && !$isadmin)
+	continue;
+    $OpmodeSelection[$mode] = $mode;
+}
+$fields['op_mode'] =
+    array('#type'	=> 'select',
+	  '#label'      => 'Operational Mode',
+	  '#options'    => $OpmodeSelection,
+	  '#checkslot'  => 'os_info:op_mode',
+	  '#required'   => TRUE);
+
+if ($isadmin) {
     #
-    # Version String
+    # Shared?
     #
-    echo "<tr>
-              <td>*Version:</td>
-              <td><input type=text
-                         name=\"formfields[version]\"
-                         value=\"" . $formfields["version"] . "\"
-                         size=$TBDB_OSID_VERSLEN maxlength=$TBDB_OSID_VERSLEN>
-              </td>
-          </tr>\n";
-
+    $fields['shared'] =
+	array('#type'        => 'checkbox',
+	      '#return_value'=> 1,
+	      '#label'       => 'Global?',
+	      '#checkslot'   => 'os_info:shared',
+	      '#description' => 'available to all projects');
     #
-    # Path to Multiboot image.
+    # Mustclean?
     #
-    echo "<tr>
-              <td>Path:</td>
-              <td><input type=text
-                         name=\"formfields[path]\"
-                         value=\"" . $formfields["path"] . "\"
-                         size=40>
-              </td>
-          </tr>\n";
-
+    $fields['mustclean'] =
+	array('#type'        => 'checkbox',
+	      '#return_value'=> 1,
+	      '#label'       => 'Clean?',
+	      '#checkslot'   => 'os_info:mustclean',
+	      '#description' => 'no disk load required');
+    
     #
-    # Magic string?
+    # Reboot Waittime. 
     #
-    echo "<tr>
-              <td>Magic (ie: uname -r -s):</td>
-              <td><input type=text
-                         name=\"formfields[magic]\"
-                         value=\"" . $formfields["magic"] . "\"
-                         size=30>
-              </td>
-          </tr>\n";
-
-    echo "<tr>
-              <td>OS Features:</td>
-              <td>";
-
-    reset($osid_featurelist);
-    while (list ($feature, $userokay) = each($osid_featurelist)) {
-	if (!$userokay && !$isadmin)
-	    continue;
-
-	$checked = "";
-	    
-	if (isset($formfields["os_feature_$feature"]) &&
-	    ! strcmp($formfields["os_feature_$feature"], "checked"))
-	    $checked = "checked";
-
-	echo "<input $checked type=checkbox value=checked
-	 	 name=\"formfields[os_feature_$feature]\">$feature &nbsp\n";
-    }
-    echo "<p>Guidelines for setting os_features for your OS:
-              <ol>
-                <li> Mark ping and/or ssh if they are supported.
-                <li> If you use a testbed kernel, or are based on a
-                     testbed kernel config, mark the ipod box.
-                <li> If it is based on a testbed image or sends its own
-                     isup, mark isup. 
-              </ol>
-            </td>
-         </tr>\n";
+    $fields['reboot_waittime'] =
+	array('#type'	     => 'textfield',
+	      '#label'       => 'Reboot Waittime',
+	      '#description' => 'seconds',
+	      '#checkslot'   => 'os_info:reboot_waittime',
+	      '#size'	     => 6);
 
-    
     #
-    # Op Mode
+    # NextOsid
     #
-    echo "<tr>
-	      <td>*Operational Mode[<b>4</b>]:</td>
-	      <td><select name=\"formfields[op_mode]\">
-		         <option value=none>Please Select </option>\n";
-
-    while (list ($mode, $userokay) = each($osid_opmodes)) {
-	$selected = "";
-
-	if (!$userokay && !$isadmin)
-	    continue;
-
-	if (isset($formfields["op_mode"]) &&
-	    strcmp($formfields["op_mode"], $mode) == 0)
-	    $selected = "selected";
-
-	echo "<option $selected value=$mode>$mode &nbsp; </option>\n";
-    }
-    echo "       </select>
-             <p>
-              Guidelines for setting op_mode for your OS:
-              <ol>
-                <li> If it is based on a testbed image (one of our
-                     Linux, Fedora, FreeBSD or Windows images) use the same
-                     op_mode as that image. Select it from the
-                     <a href=\"$TBBASE/showosid_list.php3\"
-                     >OS Descriptor List</a> to find out).
-                <li> If not, use MINIMAL.
-              </ol>
-	     </td>
-	  </tr>\n";
-
-    if ($isadmin) {
-        #
-        # Shared?
-        #
-	echo "<tr>
-	          <td>Global?:<br>
-                      (available to all projects)</td>
-                  <td><input type=checkbox
-			     name=\"formfields[shared]\"
-			     value=Yep";
-	
-	if (isset($formfields["shared"]) &&
-	    strcmp($formfields["shared"], "Yep") == 0)
-	    echo "           checked";
-	    
-	echo "                       > Yes
-		  </td>
-	      </tr>\n";
-
-        #
-        # Mustclean?
-        #
-	echo "<tr>
-	          <td>Clean?:<br>
-                  (no disk reload required)</td>
-                  <td><input type=checkbox
-			     name=\"formfields[mustclean]\"
-			     value=Yep";
-	
-	if (isset($formfields["mustclean"]) &&
-	    strcmp($formfields["mustclean"], "Yep") == 0)
-	    echo "           checked";
-	    
-	echo "                       > Yes
-		  </td>
-	      </tr>\n";
-	
-        #
-        # Reboot Waittime. 
-        #
-	echo "<tr>
-	          <td>Reboot Waittime (seconds)</td>
-                  <td><input type=text
-                             name=\"formfields[reboot_waittime]\"
-                             value=\"" . $formfields["reboot_waittime"] ."\"
-                             size=6>
-                  </td>
-              </tr>\n";
-    
-	$osid_result =
-	    DBQueryFatal("select * from os_info ".
-			 "where (path='' or path is NULL) and ".
-			 "      version!='' and version is not NULL ".
-			 "order by pid,osname");
-    
-	WRITEOSIDMENU("NextOsid", "formfields[nextosid]", $osid_result,
-		      $formfields["nextosid"]);
+    $osid_result =
+	DBQueryFatal("select * from os_info ".
+		     "where (path='' or path is NULL) and ".
+		     "      version!='' and version is not NULL ".
+		     "order by pid,osname");
+
+    $NextOsidSelection = array();
+    while ($row = mysql_fetch_array($osid_result)) {
+	$osid   = $row["osid"];
+	$osname = $row["osname"];
+	$pid    = $row["pid"];
+
+	$NextOsidSelection['$osid'] = "$pid - $osname";
     }
+    $fields['nextosid'] =
+	array('#type'	    => 'select',
+	      '#label'      => 'NextOSid',
+	      '#checkslot'  => 'os_info:nextosid',
+	      '#options'    => $NextOsidSelection);
+}
 
-    echo "<tr>
-              <td align=center colspan=2>
-                  <b><input type=submit name=submit value=Submit></b>
-              </td>
-          </tr>\n";
+#
+# Spit the form out using the array of data. 
+# 
+function SPITFORM($formfields, $errors)
+{
+    global $form, $fields;
+    
+    $fields['submit'] = array('#type'  => 'submit',
+			      '#value' => "Submit");
 
-    echo "</form>
-          </table>\n";
+    echo "<center>";
+    FormRender($form, $errors, $fields, $formfields);
+    echo "</center>";
 }
 
 #
@@ -328,8 +236,8 @@ if (!isset($submit)) {
     $defaults["version"]        = "";
     $defaults["path"]           = "";
     $defaults["magic"]          = "";
-    $defaults["shared"]         = "No";
-    $defaults["mustclean"]      = "No";
+    $defaults["shared"]         = 0;
+    $defaults["mustclean"]      = 0;
     $defaults["path"]           = "";
     $defaults["op_mode"]             = TBDB_DEFAULT_OSID_OPMODE;
     $defaults["os_feature_ping"]     = "checked";
@@ -338,7 +246,7 @@ if (!isset($submit)) {
     $defaults["os_feature_isup"]     = "checked";
     $defaults["os_feature_linktest"] = "checked";
     $defaults["reboot_waittime"]     = "";
-    $defaults["nextosid"]            = "none";
+    $defaults["nextosid"]            = "";
 
     #
     # For users that are in one project and one subgroup, it is usually
@@ -358,13 +266,16 @@ if (!isset($submit)) {
     PAGEFOOTER();
     return;
 }
+# Form submitted. Make sure we have a formfields array.
+if (!isset($formfields)) {
+    PAGEARGERROR("Invalid form arguments.");
+}
 
 #
 # Otherwise, must validate and redisplay if errors
 #
 $errors  = array();
 $project = null;
-$osname  = "";
 
 #
 # Project:
@@ -381,13 +292,8 @@ elseif (! ($project = Project::Lookup($formfields["pid"]))) {
 elseif (!$project->AccessCheck($this_user, $TB_PROJECT_MAKEOSID)) {
     $errors["Project"] = "Not enough permission";    
 }
-# Osname obviously needs to exist.
-if (! isset($formfields["osname"]) || $formfields["osname"] == "") {
-    $errors["Descriptor Name"] = "Required value not provided";
-}
-else {
-    $osname = $formfields["osname"];
-}
+
+FormValidate($form, $errors, $fields, $formfields);
 
 #
 # If any errors, respit the form with the current values and the
@@ -400,49 +306,29 @@ if (count($errors)) {
 }
 
 #
-# Build up argument array to pass along.
+# Build up argument array to pass along. We pass only those form fields that
+# have actual values and let the backend decide the rest.
 #
 $args = array();
 
-if (isset($formfields["OS"]) &&
-    $formfields["OS"] != "none" && $formfields["OS"] != "") {
-    $args["OS"]		= $formfields["OS"];
-}
-if (isset($formfields["path"]) && $formfields["path"] != "") {
-    $args["path"]	= $formfields["path"];
-}
-if (isset($formfields["version"]) && $formfields["version"] != "") {
-    $args["version"]	= $formfields["version"];
-}
-if (isset($formfields["description"]) && $formfields["description"] != "") {
-    $args["description"]= $formfields["description"];
-}
-if (isset($formfields["magic"]) && $formfields["magic"] != "") {
-    $args["magic"]	= $formfields["magic"];
-}
-if (isset($formfields["shared"]) && $formfields["shared"] == "Yep") {
-    $args["shared"]	= 1;
-}
-if (isset($formfields["mustclean"]) && $formfields["mustclean"] == "Yep") {
-    $args["mustclean"]	= 1;
-}
-if (isset($formfields["op_mode"]) &&
-    $formfields["op_mode"] != "none" && $formfields["op_mode"] != "") {
-    $args["op_mode"]	= $formfields["op_mode"];
-}
-if (isset($formfields["nextosid"]) &&
-    $formfields["nextosid"] != "" && $formfields["nextosid"] != "none") {
-    $args["nextosid"] = $formfields["nextosid"];
-}
-if (isset($formfields["reboot_waittime"]) &&
-    $formfields["reboot_waittime"] != "") {
-    $args["reboot_waittime"] = $formfields["reboot_waittime"];
+while (list ($name, $attributes) = each ($fields)) {
+    # features special. see below
+    if ($name == "features")
+	continue;
+    # pid and osname are handled in NewOSID
+    if ($name == "pid" || $name == "osname")
+	continue;
+    if (isset($formfields[$name]) && $formfields[$name] != "") {
+	$args[$name] = $formfields[$name];
+    }
 }
+
 #
 # Form comma separated list of osfeatures.
 #
 $os_features_array = array();
 
+reset($osid_featurelist);
 while (list ($feature, $userokay) = each($osid_featurelist)) {
     if (isset($formfields["os_feature_$feature"]) &&
 	$formfields["os_feature_$feature"] == "checked") {
@@ -452,7 +338,7 @@ while (list ($feature, $userokay) = each($osid_featurelist)) {
 $args["features"] = join(",", $os_features_array);
 
 if (! ($osinfo = OSinfo::NewOSID($this_user, $project,
-				 $osname, $args, $errors))) {
+				 $formfields["osname"], $args, $errors))) {
     # Always respit the form so that the form fields are not lost.
     # I just hate it when that happens so lets not be guilty of it ourselves.
     SPITFORM($formfields, $errors);
-- 
GitLab