Project

General

Profile

Download (21.3 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/* $Id$ */
3
/*
4
	diag_backup.php
5
	Copyright (C) 2004,2005,2006 Scott Ullrich
6
	All rights reserved.
7

    
8
	originally part of m0n0wall (http://m0n0.ch/wall)
9
	Copyright (C) 2003-2004 Manuel Kasper <mk@neon1.net>.
10
	All rights reserved.
11

    
12
	Redistribution and use in source and binary forms, with or without
13
	modification, are permitted provided that the following conditions are met:
14

    
15
	1. Redistributions of source code must retain the above copyright notice,
16
	   this list of conditions and the following disclaimer.
17

    
18
	2. Redistributions in binary form must reproduce the above copyright
19
	   notice, this list of conditions and the following disclaimer in the
20
	   documentation and/or other materials provided with the distribution.
21

    
22
	THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23
	INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
24
	AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25
	AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
26
	OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27
	SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28
	INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29
	CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30
	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31
	POSSIBILITY OF SUCH DAMAGE.
32
*/
33

    
34
##|+PRIV
35
##|*IDENT=page-diagnostics-backup/restore
36
##|*NAME=Diagnostics: Backup/restore page
37
##|*DESCR=Allow access to the 'Diagnostics: Backup/restore' page.
38
##|*MATCH=diag_backup.php*
39
##|-PRIV
40

    
41

    
42
/* Allow additional execution time 0 = no limit. */
43
ini_set('max_execution_time', '0');
44
ini_set('max_input_time', '0');
45

    
46
/* omit no-cache headers because it confuses IE with file downloads */
47
$omit_nocacheheaders = true;
48
require("guiconfig.inc");
49

    
50
function add_base_packages_menu_items() {
51
	global $g, $config;
52
	$base_packages = split($g['base_packages'], ",");
53
	$modified_config = false;
54
	foreach($base_packages as $bp) {
55
		$basepkg_path = "/usr/local/pkg/{$bp}";
56
		$tmpinfo = pathinfo($basepkg_path, PATHINFO_EXTENSION); 
57
		if($tmpinfo['extension'] == "xml" && file_exists($basepkg_path)) {
58
			$pkg_config = parse_xml_config_pkg($basepkg_path, "packagegui");
59
			if($pkg_config['menu'] != "") {
60
				if(is_array($pkg_config['menu'])) {
61
					foreach($pkg_config['menu'] as $menu) {
62
						if(is_array($config['installedpackages']['menu']))
63
							foreach($config['installedpackages']['menu'] as $amenu)
64
								if($amenu['name'] == $menu['name'])
65
									continue;
66
						$config['installedpackages']['menu'][] = $menu;
67
						$modified_config = true;
68
					}
69
				}
70
				$static_output .= "done.\n";
71
				update_output_window($static_output);
72
			}
73
		}
74
	}
75
	if($modified_config) {
76
		write_confg("Restored base_package menus after configuration restore.");
77
		$config = parse_config(true);
78
	}
79
}
80

    
81
function remove_bad_chars($string) {
82
	return preg_replace('/[^a-z|_|0-9]/i','',$string);
83
}
84

    
85
function check_and_returnif_section_exists($section) {
86
	global $config;
87
	if(is_array($config[$section]))
88
		return true;
89
	return false;
90
}
91

    
92
function spit_out_select_items($area, $showall) {
93
	global $config;
94
		
95
	$areas = array("aliases" => "Aliases", 
96
				   "captiveportal" => "Captive Portal",
97
				   "dnsmasq" => "DNS Forwarder",				
98
				   "dhcpd" => "DHCP Server",
99
				   "filter" => "Firewall Rules",
100
				   "interfaces" => "Interfaces",
101
				   "ipsec" => "IPSEC",
102
				   "nat" => "NAT",
103
				   "ovpn" => "OpenVPN",
104
				   "installedpackages" => "Package Manager",
105
				   "pptpd" => "PPTP Server",
106
				   "cron" => "Scheduled Tasks",				
107
				   "syslog" => "Syslog",
108
				   "system" => "System",
109
				   "staticroutes" => "Static routes",
110
				   "sysctl" => "System tunables",
111
				   "snmpd" => "SNMP Server",
112
				   "shaper" => "Traffic Shaper",
113
				   "vlans" => "VLANS",
114
				   "wol" => "Wake on LAN"
115
	);
116

    
117
	$select  = "<select name=\"{$area}\">\n";
118
	$select .= "<option VALUE=\"\">ALL</option>";
119

    
120
	if($showall == true) 
121
		foreach($areas as $area => $areaname)
122
			$select .= "<option value='{$area}'>{$areaname}</option>\n";
123
	else 
124
		foreach($areas as $area => $areaname)
125
			if(check_and_returnif_section_exists($area) == true)
126
				$select .= "<option value='{$area}'>{$areaname}</option>\n";
127

    
128
	$select .= "</select>\n";
129
		
130
	echo $select;
131

    
132
}
133

    
134
if ($_POST['apply']) {
135
        ob_flush();
136
        flush();
137
        sleep(5);
138
	conf_mount_rw();
139
	clear_subsystem_dirty("restore");
140
	conf_mount_ro();
141
        mwexec("/sbin/shutdown -r now");
142
        exit;
143
}
144

    
145
if ($_POST) {
146
	unset($input_errors);
147
	if (stristr($_POST['Submit'], "Restore configuration"))
148
		$mode = "restore";
149
	else if (stristr($_POST['Submit'], "Reinstall"))
150
		$mode = "reinstallpackages";
151
	else if (stristr($_POST['Submit'], "Download"))
152
		$mode = "download";
153
	else if (stristr($_POST['Submit'], "Restore version"))
154
		$mode = "restore_ver";
155

    
156
	if ($_POST["nopackages"] <> "")
157
		$options = "nopackages";
158

    
159
	if ($_POST["ver"] <> "")
160
		$ver2restore = $_POST["ver"];
161

    
162
	if ($mode) {
163

    
164
		if ($mode == "download") {
165

    
166
			if ($_POST['encrypt']) {
167
				if(!$_POST['encrypt_password'] || !$_POST['encrypt_passconf'])
168
					$input_errors[] = "You must supply and confirm the password for encryption.";
169
				if($_POST['encrypt_password'] != $_POST['encrypt_passconf'])
170
					$input_errors[] = "The supplied 'Password' and 'Confirm' field values must match.";
171
			}
172

    
173
			if (!$input_errors) {
174

    
175
				$lockbckp = lock('config');
176

    
177
				$host = "{$config['system']['hostname']}.{$config['system']['domain']}";
178
				$name = "config-{$host}-".date("YmdHis").".xml";
179
				$data = "";
180

    
181
				if($options == "nopackages") {
182
					$sfn = "{$g['tmp_path']}/config.xml.nopkg";
183
					exec("sed '/<installedpackages>/,/<\/installedpackages>/d' /conf/config.xml > {$sfn}");
184
					$data = file_get_contents($sfn);
185
				} else {
186
					if(!$_POST['backuparea']) {
187
						/* backup entire configuration */
188
						$data = file_get_contents("{$g['conf_path']}/config.xml");
189
					} else {
190
						/* backup specific area of configuration */
191
						$data = backup_config_section($_POST['backuparea']);
192
						$name = "{$_POST['backuparea']}-{$name}";
193
					}
194
				}
195

    
196
				unlock($lockbckp);
197

    
198
				if ($_POST['encrypt']) {
199
					$data = encrypt_data($data, $_POST['encrypt_password']);
200
					tagfile_reformat($data, $data, "config.xml");
201
				}
202

    
203
				/* 
204
				 *  Backup RRD Data
205
				 */
206
				if(!$_POST['donotbackuprrd']) {
207
					$data = str_replace("</pfsense>", "\t<rrddata>", $data);
208
					$rrd_files_var_db_rrd = split("\n",`cd /var/db/rrd && ls *.rrd`);
209
					foreach($rrd_files_var_db_rrd as $rrd) {
210
						if($rrd) {
211
							$rrd_data = file_get_contents("{$g['vardb_path']}/rrd/{$rrd}");
212
							if($rrd_data) {
213
								$data .= "\t\t<rrddatafile>\n";
214
								$data .= "\t\t\t<filename>{$rrd}</filename>\n";
215
								$data .= "\t\t\t<data>" . base64_encode($rrd_data) . "</data>\n";
216
								$data .= "\t\t</rrddatafile>\n";
217
							}
218
						}
219
					}
220
					$data .= "\t</rrddata>\n";
221
					$data .= "</pfsense>\n";
222
				}
223
				
224
				$size = strlen($data);
225
				header("Content-Type: application/octet-stream");
226
				header("Content-Disposition: attachment; filename={$name}");
227
				header("Content-Length: $size");
228
				echo $data;
229

    
230
				exit;
231
			}
232
		}
233

    
234
		if ($mode == "restore") {
235

    
236
			if ($_POST['decrypt']) {
237
				if(!$_POST['decrypt_password'] || !$_POST['decrypt_passconf'])
238
					$input_errors[] = "You must supply and confirm the password for decryption.";
239
				if($_POST['decrypt_password'] != $_POST['decrypt_passconf'])
240
					$input_errors[] = "The supplied 'Password' and 'Confirm' field values must match.";
241
			}
242

    
243
			if (!$input_errors) {
244

    
245
				if (is_uploaded_file($_FILES['conffile']['tmp_name'])) {
246

    
247
					/* read the file contents */
248
					$data = file_get_contents($_FILES['conffile']['tmp_name']);
249
					if(!$data) {
250
						log_error("Warning, could not read file " . $_FILES['conffile']['tmp_name']);
251
						return 1;
252
					}
253

    
254
					if ($_POST['decrypt']) {
255
						if (!tagfile_deformat($data, $data, "config.xml")) {
256
							$input_errors[] = "The uploaded file does not appear to contain an encrypted pfsense configuration.";
257
							return 1;
258
						}
259
						$data = decrypt_data($data, $_POST['decrypt_password']);
260
					}
261

    
262
					if(stristr($data, "m0n0wall")) {
263
						log_error("Upgrading m0n0wall configuration to pfsense.");
264
						/* m0n0wall was found in config.  convert it. */
265
						$data = str_replace("m0n0wall", "pfsense", $data);
266
						$m0n0wall_upgrade = true;
267
					}
268
					if($_POST['restorearea']) {
269
						/* restore a specific area of the configuration */
270
						if(!stristr($data, $_POST['restorearea'])) {
271
							$input_errors[] = "You have selected to restore a area but we could not locate the correct xml tag.";
272
						} else {
273
							restore_config_section($_POST['restorearea'], $data);
274
							filter_configure();
275
							$savemsg = "The configuration area has been restored.  You may need to reboot the firewall.";
276
						}
277
					} else {
278
						if(!stristr($data, "<" . $g['xml_rootobj'] . ">")) {
279
							$input_errors[] = "You have selected to restore the full configuration but we could not locate a " . $g['xml_rootobj'] . " tag.";
280
						} else {
281
							/* restore the entire configuration */
282
							file_put_contents($_FILES['conffile']['tmp_name'], $data);
283
							if (config_install($_FILES['conffile']['tmp_name']) == 0) {
284
								/* this will be picked up by /index.php */
285
								conf_mount_rw();
286
								mark_subsystem_dirty("restore");
287
								$savemsg = "The configuration has been restored. You need to reboot your firewall.";
288
								touch("/conf/needs_package_sync");
289
								/* remove cache, we will force a config reboot */
290
								if(file_exists("{$g['tmp_path']}/config.cache"))
291
									unlink("{$g['tmp_path']}/config.cache");
292
								$config = parse_config(true);
293
								/* extract out rrd items, unset from $confgi when done */
294
								if($config['rrddata']) {
295
									foreach($config['rrddata']['rrddatafile'] as $rrd) {
296
										$rrd_fd = fopen("{$g['vardb_path']}/rrd/{$rrd['filename']}", "w");
297
										fwrite($rrd_fd, base64_decode($rrd['data']));
298
										fclose($rrd_fd);
299
									}
300
									unset($config['rrddata']);
301
									unlink_if_exists("{$g['tmp_path']}/config.cache");
302
									write_config();
303
									add_base_packages_menu_items();
304
									convert_config();
305
									conf_mount_ro();
306
								}
307
								if($m0n0wall_upgrade == true) {
308
									if($config['system']['gateway'] <> "")
309
										$config['interfaces']['wan']['gateway'] = $config['system']['gateway'];
310
									unset($config['shaper']);
311
									/* optional if list */
312
									$ifdescrs = get_configured_interface_list(true, true);
313
									/* remove special characters from interface descriptions */
314
									if(is_array($ifdescrs))
315
										foreach($ifdescrs as $iface)
316
											$config['interfaces'][$iface]['descr'] = remove_bad_chars($config['interfaces'][$iface]['descr']);
317
									unlink_if_exists("{$g['tmp_path']}/config.cache");
318
									// Reset configuration version to something low
319
									// in order to force the config upgrade code to 
320
									// run through with all steps that are required.
321
									$config['system']['version'] = "1.0";
322
									// Deal with descriptions longer than 63 characters
323
									for ($i = 0; isset($config["filter"]["rule"][$i]); $i++) {
324
										if(count($config['filter']['rule'][$i]['descr']) > 63)
325
											$config['filter']['rule'][$i]['descr'] = substr($config['filter']['rule'][$i]['descr'], 0, 63);
326
									}
327
									// Move interface from ipsec to enc0
328
									for ($i = 0; isset($config["filter"]["rule"][$i]); $i++) {
329
										if($config['filter']['rule'][$i]['interface'] == "ipsec")
330
											$config['filter']['rule'][$i]['interface'] = "enc0";
331
									}
332
									// Convert icmp types
333
									// http://www.openbsd.org/cgi-bin/man.cgi?query=icmp&sektion=4&arch=i386&apropos=0&manpath=OpenBSD+Current
334
									for ($i = 0; isset($config["filter"]["rule"][$i]); $i++) {
335
										if($config["filter"]["rule"][$i]['icmptype']) {
336
											switch($config["filter"]["rule"][$i]['icmptype']) {
337
												case "echo":
338
													$config["filter"]["rule"][$i]['icmptype'] = "echoreq";
339
													break;
340
					                            case "unreach":
341
													$config["filter"]["rule"][$i]['icmptype'] = "unreach";
342
													break;
343
					                            case "echorep":
344
													$config["filter"]["rule"][$i]['icmptype'] = "echorep";
345
													break;
346
					                            case "squench":
347
													$config["filter"]["rule"][$i]['icmptype'] = "squench";
348
													break;
349
					                            case "redir":
350
													$config["filter"]["rule"][$i]['icmptype'] = "redir";
351
													break;
352
					                            case "timex":
353
													$config["filter"]["rule"][$i]['icmptype'] = "timex";
354
													break;
355
					                            case "paramprob":
356
													$config["filter"]["rule"][$i]['icmptype'] = "paramprob";
357
													break;
358
					                            case "timest":
359
													$config["filter"]["rule"][$i]['icmptype'] = "timereq";
360
													break;
361
					                            case "timestrep":
362
													$config["filter"]["rule"][$i]['icmptype'] = "timerep";
363
													break;
364
					                            case "inforeq":
365
													$config["filter"]["rule"][$i]['icmptype'] = "inforeq";
366
													break;
367
					                            case "inforep":
368
													$config["filter"]["rule"][$i]['icmptype'] = "inforep";
369
													break;
370
					                            case "maskreq":
371
													$config["filter"]["rule"][$i]['icmptype'] = "maskreq";
372
													break;
373
					                            case "maskrep":
374
													$config["filter"]["rule"][$i]['icmptype'] = "maskrep";
375
													break;
376
											}
377
										}
378
									}									
379
									write_config();
380
									add_base_packages_menu_items();									
381
									convert_config();
382
									conf_mount_ro();
383
									$savemsg = "The m0n0wall configuration has been restored and upgraded to pfSense. You need to reboot your firewall.";
384
									mark_subsystem_dirty("restore");
385
								}
386
								if(isset($config['captiveportal']['enable'])) {
387
									/* for some reason ipfw doesn't init correctly except on bootup sequence */
388
									$savemsg = "The configuration has been restored. You need to reboot your firewall.";
389
									mark_subsystem_dirty("restore");
390
								}
391
								setup_serial_port();
392
								if(is_interface_mismatch() == true) {
393
									touch("/var/run/interface_mismatch_reboot_needed");
394
									clear_subsystem_dirty("restore");
395
									convert_config();
396
									header("Location: interfaces_assign.php");
397
									exit;
398
								}
399
							} else {
400
								$input_errors[] = "The configuration could not be restored.";
401
							}
402
						}
403
					}
404
				} else {
405
					$input_errors[] = "The configuration could not be restored (file upload error).";
406
				}
407
			}
408
		}
409

    
410
		if ($mode == "reinstallpackages") {
411

    
412
			header("Location: pkg_mgr_install.php?mode=reinstallall");
413
			exit;
414
                } else if ($mode == "restore_ver") {
415
			$input_errors[] = "XXX - this feature may hose your config (do NOT backrev configs!) - billm";
416
			if ($ver2restore <> "") {
417
				$conf_file = "{$g['cf_conf_path']}/bak/config-" . strtotime($ver2restore) . ".xml";
418
                                if (config_install($conf_file) == 0) {
419
					mark_subsystem_dirty("restore");
420
					$savemsg = "The configuration has been restored. You need to reboot your firewall.";
421
                                } else {
422
                                	$input_errors[] = "The configuration could not be restored.";
423
                                }
424
                        } else {
425
                                $input_errors[] = "No version selected.";
426
                        }
427
		}
428
	}
429
}
430

    
431
$id = rand() . '.' . time();
432

    
433
$mth = ini_get('upload_progress_meter.store_method');
434
$dir = ini_get('upload_progress_meter.file.filename_template');
435

    
436
$pgtitle = array("Diagnostics","Backup/restore");
437
include("head.inc");
438

    
439
?>
440

    
441
<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
442
<?php include("fbegin.inc"); ?>
443
<script language="JavaScript">
444
<!--
445

    
446
function encrypt_change() {
447

    
448
	if (!document.iform.encrypt.checked)
449
		document.getElementById("encrypt_opts").style.display="none";
450
	else
451
		document.getElementById("encrypt_opts").style.display="";
452
}
453

    
454
function decrypt_change() {
455

    
456
	if (!document.iform.decrypt.checked)
457
		document.getElementById("decrypt_opts").style.display="none";
458
	else
459
		document.getElementById("decrypt_opts").style.display="";
460
}
461

    
462
//-->
463
</script>
464
<form action="diag_backup.php" method="post" name="iform" enctype="multipart/form-data">
465
<?php if ($input_errors) print_input_errors($input_errors); ?>
466
<?php if ($savemsg) print_info_box($savemsg); ?>
467
<?php if (is_subsystem_dirty('restore')): ?><p>
468
<?php print_info_box_np("The firewall configuration has been changed.<br>You must apply the new config by restarting the firewall in order for changes to take effect.", "apply", "Reboot firewall");?><br>
469
<?php endif; ?>
470
<table width="100%" border="0" cellspacing="0" cellpadding="0">
471
	<tr>
472
		<td>
473
<?php
474
		$tab_array = array();
475
		$tab_array[0] = array("Config History", false, "diag_confbak.php");
476
		$tab_array[1] = array("Backup/Restore", true, "diag_backup.php");
477
		display_top_tabs($tab_array);
478
?>
479
		</td>
480
	</tr>
481
	<tr>
482
		<td>
483
			<div id="mainarea">
484
			<table class="tabcont" align="center" width="100%" border="0" cellpadding="6" cellspacing="0">
485
				<tr>
486
					<td colspan="2" class="listtopic">Backup configuration</td>
487
				</tr>
488
				<tr>
489
					<td width="22%" valign="baseline" class="vncell">&nbsp;</td>
490
					<td width="78%" class="vtable">
491
						<p>Click this button to download the system configuration in XML format.<br /><br /> Backup area: <?php spit_out_select_items("backuparea", false); ?></p>
492
						<table>
493
							<tr>
494
								<td>
495
									<input name="nopackages" type="checkbox" class="formcheckbox" id="nopackages">
496
								</td>
497
								<td>
498
									<span class="vexpl">Do not backup package information.</span>
499
								</td>
500
							</tr>
501
						</table>
502
						<table>
503
							<tr>
504
								<td>
505
									<input name="encrypt" type="checkbox" class="formcheckbox" id="nopackages" onClick="encrypt_change()">
506
								</td>
507
								<td>
508
									<span class="vexpl">Encrypt this configuration file.</span>
509
								</td>
510
							</tr>
511
							<tr>
512
								<td>
513
									<input name="donotbackuprrd" type="checkbox" class="formcheckbox" id="dotnotbackuprrd">
514
								</td>
515
								<td>
516
									<span class="vexpl">Do not backup RRD data (NOTE: RRD Data can consume 4+ megabytes of config.xml space!)</span>
517
								</td>
518
							</tr>
519
						</table>
520
						<table id="encrypt_opts">
521
							<tr>
522
								<td>
523
									<span class="vexpl">Password :</span>
524
								</td>
525
								<td>
526
									<input name="encrypt_password" type="password" class="formfld pwd" size="20" value="" />
527
								</td>
528
							</tr>
529
							<tr>
530
								<td>
531
									<span class="vexpl">confirm :</span>
532
								</td>
533
								<td>
534
									<input name="encrypt_passconf" type="password" class="formfld pwd" size="20" value="" />
535
								</td>
536
							</tr>
537
						</table>
538
						<p><input name="Submit" type="submit" class="formbtn" id="download" value="Download configuration"></p>
539
					</td>
540
				</tr>
541
				<tr>
542
					<td colspan="2" class="list" height="12">&nbsp;</td>
543
                </tr>
544
                <tr>
545
					<td colspan="2" class="listtopic">Restore configuration</td>
546
				</tr>
547
				<tr>
548
					<td width="22%" valign="baseline" class="vncell">&nbsp;</td>
549
					<td width="78%" class="vtable">
550
						Open a <?=$g['[product_name']?> configuration XML file and click the button below to restore the configuration. <br /><br /> Restore area: <?php spit_out_select_items("restorearea", true); ?>
551
						<p><input name="conffile" type="file" class="formfld unknown" id="conffile" size="40"></p>
552
						<table>
553
							<tr>
554
								<td>
555
									<input name="decrypt" type="checkbox" class="formcheckbox" id="nopackages" onClick="decrypt_change()">
556
								</td>
557
								<td>
558
									<span class="vexpl">Configuration file is encrypted.</span>
559
								</td>
560
							</tr>
561
						</table>
562
						<table id="decrypt_opts">
563
							<tr>
564
								<td>
565
									<span class="vexpl">Password :</span>
566
								</td>
567
								<td>
568
									<input name="decrypt_password" type="password" class="formfld pwd" size="20" value="" />
569
								</td>
570
							</tr>
571
							<tr>
572
								<td>
573
									<span class="vexpl">confirm :</span>
574
								</td>
575
								<td>
576
									<input name="decrypt_passconf" type="password" class="formfld pwd" size="20" value="" />
577
								</td>
578
							</tr>
579
						</table>
580
						<p><input name="Submit" type="submit" class="formbtn" id="restore" value="Restore configuration"></p>
581
                      	<p><strong><span class="red">Note:</span></strong><br />The firewall may need a reboot after restoring the configuration.<br /></p>
582
					</td>
583
				</tr>
584
				<?php if($config['installedpackages']['package'] != "") { ?>
585
				<tr>
586
					<td colspan="2" class="list" height="12">&nbsp;</td>
587
				</tr>
588
				<tr>
589
					<td colspan="2" class="listtopic">Reinstall packages</td>
590
				</tr>
591
				<tr>
592
					<td width="22%" valign="baseline" class="vncell">&nbsp;</td>
593
					<td width="78%" class="vtable">
594
						<p>Click this button to reinstall all system packages.  This may take a while. <br /><br />
595
		  				<input name="Submit" type="submit" class="formbtn" id="reinstallpackages" value="Reinstall packages">
596
					</td>
597
				</tr>
598
				<?php } ?>
599
			</table>
600
			</div>
601
		</td>
602
	</tr>
603
</table>
604
</form>
605

    
606
<script language="JavaScript">
607
<!--
608
encrypt_change();
609
decrypt_change();
610
//-->
611
</script>
612

    
613
<?php include("fend.inc"); ?>
614
</body>
615
</html>
(4-4/217)