You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@vcl.apache.org by jf...@apache.org on 2010/08/31 22:41:33 UTC

svn commit: r991322 - in /incubator/vcl/trunk/web: .ht-inc/schedules.php .ht-inc/states.php .ht-inc/utils.php css/vcl.css js/schedules.js

Author: jfthomps
Date: Tue Aug 31 20:41:32 2010
New Revision: 991322

URL: http://svn.apache.org/viewvc?rev=991322&view=rev
Log:
VCL-274
check for SQL injection/XSS

found some places where $_POST was being used in schedules.php with the possiblity of poor validation; I didn't fully trace it out because I was already wanting to change the way schedule times were modified to use ajax instead of a series of page loads

utils.php: modified getDojoHTML - added stuff for editSchedule and submitAddSchedule

states.php: removed submitScheduleTime; added AJgetScheduleTimesData and AJsaveScheduleTimes

schedules.php:
-modified editOrAddSchedule - changed form to have a dojox DataGrid to manage the schedule times
-added AJgetScheduleTimesData - sends JSON data of schedule times to initially populate the datagrid
-modified processScheduleInput - removed code that dealt with schedule times
-removed printStartEndTimeForm
-removed printStartEndTimeForm2
-added AJsaveScheduleTimes - updates schedule times in database
-removed submitScheduleTime

css/vcl.css: added #savestatus

Added:
    incubator/vcl/trunk/web/js/schedules.js
Modified:
    incubator/vcl/trunk/web/.ht-inc/schedules.php
    incubator/vcl/trunk/web/.ht-inc/states.php
    incubator/vcl/trunk/web/.ht-inc/utils.php
    incubator/vcl/trunk/web/css/vcl.css

Modified: incubator/vcl/trunk/web/.ht-inc/schedules.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/schedules.php?rev=991322&r1=991321&r2=991322&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/schedules.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/schedules.php Tue Aug 31 20:41:32 2010
@@ -170,14 +170,12 @@ function viewSchedules() {
 ///
 ////////////////////////////////////////////////////////////////////////////////
 function editOrAddSchedule($state) {
-	global $submitErr, $mode, $submitErrMsg;
+	global $submitErr, $mode, $submitErrMsg, $days;
 
 	$schedules = getSchedules();
-	$days = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-	              "Friday", "Saturday");
 
 	$newcont = 0;
-	if($submitErr || $mode == "submitScheduleTime" || $mode == "submitAddSchedule") {
+	if($submitErr || $mode == "submitAddSchedule") {
 		$data = processScheduleInput(0);
 		$newcont = 1; # continuation to get here was deleted; so, we'll need to set
 		              #   deletefromself true this time
@@ -187,9 +185,7 @@ function editOrAddSchedule($state) {
 		$id = $data["scheduleid"];
 		$data["name"] = $schedules[$id]["name"];
 		$data["owner"] = $schedules[$id]["owner"];
-		$data["submode"] = processInputVar("submode", ARG_STRING);
 	}
-	$schedules = getSchedules();
 	print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
 	print "<DIV align=center>\n";
 	if($state) {
@@ -250,121 +246,56 @@ function editOrAddSchedule($state) {
 	print "    </TD>\n";
 	print "  </TR>\n";
 	print "</TABLE>\n";
+	print "</div>\n";
 	if($state)
 		return;
 	print "The start and end day/times are based on a week's time period with ";
 	print "the start/end point being 'Sunday 12:00&nbsp;am'. i.e. The earliest ";
 	print "start day/time is 'Sunday 12:00&nbsp;am' and the latest end day/";
 	print "time is 'Sunday 12:00&nbsp;am'<br><br>\n";
-	if(! $submitErr && $mode == "submitScheduleTime" && $data["submode"] == "Save changes") {
-		print "<font color=green>Changes saved</font><br>\n";
-	}
-	printSubmitErr(OVERLAPERR);
-	print "<FORM action=\"" . BASEURL . SCRIPT . "\" method=post>\n";
-	print "<TABLE>\n";
-	print "  <TR>\n";
-	print "    <TD></TD>\n";
-	print "    <TH>Start</TH>\n";
-	print "    <TD></TD>\n";
-	print "    <TH>End</TH>\n";
-	print "    <TD></TD>\n";
-	print "  </TR>\n";
-	$addrow = 0;
-	if($mode == "submitScheduleTime") {
-		$addrow = 1;
-	}
-	print "<TR><TD colspan=5>";
-	print "</TD></TR>\n";
-	$doaddrow = 0;
-	if($mode == "submitScheduleTime") {
-		if($data["selrow"] == "")
-			$end = $data["count"];
-		elseif($data["submode"] == "Insert before selected row") {
-			$doaddrow = 1;
-			$addrow = $data["selrow"];
-			$end = $data["count"] + 1;
-		}
-		elseif($data["submode"] == "Insert after selected row") {
-			$doaddrow = 1;
-			$addrow = $data["selrow"] + 1;
-			$end = $data["count"] + 1;
-		}
-		else
-			$end = $data["count"];
-	}
-	else
-		$end = count($schedules[$data["scheduleid"]]["times"]);
-	if($end == 0) {
-		$doaddrow = 1;
-		$addrow = 0;
-		$end = 1;
-	}
-	reset($schedules[$data["scheduleid"]]["times"]);
-	$index = 0;
-	for($count = 0; $count < $end; $count++) {
-		// if mode == submitScheduleTime, print submitted times
-		if($mode == "submitScheduleTime") {
-			if($doaddrow && $count == $addrow) {
-				$startday = "";
-				$starttime = "";
-				$endday = "";
-				$endtime = "";
-				$doaddrow = 0;
-				$index--;
-			}
-			else {
-				$startday = $data["startDay"][$index];
-				$starttime = $data["startTime"][$index];
-				$endday = $data["endDay"][$index];
-				$endtime = $data["endTime"][$index];
-			}
-			print "  <TR>\n";
-			print "    <TD align=right><INPUT type=radio name=selrow value=$count></TD>\n";
-			printStartEndTimeForm2($startday, $starttime, $count, "start");
-			print "    <TD>&nbsp;&nbsp;</TD>\n";
-			printStartEndTimeForm2($endday, $endtime, $count, "end");
-		}
-		// otherwise, print times from database
-		else {
-			$time = current($schedules[$data["scheduleid"]]["times"]);
-			print "  <TR>\n";
-			print "    <TD align=right><INPUT type=radio name=selrow value=$count></TD>\n";
-			printStartEndTimeForm($time["start"], $count, "start");
-			print "    <TD>&nbsp;&nbsp;</TD>\n";
-			printStartEndTimeForm($time["end"], $count, "end");
-			next($schedules[$data["scheduleid"]]["times"]);
-		}
-		print "    <TD width=70>";
-		if($data["submode"] == "Save changes")
-			printSubmitErr(1 << $count);
-		print "</TD>";
-		print "  </TR>\n";
-		$index++;
-	}
-	$colspan = 5;
-	print "  <TR>\n";
-	print "    <TD align=center colspan=$colspan><INPUT type=submit name=submode value=\"Delete selected row\"></TD>\n";
-	print "  <TR>\n";
-	print "  </TR>\n";
-	print "    <TD align=center colspan=$colspan><INPUT type=submit name=submode value=\"Insert before selected row\"></TD>\n";
-	print "  <TR>\n";
-	print "  </TR>\n";
-	print "    <TD align=center colspan=$colspan><INPUT type=submit name=submode value=\"Insert after selected row\"></TD>\n";
-	print "  <TR>\n";
-	print "  </TR>\n";
-	print "    <TD align=center colspan=$colspan><INPUT type=submit name=submode value=\"Save changes\"></TD>\n";
-	print "  </TR>\n";
-	print "</TABLE>\n";
-	$cdata = array('scheduleid' => $data['scheduleid'],
-	               'count' => $count,
-	               'name' => $data['name'],
-	               'owner' => $data['owner']);
-	if($newcont)
-		$cont = addContinuationsEntry('submitScheduleTime', $cdata, SECINDAY, 1, 0);
-	else
-		$cont = addContinuationsEntry('submitScheduleTime', $cdata, SECINDAY, 0, 0);
-	print "<INPUT type=hidden name=continuation value=\"$cont\">\n";
-	print "</FORM>\n";
+
+
+	print "Start:";
+	printSelectInput('startday', $days, -1, 0, 0, 'startday');
+	print "<input type=\"text\" id=\"starttime\" dojoType=\"dijit.form.TimeTextBox\" ";
+	print "required=\"true\" />\n";
+	print "End:";
+	printSelectInput('endday', $days, -1, 0, 0, 'endday');
+	print "<input type=\"text\" id=\"endtime\" dojoType=\"dijit.form.TimeTextBox\" ";
+	print "required=\"true\" />\n";
+	print "<button dojoType=\"dijit.form.Button\" type=\"button\" ";
+	print "id=\"addTimeBtn\">\n";
+	print "  Add\n";
+	print "  <script type=\"dojo/method\" event=\"onClick\">\n";
+	print "    addTime();\n";
+	print "  </script>\n";
+	print "</button>\n";
+	print "<div dojoType=\"dojo.data.ItemFileWriteStore\" jsId=\"scheduleStore\" ";
+	print "data=\"scheduleTimeData\"></div>\n";
+	print "<table dojoType=\"dojox.grid.DataGrid\" jsId=\"scheduleGrid\" sortInfo=1 ";
+	print "store=\"scheduleStore\" style=\"width: 524px; height: 165px;\">\n";
+	print "<thead>\n";
+	print "<tr>\n";
+	print "<th field=\"startday\" width=\"94px\" formatter=\"formatDay\">Start Day</th>\n";
+	print "<th field=\"startday\" width=\"94px\" formatter=\"formatTime\">Start Time</th>\n";
+	print "<th field=\"endday\" width=\"94px\" formatter=\"formatDay\">End Day</th>\n";
+	print "<th field=\"endday\" width=\"94px\" formatter=\"formatTime\">End Time</th>\n";
+	print "<th field=\"remove\" width=\"80px\">Remove</th>\n";
+	print "</tr>\n";
+	print "</thead>\n";
+	print "</table>\n";
+
+	print "<div align=\"center\">\n";
+	print "<div id=\"savestatus\"></div>\n";
+	print "<button dojoType=\"dijit.form.Button\" type=\"button\" id=\"saveTimesBtn\">\n";
+	print "  Save Schedule Times\n";
+	print "  <script type=\"dojo/method\" event=\"onClick\">\n";
+	$cdata = array('id' => $data['scheduleid']);
+	$cont = addContinuationsEntry('AJsaveScheduleTimes', $cdata);
+	print "    saveTimes('$cont');\n";
+	print "  </script>\n";
+	print "</button>\n";
+	print "</div>\n";
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -470,6 +401,39 @@ function submitAddSchedule() {
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
+/// \fn AJgetScheduleTimesData()
+///
+/// \brief gets start/end times for a schedule and sends in JSON format
+///
+////////////////////////////////////////////////////////////////////////////////
+function AJgetScheduleTimesData() {
+	$id = getContinuationVar('id');
+	$query = "SELECT start, "
+	       .        "end "
+	       . "FROM scheduletimes "
+	       . "WHERE scheduleid = $id "
+	       . "ORDER BY start";
+	$qh = doQuery($query, 101);
+	$times = array();
+	while($row = mysql_fetch_assoc($qh)) {
+		$smin = $row['start'] % 1440;
+		$sday = (int)($row['start'] / 1440);
+		if($sday > 6)
+			$sday = 0;
+		$emin = $row['end'] % 1440;
+		$eday = (int)($row['end'] / 1440);
+		if($eday > 6)
+			$eday = 0;
+		$times[] = array('smin' => $smin,
+		                 'sday' => $sday,
+		                 'emin' => $emin,
+		                 'eday' => $eday);
+	}
+	sendJSON($times);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
 /// \fn confirmDeleteSchedule()
 ///
 /// \brief prints a form to confirm the deletion of a schedule
@@ -659,8 +623,7 @@ function submitScheduleGroups() {
 /// \param $checks - (optional) 1 to perform validation, 0 not to
 ///
 /// \return an array with the following indexes:\n
-/// scheduleid, name, owner, submode, selrow, count, startDay, startTime,
-/// endDay, endTime
+/// scheduleid, name, owner
 ///
 /// \brief validates input from the previous form; if anything was improperly
 /// submitted, sets submitErr and submitErrMsg
@@ -669,23 +632,12 @@ function submitScheduleGroups() {
 function processScheduleInput($checks=1) {
 	global $submitErr, $submitErrMsg;
 	$return = array();
-	$return["start"] = array();
-	$return["end"] = array();
-
 	$return["scheduleid"] = getContinuationVar("scheduleid", processInputVar("scheduleid" , ARG_NUMERIC));
 	$return["name"] = getContinuationVar("name", processInputVar("name", ARG_STRING));
 	$return["owner"] = getContinuationVar("owner", processInputVar("owner", ARG_STRING));
-	$return["submode"] = processInputVar("submode", ARG_STRING);
-	$return["selrow"] = processInputVar("selrow", ARG_NUMERIC);
-	$return["count"] = getContinuationVar("count", processInputVar("count", ARG_NUMERIC, 0));
-	$return["startDay"] = processInputVar("startDay", ARG_MULTINUMERIC);
-	$return["startTime"] = processInputVar("startTime", ARG_MULTISTRING);
-	$return["endDay"] = processInputVar("endDay", ARG_MULTINUMERIC);
-	$return["endTime"] = processInputVar("endTime", ARG_MULTISTRING);
 
-	if(! $checks) {
+	if(! $checks)
 		return $return;
-	}
 	
 	if(strlen($return["name"]) > 25 || strlen($return["name"]) < 2) {
 	   $submitErr |= SCHNAMEERR;
@@ -700,30 +652,6 @@ function processScheduleInput($checks=1)
 	   $submitErr |= SCHOWNERERR;
 	   $submitErrMsg[SCHOWNERERR] = "The submitted unity ID is invalid.";
 	}
-	for($i = 0; $i < $return["count"]; $i++) {
-		if((! preg_match('/^((0?[1-9])|(1[0-2])):([0-5][0-9]) (am|pm)$/', $return["startTime"][$i])) ||
-		   (! preg_match('/^((0?[1-9])|(1[0-2])):([0-5][0-9]) (am|pm)$/', $return["endTime"][$i]))) {
-			$submitErr |= (1 << $i);
-			$submitErrMsg[1 << $i] = "Time must be of the form [H]H:MM&nbsp;am/pm";
-		}
-		elseif(daytimeToMin($return["startDay"][$i], $return["startTime"][$i], "start") >=
-		       daytimeToMin($return["endDay"][$i], $return["endTime"][$i], "end")) {
-			$submitErr |= (1 << $i);
-			$submitErrMsg[1 << $i] = "The start day/time must be before the end day/time";
-		}
-	}
-	for($i = 0; $i < $return["count"] - 1; $i++) {
-		for($j = $i + 1; $j < $return["count"]; $j++) {
-			if(daytimeToMin($return["startDay"][$i], $return["startTime"][$i], "start") <
-			   daytimeToMin($return["endDay"][$j], $return["endTime"][$j], "end") &&
-			   daytimeToMin($return["endDay"][$i], $return["endTime"][$i], "end") >
-			   daytimeToMin($return["startDay"][$j], $return["startTime"][$j], "start")) {
-				$submitErr |= OVERLAPERR;
-				$submitErrMsg[OVERLAPERR] = "At least 2 of the time periods overlap. Please combine them into a single entry.";
-				break(2);
-			}
-		}
-	}
 	return $return;
 }
 
@@ -810,157 +738,42 @@ function addSchedule($data) {
 
 ////////////////////////////////////////////////////////////////////////////////
 ///
-/// \fn printStartEndTimeForm($min, $count, $startend)
+/// \fn AJsaveScheduleTimes()
 ///
-/// \param $min - minute in the week, pass empty string to get an empty text
-/// entry field
-/// \param $count - counter value - used to keep track of which row this is
-/// \param $startend - "start" or "end"
-///
-/// \brief prints a select input for the day of week and a text entry field
-/// for the time to be entered
+/// \brief saves the submitted time for the schedule and notifies the user
 ///
 ////////////////////////////////////////////////////////////////////////////////
-function printStartEndTimeForm($min, $count, $startend) {
-	$days = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-	              "Friday", "Saturday");
-	if($min == "") {
-		print "    <TD>\n";
-		printSelectInput("$startend" . "Day[$count]", $days);
-		$name = $startend . "Time[$count]";
-		print "      <INPUT type=text name=$name size=8 mazlength=8>\n";
-		print "    </TD>\n";
+function AJsaveScheduleTimes() {
+	$id = getContinuationVar('id');
+	$tmp = processInputVar('times', ARG_STRING);
+	if(! preg_match('/^([0-9]+:[0-9]+,)*([0-9]+:[0-9]+){1}$/', $tmp)) {
+		print "alert('invalid data submitted');";
 		return;
 	}
-	$time = minuteToTime($min % 1440);
-	if((int)($min / 1440) == 0) {
-		$day = 0;
-	}
-	elseif((int)($min / 1440) == 1) {
-		$day = 1;
-	}
-	elseif((int)($min / 1440) == 2) {
-		$day = 2;
-	}
-	elseif((int)($min / 1440) == 3) {
-		$day = 3;
-	}
-	elseif((int)($min / 1440) == 4) {
-		$day = 4;
-	}
-	elseif((int)($min / 1440) == 5) {
-		$day = 5;
-	}
-	elseif((int)($min / 1440) == 6) {
-		$day = 6;
-	}
-	elseif((int)($min / 1440) > 6) {
-		$day = 0;
-	}
-	print "    <TD>\n";
-	printSelectInput("$startend" . "Day[$count]", $days, $day);
-	$name = $startend . "Time[$count]";
-	print "      <INPUT type=text name=$name value=\"$time\" size=8 maxlength=8>\n";
-	print "    </TD>\n";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
-/// \fn printStartEndTimeForm2($day, $time, $count, $startend)
-///
-/// \param $day - numeric day of week with Sunday being 0
-/// \param $time - time of day in string format HH:MM am/pm
-/// \param $count - counter value - used to keep track of which row this is
-/// \param $startend - "start" or "end"
-///
-/// \brief prints a select input for the day of week and a text entry field
-/// for the time to be entered
-///
-////////////////////////////////////////////////////////////////////////////////
-function printStartEndTimeForm2($day, $time, $count, $startend) {
-	$days = array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
-	              "Friday", "Saturday");
-	print "    <TD>\n";
-	printSelectInput("$startend" . "Day[$count]", $days, $day);
-	$name = $startend . "Time[$count]";
-	print "      <INPUT type=text name=$name value=\"$time\" size=8 maxlength=8>\n";
-	print "    </TD>\n";
-}
-
-////////////////////////////////////////////////////////////////////////////////
-///
-/// \fn submitScheduleTime()
-///
-/// \brief handles submitting date/time form for schedule times and calls
-/// editOrAddSchedule(0) again
-///
-////////////////////////////////////////////////////////////////////////////////
-function submitScheduleTime() {
-	global $submitErr, $contdata;
-
-	if($_POST["submode"] == "Save changes") {
-		$data = processScheduleInput(1);
-		if($submitErr) {
-			editOrAddSchedule(0);
-			return;
-		}
-	}
-	else {
-		$data = processScheduleInput(0);
-		if($data["selrow"] == "") {
-			editOrAddSchedule(0);
-			return;
-		}
-	}
-
-	if($data["submode"] == "Delete selected row") {
-		// delete entry from db
-		$start = daytimeToMin($data["startDay"][$data["selrow"]], $data["startTime"][$data["selrow"]], "start");
-		$end = daytimeToMin($data["endDay"][$data["selrow"]], $data["endTime"][$data["selrow"]], "end");
-		$query = "DELETE FROM scheduletimes "
-		       . "WHERE scheduleid = {$data["scheduleid"]} AND "
-		       .       "start = $start AND "
-		       .       "end = $end";
-		doQuery($query, 101);
-		// decrease all values by 1 that are > deleted row
-		for($i = 0; $i < $data["count"] - 1; $i++) {
-			if($i >= $data["selrow"]) {
-				$_POST["startDay"][$i] = $_POST["startDay"][$i + 1];
-				$_POST["startTime"][$i] = $_POST["startTime"][$i + 1];
-				$_POST["endDay"][$i] = $_POST["endDay"][$i + 1];
-				$_POST["endTime"][$i] = $_POST["endTime"][$i + 1];
+	$times = explode(',', $tmp);
+	$newtimes = array();
+	$qvals = array();
+	foreach($times as $pair) {
+		list($start, $end) = explode(':', $pair);
+		foreach($newtimes as $check) {
+			if($start < $check['end'] && $end > $check['start']) {
+				print "alert('Two sets of times are overlapping;\nplease correct and save again.');";
+				return;
 			}
 		}
-		unset($_POST["startDay"][$i]);
-		unset($_POST["startTime"][$i]);
-		unset($_POST["endDay"][$i]);
-		unset($_POST["endTime"][$i]);
-		$contdata["count"]--;
-		editOrAddSchedule(0);
-	}
-	elseif($data["submode"] == "Insert before selected row") {
-		editOrAddSchedule(0);
-	}
-	elseif($data["submode"] == "Insert after selected row") {
-		editOrAddSchedule(0);
-	}
-	elseif($data["submode"] == "Save changes") {
-		$query = "DELETE FROM scheduletimes WHERE scheduleid = {$data["scheduleid"]}";
-		doQuery($query, 101);
-		for($i = 0; $i < $data["count"]; $i++) {
-			$start = daytimeToMin($data["startDay"][$i], $data["startTime"][$i], "start");
-			$end = daytimeToMin($data["endDay"][$i], $data["endTime"][$i], "end");
-			$query = "INSERT INTO scheduletimes "
-			       .        "(scheduleid, "
-			       .        "start, "
-			       .        "end) "
-			       . "VALUES ({$data["scheduleid"]}, "
-			       .        "$start, "
-			       .        "$end)";
-			doQuery($query, 101);
-		}
-		editOrAddSchedule(0);
+		$newtimes[] = array('start' => $start, 'end' => $end);
+		$qvals[] = "($id, $start, $end)";
 	}
+	$query = "DELETE FROM scheduletimes WHERE scheduleid = $id";
+	doQuery($query, 101);
+	$allvals = implode(',', $qvals);
+	$query = "INSERT INTO scheduletimes "
+	       .        "(scheduleid, start, end) "
+			 . "VALUES $allvals";
+	doQuery($query, 101);
+	print "dijit.byId('saveTimesBtn').attr('disabled', false);";
+	print "dojo.byId('savestatus').innerHTML = 'Schedule times successfully saved';";
+	print "setTimeout(function() {dojo.byId('savestatus').innerHTML = '';}, 8000);";
 }
 
 ////////////////////////////////////////////////////////////////////////////////

Modified: incubator/vcl/trunk/web/.ht-inc/states.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/states.php?rev=991322&r1=991321&r2=991322&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/states.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/states.php Tue Aug 31 20:41:32 2010
@@ -139,6 +139,8 @@ $noHTMLwrappers = array('sendRDPfile',
                         'AJgetDelSiteMaintenanceData',
                         'AJeditSiteMaintenance',
                         'AJdeleteSiteMaintenance',
+                        'AJgetScheduleTimesData',
+                        'AJsaveScheduleTimes',
 );
 
 # main
@@ -356,7 +358,8 @@ $actions['mode']['submitAddSchedule'] = 
 $actions['mode']['confirmDeleteSchedule'] = "confirmDeleteSchedule";
 $actions['mode']['submitDeleteSchedule'] = "submitDeleteSchedule";
 $actions['mode']['submitScheduleGroups'] = "submitScheduleGroups";
-$actions['mode']['submitScheduleTime'] = "submitScheduleTime";
+$actions['mode']['AJgetScheduleTimesData'] = "AJgetScheduleTimesData";
+$actions['mode']['AJsaveScheduleTimes'] = "AJsaveScheduleTimes";
 $actions['pages']['viewSchedules'] = "manageSchedules";
 $actions['pages']['editSchedule'] = "manageSchedules";
 $actions['pages']['confirmEditSchedule'] = "manageSchedules";
@@ -366,7 +369,8 @@ $actions['pages']['submitAddSchedule'] =
 $actions['pages']['confirmDeleteSchedule'] = "manageSchedules";
 $actions['pages']['submitDeleteSchedule'] = "manageSchedules";
 $actions['pages']['submitScheduleGroups'] = "manageSchedules";
-$actions['pages']['submitScheduleTime'] = "manageSchedules";
+$actions['pages']['AJgetScheduleTimesData'] = "manageSchedules";
+$actions['pages']['AJsaveScheduleTimes'] = "manageSchedules";
 
 # manage computers
 $actions['mode']['selectComputers'] = "selectComputers"; # entry

Modified: incubator/vcl/trunk/web/.ht-inc/utils.php
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/.ht-inc/utils.php?rev=991322&r1=991321&r2=991322&view=diff
==============================================================================
--- incubator/vcl/trunk/web/.ht-inc/utils.php (original)
+++ incubator/vcl/trunk/web/.ht-inc/utils.php Tue Aug 31 20:41:32 2010
@@ -9051,6 +9051,17 @@ function getDojoHTML($refresh) {
 		case 'viewBlockStatus':
 			$dojoRequires = array('dojo.parser');
 			break;
+		case 'editSchedule':
+		case 'submitAddSchedule':
+			// TODO remove any unneeded items
+			$dojoRequires = array('dojo.parser',
+			                      'dijit.form.TimeTextBox',
+			                      'dojox.grid.DataGrid',
+			                      'dojox.string.sprintf',
+			                      #'dijit.form.FilteringSelect',
+			                      #'dijit.Tooltip',
+			                      'dijit.form.Button',
+			                      'dojo.data.ItemFileWriteStore');
 		case 'viewImages':
 			/*$dojoRequires = array('dojo.data.ItemFileWriteStore',
 			                      'dojox.grid.Grid',
@@ -9237,6 +9248,29 @@ function getDojoHTML($refresh) {
 			$rt .= "</script>\n";
 			return $rt;
 
+		case "editSchedule":
+		case "submitAddSchedule":
+			$rt .= "<style type=\"text/css\">\n";
+			$rt .= "   @import \"themes/$skin/css/dojo/$skin.css\";\n";
+			$rt .= "   @import \"dojo/dojox/grid/resources/Grid.css\";\n";
+			$rt .= "</style>\n";
+			$rt .= "<script type=\"text/javascript\" src=\"js/schedules.js\"></script>\n";
+			$rt .= "<script type=\"text/javascript\" src=\"dojo/dojo/dojo.js\"\n";
+			$rt .= "   djConfig=\"parseOnLoad: true\">\n";
+			$rt .= "</script>\n";
+			$rt .= "<script type=\"text/javascript\">\n";
+			$rt .= "   dojo.addOnLoad(function() {\n";
+			foreach($dojoRequires as $req) {
+				$rt .= "   dojo.require(\"$req\");\n";
+			}
+			$id = getContinuationVar("scheduleid");
+			$cont = addContinuationsEntry('AJgetScheduleTimesData', array('id' => $id), SECINDAY, 1, 0);
+			$rt .= "   populateTimeStore('$cont');\n";
+			#$rt .= "   setTimeout(function() {populateTimeStore('$cont');}, 1000);\n";
+			$rt .= "   });\n";
+			$rt .= "</script>\n";
+			return $rt;
+
 		case "viewImageGrouping":
 		case "submitImageGroups":
 		case "viewImageMapping":

Modified: incubator/vcl/trunk/web/css/vcl.css
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/css/vcl.css?rev=991322&r1=991321&r2=991322&view=diff
==============================================================================
--- incubator/vcl/trunk/web/css/vcl.css (original)
+++ incubator/vcl/trunk/web/css/vcl.css Tue Aug 31 20:41:32 2010
@@ -256,3 +256,7 @@
 	border: 1px solid;
 	background-color: #f3f3f3;
 }
+
+#savestatus {
+	color: #008000;
+}

Added: incubator/vcl/trunk/web/js/schedules.js
URL: http://svn.apache.org/viewvc/incubator/vcl/trunk/web/js/schedules.js?rev=991322&view=auto
==============================================================================
--- incubator/vcl/trunk/web/js/schedules.js (added)
+++ incubator/vcl/trunk/web/js/schedules.js Tue Aug 31 20:41:32 2010
@@ -0,0 +1,193 @@
+var scheduleTimeData = {
+	identifier: 'id',
+	items: []
+}
+
+function RPCwrapper(data, CB, dojson) {
+	if(dojson) {
+		dojo.xhrPost({
+			url: 'index.php',
+			load: CB,
+			handleAs: "json",
+			error: errorHandler,
+			content: data,
+			timeout: 15000
+		});
+	}
+	else {
+		dojo.xhrPost({
+			url: 'index.php',
+			load: CB,
+			error: errorHandler,
+			content: data,
+			timeout: 15000
+		});
+	}
+}
+
+function generalReqCB(data, ioArgs) {
+	eval(data);
+	document.body.style.cursor = 'default';
+}
+
+function populateTimeStore(cont) {
+	RPCwrapper({continuation: cont}, populateTimeStoreCB, 1);
+}
+
+function populateTimeStoreCB(data, ioArgs) {
+	if(data.items.error) {
+		alert(data.items.error);
+		return;
+	}
+	var store = scheduleStore;
+	if(! store.nextid)
+		store.nextid = 0;
+	for(var i = 0; i < data.items.length; i++) {
+		var id = store.nextid + 1;
+		store.nextid = id;
+		var sday = new Date(0);
+		sday.setFullYear(2000);
+		sday.setMonth(9);
+		sday.setDate(data.items[i].sday + 1);
+		sday.setHours(Math.floor(data.items[i].smin / 60));
+		sday.setMinutes(data.items[i].smin % 60);
+		var eday = new Date(0);
+		eday.setFullYear(2000);
+		eday.setMonth(9);
+		if(data.items[i].eday == 0 && 
+		   data.items[i].emin == 0) {
+			eday.setDate(data.items[i].eday + 8);
+			eday.setHours(Math.floor(data.items[i].emin / 60));
+			eday.setMinutes(data.items[i].emin % 60);
+		}
+		else {
+			eday.setDate(data.items[i].eday + 1);
+			eday.setHours(Math.floor(data.items[i].emin / 60));
+			eday.setMinutes(data.items[i].emin % 60);
+		}
+		var btn = new dijit.form.Button({
+			label: "Remove",
+			onClick: createRemoveFunc(removeTime, id)
+		});
+		store.newItem({id: id, startday: sday, endday: eday, remove: btn});
+	}
+	scheduleGrid.sort();
+}
+
+function createRemoveFunc(func, id) {
+	return function() {func(id);}
+}
+
+function removeTime(id) {
+	scheduleStore.fetch({
+		query: {id: id},
+	   onItem: function(item) {
+			scheduleStore.deleteItem(item);
+		}
+	});
+}
+
+function addTime() {
+	var endday = parseInt(dojo.byId('endday').value);
+	var endtimeobj = dijit.byId('endtime').value;
+	if(dojo.byId('startday').value != 0 &&
+	   endday == 0 &&
+	   (endtimeobj.getHours() != 0 ||
+	   endtimeobj.getMinutes() != 0)) {
+		alert("If the start day is not Sunday, the end day cannot\nbe Sunday with a time later than 12:00 AM.");
+		return;
+	}
+	var sday = new Date(0);
+	sday.setFullYear(2000);
+	sday.setMonth(9);
+	sday.setDate(parseInt(dojo.byId('startday').value) + 1);
+	sday.setHours(dijit.byId('starttime').value.getHours());
+	sday.setMinutes(dijit.byId('starttime').value.getMinutes());
+	var eday = new Date(0);
+	eday.setFullYear(2000);
+	eday.setMonth(9);
+	if(endday == 0 && 
+	   endtimeobj.getHours() == 0 &&
+		endtimeobj.getMinutes() == 0) {
+		eday.setDate(endday + 8);
+		eday.setHours(endtimeobj.getHours());
+		eday.setMinutes(endtimeobj.getMinutes());
+	}
+	else {
+		eday.setDate(endday + 1);
+		eday.setHours(endtimeobj.getHours());
+		eday.setMinutes(endtimeobj.getMinutes());
+	}
+
+	if(eday < sday) {
+		alert('The ending day/time cannot be earlier than the starting day/time');
+		return;
+	}
+
+	var items = scheduleStore._arrayOfAllItems;
+	for(var i = 0; i < items.length; i++) {
+		if(items[i] == null)
+			continue;
+		if(sday < items[i].endday[0] && eday > items[i].startday[0]) {
+			alert("The submitted days/times overlap with\nan existing set of days/times.");
+			return;
+		}
+	}
+
+	id = ++scheduleStore.nextid;
+	var btn = new dijit.form.Button({
+		label: "Remove",
+		onClick: createRemoveFunc(removeTime, id)
+	});
+	scheduleStore.newItem({id: id, startday: sday, endday: eday, remove: btn});
+	scheduleGrid.sort();
+}
+
+function formatDay(val) {
+	return getDay(val.getDay());
+}
+
+function formatTime(val) {
+	return getTime(val);
+}
+
+function getDay(day) {
+	var days = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
+	return days[day];
+}
+
+function getTime(obj) {
+	var hour = obj.getHours();
+	var min = obj.getMinutes();
+	if(hour == 12)
+		return dojox.string.sprintf('12:%02d PM', min);
+	if(hour == 0)
+		return dojox.string.sprintf('12:%02d AM', min);
+	if(parseInt(hour / 12))
+		return dojox.string.sprintf('%d:%02d PM', hour % 12, min);
+	return dojox.string.sprintf('%d:%02d AM', hour, min);
+}
+
+function saveTimes(cont) {
+	var times = new Array();
+	var items = scheduleStore._arrayOfAllItems;
+	for(var i = 0; i < items.length; i++) {
+		if(items[i] == null)
+			continue;
+		var start = minuteInWeek(items[i].startday[0]);
+		var end = minuteInWeek(items[i].endday[0]);
+		times.push(dojox.string.sprintf('%d:%d', start, end));
+	}
+	var data = {continuation: cont,
+	            times: times.join(',')};
+	dijit.byId('saveTimesBtn').attr('disabled', true);
+	document.body.style.cursor = 'wait';
+	RPCwrapper(data, generalReqCB);
+}
+
+function minuteInWeek(val) {
+	var min = val.getMinutes();
+	min += val.getHours() * 60;
+	min += (val.getDate() - 1) * 1440;
+	return min;
+}