diff --git a/etc/inc/xmlparse.inc b/etc/inc/xmlparse.inc index 97c3c143d7..8bb1b3f8c3 100644 --- a/etc/inc/xmlparse.inc +++ b/etc/inc/xmlparse.inc @@ -35,7 +35,7 @@ function listtags() { $ret = explode(" ", "element alias aliasurl allowedip cacert config columnitem disk dnsserver domainoverrides " . "earlyshellcmd encryption-algorithm-option field fieldname hash-algorithm-option " . "hosts group interface_array item key lbpool menu mobilekey mount onetoone option package passthrumac priv proxyarpnet " . - "queue pages pipe route row rule service servernat servers earlyshellcmd shellcmd staticmap subqueue " . + "queue pages pipe route row rule schedule service servernat servers earlyshellcmd shellcmd staticmap subqueue " . "tunnel user vip virtual_server vlan winsserver wolentry depends_on_package"); return $ret; } diff --git a/usr/local/www/fbegin.inc b/usr/local/www/fbegin.inc index a52066cb76..b5a1da174f 100755 --- a/usr/local/www/fbegin.inc +++ b/usr/local/www/fbegin.inc @@ -147,6 +147,7 @@ require_once("notices.inc");
  • Aliases
  • NAT
  • Rules
  • +
  • Schedules
  • Traffic Shaper
  • Virtual IPs
  • diff --git a/usr/local/www/firewall_rules_edit.php b/usr/local/www/firewall_rules_edit.php index ddaa2f07bf..5b0e636748 100755 --- a/usr/local/www/firewall_rules_edit.php +++ b/usr/local/www/firewall_rules_edit.php @@ -100,6 +100,9 @@ if (isset($id) && $a_filter[$id]) { /* Multi-WAN next-hop support */ $pconfig['gateway'] = $a_filter[$id]['gateway']; + + //schedule support + $pconfig['sched'] = $a_filter[$id]['sched']; } else { /* defaults */ @@ -320,6 +323,10 @@ if ($_POST) { $filterent['gateway'] = $_POST['gateway']; } + if ($_POST['sched'] != "") { + $filterent['sched'] = $_POST['sched']; + } + if (isset($id) && $a_filter[$id]) $a_filter[$id] = $filterent; else { @@ -715,10 +722,42 @@ include("head.inc"); HINT: This prevents the rule from automatically syncing to other carp members. + "") + $schedules[] = $schedule['name']; + } + ?> + + Schedule + + +

    Leave as 'none' to leave the rule enabled all the time.

    + + + "") $gateways[]=$int['gateway']; diff --git a/usr/local/www/firewall_schedule.php b/usr/local/www/firewall_schedule.php new file mode 100644 index 0000000000..7be2967868 --- /dev/null +++ b/usr/local/www/firewall_schedule.php @@ -0,0 +1,218 @@ +. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + + +$pgtitle = "Firewall: Schedules"; + +$dayArray = array ('Sun','Mon','Tues','Wed','Thur','Fri','Sat'); +$monthArray = array ('January','February','March','April','May','June','July','August','September','October','November','December'); + +require("guiconfig.inc"); + +if (!is_array($config['schedules']['schedule'])) + $config['schedules']['schedule'] = array(); + +schedule_sort(); +$a_schedules = &$config['schedules']['schedule']; + + +if ($_GET['act'] == "del") { + if ($a_schedules[$_GET['id']]) { + /* make sure rule is not being referenced by any nat or filter rules */ + $is_schedule_referenced = false; + $referenced_by = false; + $schedule_name = $a_schedules[$_GET['id']]['name']; + + if(is_array($config['filter']['rule'])) { + foreach($config['filter']['rule'] as $rule) { + //check for this later once this is established + if ($rule['sched'] = $schedule_name){ + $referenced_by = $rule['descr']; + $is_schedule_referenced = true; + } + } + } + + if($is_schedule_referenced == true) { + $savemsg = "Cannot delete Schedule. Currently in use by {$referenced_by}"; + } else { + unset($a_schedules[$_GET['id']]); + write_config(); + header("Location: firewall_schedule.php"); + exit; + } + } +} + +include("head.inc"); +?> + + + +

    + +
    + + + + + + + + + + + + + + + + + + + + + + +
    NameTime Range(s)Description
    + + + "; + } + }?> + + +   + + + + + + +
    +
    + + + + +
    + + " alt="" /> + +
    +
    +

    Note:
    Schedules act as placeholders for time ranges to be used in Firewall Rules.

    +
    + +
    + + + + diff --git a/usr/local/www/firewall_schedule_edit.php b/usr/local/www/firewall_schedule_edit.php new file mode 100644 index 0000000000..b3fa6502e0 --- /dev/null +++ b/usr/local/www/firewall_schedule_edit.php @@ -0,0 +1,900 @@ +. + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +$pgtitle = "Firewall: Schedules: Edit"; +require("guiconfig.inc"); + +$starttimehr = 00; +$starttimemin = 00; + +$stoptimehr = 24; +$stoptimemin = 00; + +$dayArray = array ('Sun','Mon','Tues','Wed','Thur','Fri','Sat'); +$monthArray = array ('January','February','March','April','May','June','July','August','September','October','November','December'); + +if (!is_array($config['schedules']['schedule'])) + $config['schedules']['schedule'] = array(); + +schedule_sort(); +$a_schedules = &$config['schedules']['schedule']; + +$id = $_GET['id']; +if (isset($_POST['id'])) + $id = $_POST['id']; + +if (isset($id) && $a_schedules[$id]) { + $pconfig['name'] = $a_schedules[$id]['name']; + $pconfig['descr'] = html_entity_decode($a_schedules[$id]['descr']); + $pconfig['timerange'] = $a_schedules[$id]['timerange']; + $pconfig['timedescr'] = html_entity_decode($a_schedules[$id]['timedescr']); + $getSchedule = true; +} + +if ($_POST) { + + if(strtolower($_POST['name']) == "lan") + $input_errors[] = "Schedule may not be named LAN."; + if(strtolower($_POST['name']) == "wan") + $input_errors[] = "Schedule may not be named WAN."; + + $x = is_validaliasname($_POST['name']); + if (!isset($x)) { + $input_errors[] = "Reserved word used for schedule name."; + } else { + if (is_validaliasname($_POST['name']) == false) + $input_errors[] = "The schedule name may only consist of the characters a-z, A-Z, 0-9, -, _."; + } + + /* check for name conflicts */ + foreach ($a_schedules as $schedule) { + if (isset($id) && ($a_schedules[$id]) && ($a_schedules[$id] === $schedule)) + continue; + + if ($schedule['name'] == $_POST['name']) { + $input_errors[] = "A Schedule with this name already exists."; + break; + } + } + $schedule = array(); + + for ($x=0; $x<99; $x++){ + if($_POST['schedule' . $x]) { + $timestr .= $_POST['schedule' . $x]; + $timestr .= $_POST['starttime' . $x]; + $timestr .= "-"; + $timestr .= $_POST['stoptime' . $x]; + $timestr .= "||"; + $timedescrstr .= htmlentities($_POST['timedescr' . $x], ENT_QUOTES, 'UTF-8'); + $timedescrstr .= "||"; + } + } + + $schedule['name'] = $_POST['name']; + $schedule['descr'] = htmlentities($_POST['descr'], ENT_QUOTES, 'UTF-8'); + $schedule['timerange'] = $timestr; + $schedule['timedescr'] = $timedescrstr; + + if (!$input_errors) { + + if (isset($id) && $a_schedules[$id]) + $a_schedules[$id] = $schedule; + else + $a_schedules[] = $schedule; + + write_config(); + + header("Location: firewall_schedule.php"); + exit; + + } + //we received input errors, copy data to prevent retype + else + { + $getSchedule = true; + $pconfig['descr'] = $schedule['descr'] = htmlentities($_POST['descr'], ENT_QUOTES, 'UTF-8'); + $pconfig['timerange'] = $schedule['timerange']; + $pconfig['timedescr'] = $schedule['timedescr']; + } + +} +include("head.inc"); + +/* put your custom HTML head content here */ +/* using some of the $pfSenseHead function calls */ +$jscriptstr = << + +var daysSelected = ""; +var month_array = ['January','February','March','April','May','June','July','August','September','October','November','December']; +var day_array = ['Sun','Mon','Tues','Wed','Thur','Fri','Sat']; +var schCounter = 0; + +function repeatExistingDays(){ + var tempstr, tempstrdaypos, week, daypos, dayposdone = ""; + + var dayarray = daysSelected.split(","); + for (i=0; i<=dayarray.length; i++){ + tempstr = dayarray[i]; + tempstrdaypos = tempstr.search("p"); + week = tempstr.substring(1,tempstrdaypos); + week = parseInt(week); + dashpos = tempstr.search("-"); + daypos = tempstr.substring(tempstrdaypos+1, dashpos); + daypos = parseInt(daypos); + + daydone = dayposdone.search(daypos); + tempstr = 'w' + week + 'p' + daypos; + daycell = eval('document.getElementById(tempstr)'); + if (daydone == "-1"){ + if (daycell.style.backgroundColor == "lightcoral") + daytogglerepeating(week,daypos,true); + else + daytogglerepeating(week,daypos,false); + dayposdone += daypos + ","; + } + } +} + +function daytogglerepeating(week,daypos,bExists){ + var tempstr, daycell, dayoriginal = ""; + for (j=1; j<=53; j++) + { + tempstr = 'w' + j + 'p' + daypos; + daycell = eval('document.getElementById(tempstr)'); + dayoriginalpos = daysSelected.indexOf(tempstr); + + //if bExists set to true, means cell is already select it + //unselect it and remove original day from daysSelected string + + if (daycell != null) + { + if (bExists){ + daycell.style.backgroundColor = "WHITE"; + } + else + { + daycell.style.backgroundColor = "lightcoral"; + } + + if (dayoriginalpos != "-1") + { + dayoriginalend = daysSelected.indexOf(',', dayoriginalpos); + tempstr = daysSelected.substring(dayoriginalpos, dayoriginalend+1); + daysSelected = daysSelected.replace(tempstr, ""); + + } + } + } +} + +function daytoggle(id) { + var runrepeat, tempstr = ""; + var bFoundValid = false; + + iddashpos = id.search("-"); + var tempstrdaypos = id.search("p"); + var week = id.substring(1,tempstrdaypos); + week = parseInt(week); + + if (iddashpos == "-1") + { + idmod = id; + runrepeat = true; + var daypos = id.substr(tempstrdaypos+1); + } + else + { + idmod = id.substring(0,iddashpos); + var daypos = id.substring(tempstrdaypos+1,iddashpos); + } + + daypos = parseInt(daypos); + + while (!bFoundValid){ + var daycell = document.getElementById(idmod); + + if (daycell != null){ + if (daycell.style.backgroundColor == "RED"){ + daycell.style.backgroundColor = "WHITE"; + str = id + ","; + daysSelected = daysSelected.replace(str, ""); + } + else if (daycell.style.backgroundColor == "lightcoral") + { + daytogglerepeating(week,daypos,true); + } + else //color is white cell + { + if (!runrepeat) + { + daycell.style.backgroundColor = "RED"; + } + else + { + daycell.style.backgroundColor = "lightcoral"; + daytogglerepeating(week,daypos,false); + } + daysSelected += id + ","; + } + bFoundValid = true; + } + else + { + //we found an invalid cell when column was clicked, move up to the next week + week++; + tempstr = "w" + week + "p" + daypos; + idmod = tempstr; + } + } +} + +function update_month(){ + var indexNum = document.forms[0].monthsel.selectedIndex; + var selected = document.forms[0].monthsel.options[indexNum].text; + + for (i=0; i<=11; i++){ + option = document.forms[0].monthsel.options[i].text; + document.popupMonthLayer = eval('document.getElementById (option)'); + + if(selected == option) { + document.popupMonthLayer.style.display="block"; + } + else + document.popupMonthLayer.style.display="none"; + } +} + +//limit numbers only input for time range input boxes +function checkKeyEntry(incEvent) +{ + //cross browser support + if (incEvent.which) + var code = incEvent.which; + else + var code = event.keyCode; + + if (code > 31 && (code < 48 || code > 57)) + return false; + else + return true; +} + +//check time limits +function checkTimeLimits(){ + var starttimehour, starttimemin, stoptimehour, stoptimemin = ""; + + //get time specified + starttimehour = parseInt(document.getElementById("starttimehour").value); + starttimemin = parseInt(document.getElementById("starttimemin").value); + stoptimehour = parseInt(document.getElementById("stoptimehour").value); + stoptimemin = parseInt(document.getElementById("stoptimemin").value); + + //check limits + if (starttimehour > 23) + document.getElementById("starttimehour").value = 23; + if (starttimemin > 59) + document.getElementById("starttimemin").value = 59; + if (stoptimehour >= 24){ + document.getElementById("stoptimehour").value = 24; + document.getElementById("stoptimemin").value = 0; + } + if (stoptimemin > 59) + if (stoptimehour != 24) + document.getElementById("stoptimemin").value = 59; + else + document.getElementById("stoptimemin").value = 0; +} + +function processEntries(){ + var tempstr, starttimehour, starttimemin, stoptimehour, stoptimemin, errors = ""; + var passedValidiation = true; + + //get time specified + starttimehour = parseInt(document.getElementById("starttimehour").value); + starttimemin = parseInt(document.getElementById("starttimemin").value); + stoptimehour = parseInt(document.getElementById("stoptimehour").value); + stoptimemin = parseInt(document.getElementById("stoptimemin").value); + + //do time checks + if (starttimehour > stoptimehour) + { + errors = "Error: Start Hour cannot be greater than Stop Hour."; + passedValidiation = false; + } + else if (starttimehour = stoptimehour) + { + if (starttimemin > stoptimemin){ + errors = "Error: Start Minute cannot be greater than Stop Minute."; + passedValidiation = false; + } + } + + if (passedValidiation){ + addTimeRange(); + } + else if (errors != "") + alert(errors); +} + +function addTimeRange(){ + var tempdayarray = daysSelected.split(","); + var tempstr, tempFriendlyDay, starttimehour, starttimemin, stoptimehour, tempFriendlyTime, tempID, stoptimemin, timeRange, tempstrdaypos, week, daypos, day, month, dashpos, tempTime = ""; + tempFriendlyTime = ""; + tempID = ""; + tempdayarray.sort(); + tempFriendlyDay = ""; + + + //check for existing entries + var findCurrentCounter; + for (u=0; u<99; u++){ + findCurrentCounter = document.getElementById("schedule" + u); + if (!findCurrentCounter) + { + //found last entry, bump id number up by 1 + u++ + schCounter = u; + break; + } + } + + if (daysSelected != ""){ + //get days selected + for (i=0; i"; + tr.appendChild(td); + + td = d.createElement("td"); + td.innerHTML=""; + tr.appendChild(td); + + td = d.createElement("td"); + td.innerHTML=""; + tr.appendChild(td); + + td = d.createElement("td"); + td.innerHTML=td.innerHTML=""; + tr.appendChild(td); + + td = d.createElement("td"); + td.innerHTML = ""; + tr.appendChild(td); + + td = d.createElement("td"); + td.innerHTML = ""; + tr.appendChild(td); + + td = d.createElement("td"); + td.innerHTML=""; + tr.appendChild(td); + tbody.appendChild(tr); + + schCounter++; + + //reset calendar and time and descr + clearCalendar(); + clearTime(); + clearDescr(); + } + else + { + //no days were selected, alert user + alert ("You must select at least 1 day before adding time"); + } +} + + +function clearCalendar(){ + var tempstr, daycell = ""; + //clear days selected + daysSelected = ""; + //loop through all 52 weeks + for (j=1; j<=53; j++) + { + //loop through all 7 days + for (k=0; k<7; k++){ + tempstr = 'w' + j + 'p' + k; + daycell = eval('document.getElementById(tempstr)'); + if (daycell != null){ + daycell.style.backgroundColor = "WHITE"; + } + } + } +} + +function clearTime(){ + document.getElementById("starttimehour").value = $starttimehr; + document.getElementById("starttimemin").value = $starttimemin; + document.getElementById("stoptimehour").value = $stoptimehr; + document.getElementById("stoptimemin").value = $stoptimemin; +} + +function clearDescr(){ + document.getElementById("timerangedescr").value = ""; +} + +function editRow(incTime) { + //reset calendar and time + clearCalendar(); + clearTime(); + + var starttimehour, descr, days, tempstr, starttimemin, hours, stoptimehour, stoptimemin = ""; + + tempArray = incTime.split ("||"); + + days = tempArray[0]; + hours = tempArray[1]; + descr = tempArray[2]; + + var tempdayArray = days.split(","); + var temphourArray = hours.split("-"); + tempstr = temphourArray[0]; + var temphourArray2 = tempstr.split(":"); + + document.getElementById("starttimehour").value = temphourArray2[0]; + document.getElementById("starttimemin").value = temphourArray2[1]; + + tempstr = temphourArray[1]; + temphourArray2 = tempstr.split(":"); + + document.getElementById("stoptimehour").value = temphourArray2[0]; + document.getElementById("stoptimemin").value = temphourArray2[1]; + + document.getElementById("timerangedescr").value = descr; + + //toggle the appropriate days + for (i=0; i +EOD; +?> + +"> + + + + +

    + + +
    + +
    + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Schedule Name +
    + + The name of the alias may only consist of the characters a-z, A-Z and 0-9. + +
    Description
    + + You may enter a description here for your reference (not parsed). + +
    Month +

    + +
    " z-index:-1000; style="position:relative; display:"> + + + + + + + + + + + + + + "; + } + if ($firstdayofmonth == $weekdaycounter){?> + "; + } + + //if day is Saturday, + if ($weekdaycounter == 6) + { + $weekdaycounter = 0; + $weekcounter++; + echo ""; + } + else{ + $weekdaycounter++; + } + }?> +
    SunMonTueWedThuFriSat
    + "; + } + elseif ($firstdayprinted == TRUE && $daycounter <= $numberofdays){?> + + "; + } + else + { + echo "
    +
    + +
    + Click individual date to select that date only. Click the appropriate weekday Header to select all occurences of that weekday. +
    Time + + + + + + + + + +
    Start TimeStop Time
    +  Hr   +  Min + +  Hr   +  Min +

    + Enter the time range (in 24 hour format) for the day(s) selected on the Month(s) above. +
    Time Range Description
    + + You may enter a description here for your reference (not parsed). + +
      +     + +
    +
    Configured Ranges + + + + + + + + + + + + + + + + + + + + +
    Day(s)Start TimeStop TimeDescription
    + + + + + + + + + /images/icons/icon_e.gif' onclick='editRow(""); removeRow(this); return false;' value='Edit'> + + /images/icons/icon_x.gif' onclick='removeRow(this); return false;' value='Delete'> + + +
    +
      + + + + + +
    + +
    + + + \ No newline at end of file diff --git a/usr/local/www/guiconfig.inc b/usr/local/www/guiconfig.inc index 7f39ae6e19..a6c1c00bdb 100755 --- a/usr/local/www/guiconfig.inc +++ b/usr/local/www/guiconfig.inc @@ -443,6 +443,17 @@ function aliases_sort() { usort($config['aliases']['alias'], "aliascmp"); } +function schedule_sort(){ + global $g, $config; + + function schedulecmp($a, $b) { + return strcmp($a['name'], $b['name']); + } + + usort($config['schedules']['schedule'], "schedulecmp"); + +} + function ipsec_mobilekey_sort() { global $g, $config;