Project

General

Profile

Download (13.7 KB) Statistics
| Branch: | Tag: | Revision:
1 5b237745 Scott Ullrich
<?php
2 b46bfcf5 Bill Marquette
/* $Id$ */
3 5b237745 Scott Ullrich
/*
4 197bfe96 Ermal Luçi
	firewall_shaper.php
5
	Copyright (C) 2004, 2005 Scott Ullrich
6 1d7ba683 ayvis
	Copyright (C) 2008 Ermal Luçi
7 dd447bde Jim Thompson
        Copyright (C) 2013-2014 Electric Sheep Fencing, LP
8 197bfe96 Ermal Luçi
	All rights reserved.
9 b49448ac Scott Ullrich
10 197bfe96 Ermal Luçi
	Redistribution and use in source and binary forms, with or without
11
	modification, are permitted provided that the following conditions are met:
12 b49448ac Scott Ullrich
13 197bfe96 Ermal Luçi
	1. Redistributions of source code must retain the above copyright notice,
14
	   this list of conditions and the following disclaimer.
15 b49448ac Scott Ullrich
16 197bfe96 Ermal Luçi
	2. Redistributions in binary form must reproduce the above copyright
17
	   notice, this list of conditions and the following disclaimer in the
18
	   documentation and/or other materials provided with the distribution.
19 b49448ac Scott Ullrich
20 197bfe96 Ermal Luçi
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
22
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
24
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29
	POSSIBILITY OF SUCH DAMAGE.
30 5b237745 Scott Ullrich
*/
31 7ac5a4cb Scott Ullrich
/*
32
	pfSense_BUILDER_BINARIES:	/usr/bin/killall
33
	pfSense_MODULE:	shaper
34
*/
35 5b237745 Scott Ullrich
36 6b07c15a Matthew Grooms
##|+PRIV
37
##|*IDENT=page-firewall-trafficshaper
38
##|*NAME=Firewall: Traffic Shaper page
39
##|*DESCR=Allow access to the 'Firewall: Traffic Shaper' page.
40
##|*MATCH=firewall_shaper.php*
41
##|-PRIV
42
43 5b237745 Scott Ullrich
require("guiconfig.inc");
44 7a927e67 Scott Ullrich
require_once("functions.inc");
45
require_once("filter.inc");
46
require_once("shaper.inc");
47 a5f07f09 Ermal Lu?i
require_once("rrd.inc");
48 5b237745 Scott Ullrich
49 1b2c6c29 Ermal Luçi
if($_GET['reset'] <> "") {
50 7ac5a4cb Scott Ullrich
	/* XXX: Huh, why are we killing php? */
51
	mwexec("killall -9 pfctl php");
52 8f8a97c8 Ermal Luçi
	exit;
53 1b2c6c29 Ermal Luçi
}
54
55 4e52fac4 Carlos Eduardo Ramos
$pgtitle = array(gettext("Firewall"),gettext("Traffic Shaper"));
56 b32dd0a6 jim-p
$shortcut_section = "trafficshaper";
57 09eafb8b Scott Ullrich
58 9d5b21c6 Ermal Luçi
$shaperIFlist = get_configured_interface_with_descr();
59 197bfe96 Ermal Luçi
read_altq_config();
60
/* 
61
 * The whole logic in these code maybe can be specified.
62
 * If you find a better way contact me :).
63
 */
64 57b89461 Scott Ullrich
65 197bfe96 Ermal Luçi
if ($_GET) {
66
	if ($_GET['queue'])
67
        	$qname = trim($_GET['queue']);
68
        if ($_GET['interface'])
69 daab67a1 Scott Ullrich
                $interface = htmlspecialchars(trim($_GET['interface']));
70 197bfe96 Ermal Luçi
        if ($_GET['action'])
71 daab67a1 Scott Ullrich
                $action = htmlspecialchars($_GET['action']);
72 197bfe96 Ermal Luçi
}
73
if ($_POST) {
74
	if ($_POST['name'])
75 daab67a1 Scott Ullrich
        	$qname = htmlspecialchars(trim($_POST['name']));
76 197bfe96 Ermal Luçi
        if ($_POST['interface'])
77 daab67a1 Scott Ullrich
                $interface = htmlspecialchars(trim($_POST['interface']));
78 197bfe96 Ermal Luçi
	if ($_POST['parentqueue'])
79 daab67a1 Scott Ullrich
		$parentqueue = htmlspecialchars(trim($_POST['parentqueue']));
80 57b89461 Scott Ullrich
}
81
82 197bfe96 Ermal Luçi
if ($interface) {
83
	$altq = $altq_list_queues[$interface];
84
	if ($altq) {
85
		$queue =& $altq->find_queue($interface, $qname);
86
	} else $addnewaltq = true;
87 57b89461 Scott Ullrich
}
88
89 197bfe96 Ermal Luçi
$dontshow = false;
90
$newqueue = false;
91 92125c97 Ermal Luçi
$output_form = "";
92 5b237745 Scott Ullrich
93 197bfe96 Ermal Luçi
if ($_GET) {
94
	switch ($action) {
95
	case "delete":
96
			if ($queue) {
97
				$queue->delete_queue();
98 3a343d73 jim-p
				if (write_config())
99
					mark_subsystem_dirty('shaper');
100 197bfe96 Ermal Luçi
			}
101
			header("Location: firewall_shaper.php");
102
			exit;
103
		break;
104 26dfbf80 Ermal Luçi
	case "resetall":
105
			foreach ($altq_list_queues as $altq)
106
				$altq->delete_all();
107
			unset($altq_list_queues);
108
			$altq_list_queues = array();
109
			$tree = "<ul class=\"tree\" >";
110
			$tree .= get_interface_list_to_show();
111
			$tree .= "</ul>";
112
			unset($config['shaper']['queue']);
113
			unset($queue);
114
			unset($altq);
115
			$can_add = false;
116
			$can_enable = false;
117
			$dontshow = true;
118
			foreach ($config['filter']['rule'] as $key => $rule) {
119
				if (isset($rule['wizard']) && $rule['wizard'] == "yes")
120
					unset($config['filter']['rule'][$key]);
121
			}
122 3a343d73 jim-p
			if (write_config()) {
123
				$retval = 0;
124
				$retval |= filter_configure();
125
				$savemsg = get_std_save_message($retval);
126 26dfbf80 Ermal Luçi
127 3a343d73 jim-p
				if (stristr($retval, "error") <> true)
128
					$savemsg = get_std_save_message($retval);
129
				else
130
					$savemsg = $retval;
131
			} else {
132
				$savemsg = gettext("Unable to write config.xml (Access Denied?)");
133
			}
134 26dfbf80 Ermal Luçi
			$output_form = $default_shaper_message;
135
136
		break;
137 197bfe96 Ermal Luçi
	case "add":
138
			/* XXX: Find better way because we shouldn't know about this */
139
		if ($altq) {
140
	                switch ($altq->GetScheduler()) {
141
         	        case "PRIQ":
142
                	        $q = new priq_queue();
143
                        	break;
144 c563b7a8 Ermal Luçi
			case "FAIRQ":
145
				$q = new fairq_queue();
146
				break;
147 197bfe96 Ermal Luçi
                        case "HFSC":
148
                         	$q = new hfsc_queue();
149
                        	break;
150
                        case "CBQ":
151
                                $q = new cbq_queue();
152
                        	break;
153
                        default:
154
                                /* XXX: Happens when sched==NONE?! */
155
				$q = new altq_root_queue();
156
                        	break;
157
        		}
158
		} else if ($addnewaltq) {
159
			$q = new altq_root_queue();
160
		} else 
161 1c52312d Jeann
			$input_errors[] = gettext("Could not create new queue/discipline!");
162 197bfe96 Ermal Luçi
163
			if ($q) {
164
				$q->SetInterface($interface);
165 92125c97 Ermal Luçi
				$output_form .= $q->build_form();
166
				$output_form .= "<input type=\"hidden\" name=\"parentqueue\" id=\"parentqueue\"";
167 df5c0bc0 Colin Fleming
				$output_form .= " value=\"".$qname."\" />";
168 bdb0d479 Ermal Luçi
				$newjavascript = $q->build_javascript();
169 197bfe96 Ermal Luçi
                unset($q);
170
				$newqueue = true;
171
			}
172
		break;
173
		case "show":
174
			if ($queue)  
175 92125c97 Ermal Luçi
                        $output_form .= $queue->build_form();
176 197bfe96 Ermal Luçi
			else
177 1c52312d Jeann
					$input_errors[] = gettext("Queue not found!");
178 197bfe96 Ermal Luçi
		break;
179
		case "enable":
180
			if ($queue) {
181
					$queue->SetEnabled("on");
182 92125c97 Ermal Luçi
					$output_form .= $queue->build_form();
183 3a343d73 jim-p
					if (write_config())
184
						mark_subsystem_dirty('shaper');
185 197bfe96 Ermal Luçi
			} else
186 1c52312d Jeann
					$input_errors[] = gettext("Queue not found!");
187 197bfe96 Ermal Luçi
		break;
188
		case "disable":
189
			if ($queue) {
190
					$queue->SetEnabled("");
191 92125c97 Ermal Luçi
					$output_form .= $queue->build_form();
192 3a343d73 jim-p
					if (write_config())
193
						mark_subsystem_dirty('shaper');
194 197bfe96 Ermal Luçi
			} else
195 1c52312d Jeann
					$input_errors[] = gettext("Queue not found!");
196 197bfe96 Ermal Luçi
		break;
197
		default:
198 4eb7d4d7 Colin Fleming
			$output_form .= $default_shaper_msg;
199 197bfe96 Ermal Luçi
			$dontshow = true;
200
			break;
201 5b237745 Scott Ullrich
	}
202 197bfe96 Ermal Luçi
} else if ($_POST) {
203
	unset($input_errors);
204 5b237745 Scott Ullrich
205 197bfe96 Ermal Luçi
	if ($addnewaltq) {
206
		$altq =& new altq_root_queue();
207
		$altq->SetInterface($interface);
208 92125c97 Ermal Luçi
		
209
		switch ($altq->GetBwscale()) {
210
				case "Mb":
211
					$factor = 1000 * 1000;
212
					brak;
213
				case "Kb":
214
					$factor = 1000;
215
					break;
216
				case "b":
217
					$factor = 1;
218
					break;
219
				case "Gb":
220
					$factor = 1000 * 1000 * 1000;
221
					break;
222
				case "%": /* We don't use it for root_XXX queues. */
223
				default: /* XXX assume Kb by default. */
224
					$factor = 1000;
225
					break;
226
			} 
227
		$altq->SetAvailableBandwidth($altq->GetBandwidth() * $factor);
228 197bfe96 Ermal Luçi
		$altq->ReadConfig($_POST);
229 ea51e9f8 Renato Botelho
		$altq->validate_input($_POST, $input_errors);
230 92125c97 Ermal Luçi
		if (!$input_errors) {
231
			unset($tmppath);
232
			$tmppath[] = $altq->GetInterface();
233 ea51e9f8 Renato Botelho
			$altq->SetLink($tmppath);	
234 92125c97 Ermal Luçi
			$altq->wconfig();
235 3a343d73 jim-p
			if (write_config())
236
				mark_subsystem_dirty('shaper');
237 92125c97 Ermal Luçi
			$can_enable = true;
238 fce82460 Ermal Luçi
                        $can_add = true;
239 92125c97 Ermal Luçi
		}
240 48d418e8 Ermal Luçi
		read_altq_config();
241 92125c97 Ermal Luçi
		$output_form .= $altq->build_form();
242
243 197bfe96 Ermal Luçi
	} else if ($parentqueue) { /* Add a new queue */
244
		$qtmp =& $altq->find_queue($interface, $parentqueue);
245
		if ($qtmp) {
246
			$tmppath =& $qtmp->GetLink();
247
			array_push($tmppath, $qname);
248 ea51e9f8 Renato Botelho
			$tmp =& $qtmp->add_queue($interface, $_POST, $tmppath, $input_errors);
249 92125c97 Ermal Luçi
			if (!$input_errors) {
250
				array_pop($tmppath);
251
				$tmp->wconfig();
252
				$can_enable = true;
253 70b139a3 Chris Buechler
				if ($tmp->CanHaveChildren() && $can_enable) {
254 fce82460 Ermal Luçi
					if ($tmp->GetDefault() <> "")
255 96d1d4ad Ermal Luçi
                             			$can_add = false;
256
                        		else
257
                             			$can_add = true;
258
				} else
259 92125c97 Ermal Luçi
					$can_add = false;
260 3a343d73 jim-p
				if (write_config())
261
					mark_subsystem_dirty('shaper');
262 92125c97 Ermal Luçi
				$can_enable = true;
263
				if ($altq->GetScheduler() != "PRIQ") /* XXX */
264 fce82460 Ermal Luçi
					if ($tmp->GetDefault() <> "")
265 96d1d4ad Ermal Luçi
                                                $can_add = false;
266
                                        else
267
                                                $can_add = true;
268 92125c97 Ermal Luçi
			}
269 48d418e8 Ermal Luçi
			read_altq_config();
270 92125c97 Ermal Luçi
			$output_form .= $tmp->build_form();			
271 197bfe96 Ermal Luçi
		} else
272 2f8fe6af Carlos Eduardo Ramos
			$input_errors[] = gettext("Could not add new queue.");
273 197bfe96 Ermal Luçi
	} else if ($_POST['apply']) {
274 92125c97 Ermal Luçi
			write_config();
275 0df08a41 Scott Ullrich
276 92125c97 Ermal Luçi
			$retval = 0;
277
			$retval = filter_configure();
278 0027de0a Ermal Lu?i
			$savemsg = get_std_save_message($retval);
279 92125c97 Ermal Luçi
			
280
			if (stristr($retval, "error") <> true)
281
					$savemsg = get_std_save_message($retval);
282
			else
283
					$savemsg = $retval;
284 5b237745 Scott Ullrich
285 96b777d6 Ermal Luçi
 		/* reset rrd queues */
286 7ac5a4cb Scott Ullrich
		system("rm -f /var/db/rrd/*queuedrops.rrd");
287
		system("rm -f /var/db/rrd/*queues.rrd");
288
		enable_rrd_graphing();
289 1f276138 Scott Ullrich
290 a368a026 Ermal Lu?i
		clear_subsystem_dirty('shaper');
291 92125c97 Ermal Luçi
			
292
			if ($queue) {
293
				$output_form .= $queue->build_form();
294
				$dontshow = false;
295
			}
296
			else {
297
				$output_form .= $default_shaper_message;
298
				$dontshow = true;
299
			}
300 1f276138 Scott Ullrich
301 197bfe96 Ermal Luçi
	} else if ($queue) {
302 ea51e9f8 Renato Botelho
                $queue->validate_input($_POST, $input_errors);
303 197bfe96 Ermal Luçi
                if (!$input_errors) {
304 92125c97 Ermal Luçi
                            $queue->update_altq_queue_data($_POST);
305
                            $queue->wconfig();
306 3a343d73 jim-p
				if (write_config())
307
					mark_subsystem_dirty('shaper');
308 92125c97 Ermal Luçi
				$dontshow = false;
309
                } 
310 48d418e8 Ermal Luçi
		read_altq_config();
311
		$output_form .= $queue->build_form();
312 92125c97 Ermal Luçi
	} else  {
313 4eb7d4d7 Colin Fleming
		$output_form .= $default_shaper_msg;
314 92125c97 Ermal Luçi
		$dontshow = true;
315
	}
316 5f471c95 Ermal
	mwexec("killall qstats");
317 0ceb8927 Bill Marquette
} else {
318 4eb7d4d7 Colin Fleming
	$output_form .= $default_shaper_msg;
319 197bfe96 Ermal Luçi
	$dontshow = true;
320
}
321 0ceb8927 Bill Marquette
322 fce82460 Ermal Luçi
if ($queue) {
323
                        if ($queue->GetEnabled())
324
                                $can_enable = true;
325
                        else
326
                                $can_enable = false;
327 70b139a3 Chris Buechler
                        if ($queue->CanHaveChildren() && $can_enable) { 
328 58dc3a03 Ermal Luçi
                                if ($altq->GetQname() <> $queue->GetQname() && $queue->GetDefault() <> "")
329 fce82460 Ermal Luçi
                                        $can_add = false;
330
                                else
331
                                        $can_add = true;
332
                        } else
333
                                $can_add = false;
334
}
335
336
$tree = "<ul class=\"tree\" >";
337
if (is_array($altq_list_queues)) {
338 a843b04f Ermal Luçi
        foreach ($altq_list_queues as $tmpaltq) {
339
                $tree .= $tmpaltq->build_tree();
340 fce82460 Ermal Luçi
        }
341
$tree .=  get_interface_list_to_show();
342
}
343
$tree .= "</ul>";
344 0ceb8927 Bill Marquette
345 197bfe96 Ermal Luçi
if (!$dontshow || $newqueue) {
346 0ceb8927 Bill Marquette
347 7da5315d Colin Fleming
$output_form .= "<tr><td width=\"22%\" valign=\"middle\" class=\"vncellreq\">";
348 270f81d9 Renato Botelho
$output_form .= "<br />" . gettext("Queue Actions") . "<br />";
349 7da5315d Colin Fleming
$output_form .= "</td><td valign=\"middle\" class=\"vncellreq\" width=\"78%\"><br />";
350 197bfe96 Ermal Luçi
351 92125c97 Ermal Luçi
$output_form .= "<input type=\"submit\" name=\"Submit\" value=\"" . gettext("Save") . "\" class=\"formbtn\" />";
352 197bfe96 Ermal Luçi
if ($can_add || $addnewaltq) {
353 92125c97 Ermal Luçi
	$output_form .= "<a href=\"firewall_shaper.php?interface=";
354
	$output_form .= $interface; 
355
	if ($queue) {
356 df5c0bc0 Colin Fleming
		$output_form .= "&amp;queue=" . $queue->GetQname();
357 92125c97 Ermal Luçi
	}
358 df5c0bc0 Colin Fleming
	$output_form .= "&amp;action=add\">";
359
	$output_form .= "<input type=\"button\" class=\"formbtn\" name=\"add\" value=\"" . gettext("Add new queue") . "\" />";
360 92125c97 Ermal Luçi
	$output_form .= "</a>";
361 5b237745 Scott Ullrich
}
362 a22537c7 Renato Botelho
$output_form .= "<a href=\"firewall_shaper.php?interface=";
363
$output_form .= $interface . "&amp;queue=";
364
if ($queue) {
365
	$output_form .= "&amp;queue=" . $queue->GetQname();
366
}
367
$output_form .= "&amp;action=delete\">";
368
$output_form .= "<input type=\"button\" class=\"formbtn\" name=\"delete\"";
369
if ($queue)
370
	$output_form .= " value=\"" . gettext("Delete this queue") . "\" />";
371
else
372
	$output_form .= " value=\"" . gettext("Disable shaper on interface") . "\" />";
373
$output_form .= "</a>";
374 f5e511d3 Ermal
$output_form .= "<br /></td></tr>";
375 4eb7d4d7 Colin Fleming
$output_form .= "</table>";
376 f5e511d3 Ermal
}
377 197bfe96 Ermal Luçi
else 
378 4eb7d4d7 Colin Fleming
	$output_form .= "</table>";
379 92125c97 Ermal Luçi
380 4eb7d4d7 Colin Fleming
$output = "<table  summary=\"output form\">";
381 92125c97 Ermal Luçi
$output .= $output_form;
382 52380979 Scott Ullrich
383 58dc3a03 Ermal Luçi
//$pgtitle = "Firewall: Shaper: By Interface View";
384 df5c0bc0 Colin Fleming
$closehead = false;
385 197bfe96 Ermal Luçi
include("head.inc");
386 5b237745 Scott Ullrich
?>
387 197bfe96 Ermal Luçi
<link rel="stylesheet" type="text/css" media="all" href="./tree/tree.css" />
388
<script type="text/javascript" src="./tree/tree.js"></script>
389 df5c0bc0 Colin Fleming
</head>
390
391
<body link="#0000CC" vlink="#0000CC" alink="#0000CC" >
392 92125c97 Ermal Luçi
<?php
393 1309fadd Ermal
if ($queue)
394 92125c97 Ermal Luçi
        echo $queue->build_javascript();
395 bdb0d479 Ermal Luçi
echo $newjavascript;
396 5b237745 Scott Ullrich
397 92125c97 Ermal Luçi
include("fbegin.inc"); 
398
?>
399 197bfe96 Ermal Luçi
<div id="inputerrors"></div>
400
<?php if ($input_errors) print_input_errors($input_errors); ?>
401
402 92125c97 Ermal Luçi
<form action="firewall_shaper.php" method="post" id="iform" name="iform">
403 197bfe96 Ermal Luçi
404 5b237745 Scott Ullrich
<?php if ($savemsg) print_info_box($savemsg); ?>
405 a368a026 Ermal Lu?i
<?php if (is_subsystem_dirty('shaper')): ?><p>
406 1d7ba683 ayvis
<?php print_info_box_np(gettext("The traffic shaper configuration has been changed.")."<br />".gettext("You must apply the changes in order for them to take effect."));?><br /></p>
407 5b237745 Scott Ullrich
<?php endif; ?>
408 df5c0bc0 Colin Fleming
<table width="100%" border="0" cellpadding="0" cellspacing="0" summary="traffic shaper">
409 5b237745 Scott Ullrich
  <tr><td>
410 52380979 Scott Ullrich
<?php
411
	$tab_array = array();
412 1c52312d Jeann
	$tab_array[0] = array(gettext("By Interface"), true, "firewall_shaper.php");
413
	$tab_array[1] = array(gettext("By Queue"), false, "firewall_shaper_queues.php");
414
	$tab_array[2] = array(gettext("Limiter"), false, "firewall_shaper_vinterface.php");
415
	$tab_array[3] = array(gettext("Layer7"), false, "firewall_shaper_layer7.php");
416
	$tab_array[4] = array(gettext("Wizards"), false, "firewall_shaper_wizards.php");
417 52380979 Scott Ullrich
	display_top_tabs($tab_array);
418 197bfe96 Ermal Luçi
?>
419 5b237745 Scott Ullrich
  </td></tr>
420
  <tr>
421 d732f186 Bill Marquette
    <td>
422
	<div id="mainarea">
423 df5c0bc0 Colin Fleming
              <table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0" summary="main area">
424 26dfbf80 Ermal Luçi
<?php if (count($altq_list_queues) > 0): ?>
425
                        <tr class="tabcont"><td width="25%" align="left">
426
                                <a href="firewall_shaper.php?action=resetall" >
427 df5c0bc0 Colin Fleming
                                        <input type="button" value="<?=gettext("Remove Shaper")?>" class="formbtn" />
428 26dfbf80 Ermal Luçi
                                </a>
429
                        </td><td width="75%"> </td></tr>
430 ee9933b6 Renato Botelho
<?php endif; ?>
431 197bfe96 Ermal Luçi
			<tr>
432 df5c0bc0 Colin Fleming
			<td width="25%" valign="top" align="left">
433 197bfe96 Ermal Luçi
			<?php
434
				echo $tree; 
435
			?>
436
			</td>
437
			<td width="75%" valign="top" align="center">
438 4eb7d4d7 Colin Fleming
			<div id="shaperarea" style="position:relative">
439 df5c0bc0 Colin Fleming
			<?php
440 197bfe96 Ermal Luçi
				echo $output;
441
			?>	
442 4eb7d4d7 Colin Fleming
			</div>
443 e295675f Scott Ullrich
444 197bfe96 Ermal Luçi
		      </td></tr>
445 d732f186 Bill Marquette
                    </table>
446
		</div>
447
	  </td>
448 5b237745 Scott Ullrich
	</tr>
449
</table>
450
            </form>
451 df5c0bc0 Colin Fleming
<?php include("fend.inc"); ?>
452 5b237745 Scott Ullrich
</body>
453
</html>