Project

General

Profile

Download (38.6 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/*
3
	installer.php (pfSense webInstaller)
4
	part of pfSense (https://www.pfsense.org/)
5
        Copyright (C) 2013-2015 Electric Sheep Fencing, LP
6
	Copyright (C) 2010 Scott Ullrich <sullrich@gmail.com>
7
	All rights reserved.
8

    
9
	Redistribution and use in source and binary forms, with or without
10
	modification, are permitted provided that the following conditions are met:
11

    
12
	1. Redistributions of source code must retain the above copyright notice,
13
	   this list of conditions and the following disclaimer.
14

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

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

    
31
$nocsrf = true;
32

    
33
require("globals.inc");
34
require("guiconfig.inc");
35

    
36
define('PC_SYSINSTALL', '/usr/sbin/pc-sysinstall/pc-sysinstall/pc-sysinstall.sh');
37

    
38
if($g['platform'] == "pfSense" or $g['platform'] == "nanobsd") {
39
	header("Location: /");
40
	exit;
41
}
42

    
43
// Main switch dispatcher
44
switch ($_REQUEST['state']) {
45
	case "update_installer_status":
46
		update_installer_status();
47
		exit;
48
	case "custominstall":
49
		installer_custom();
50
		exit;
51
	case "begin_install":
52
		installing_gui();
53
		begin_install();
54
		exit;
55
	case "verify_before_install":
56
		verify_before_install();
57
		exit;
58
	case "easy_install_ufs":
59
		easy_install("UFS+S");
60
		exit;
61
	case "easy_install_ufs":
62
		easy_install("ZFS");
63
		exit;
64

    
65
	default:
66
		installer_main();	
67
}
68

    
69
function easy_install($fstype = "UFS+S") {
70
	// Calculate swap and disk sizes
71
	$disks = installer_find_all_disks();
72
	$memory = get_memory();
73
	$swap_size = $memory[0] * 2;
74
	$first_disk = trim(installer_find_first_disk());
75
	$disk_info = pcsysinstall_get_disk_info($first_disk);
76
	$size = $disk_info['size'];
77
	$first_disk_size = $size - $swap_size;
78
	$disk_setup = array();
79
	$tmp_array = array();
80
	// Build the disk layout for /
81
	$tmp_array['disk'] = $first_disk;
82
	$tmp_array['size'] = $first_disk_size;
83
	$tmp_array['mountpoint'] = "/";
84
	$tmp_array['fstype'] = $fstype;
85
	$disk_setup[] = $tmp_array;
86
	unset($tmp_array);
87
	$tmp_array = array();
88
	// Build the disk layout for SWAP
89
	$tmp_array['disk'] = $first_disk;
90
	$tmp_array['size'] = $swap_size;
91
	$tmp_array['mountpoint'] = "none";
92
	$tmp_array['fstype'] = "SWAP";
93
	$disk_setup[] = $tmp_array;
94
	unset($tmp_array);
95
	$bootmanager = "bsd";
96
	file_put_contents("/tmp/webInstaller_disk_layout.txt", serialize($disk_setup));
97
	file_put_contents("/tmp/webInstaller_disk_bootmanager.txt", serialize($bootmanager));
98
	header("Location: installer.php?state=verify_before_install");
99
	exit;
100
}
101

    
102
function write_out_pc_sysinstaller_config($disks, $bootmanager = "bsd") {
103
	$diskareas = "";
104
	$fd = fopen("/usr/sbin/pc-sysinstall/examples/pfSense-install.cfg", "w");
105
	if(!$fd) 
106
		return true;
107
	if($bootmanager == "") 
108
	 	$bootmanager = "none";
109
	// Yes, -1.  We ++ early in loop.
110
	$numdisks = -1;
111
	$lastdisk = "";
112
	$diskdefs = "";
113
	// Run through the disks and create the conf areas for pc-sysinstaller
114
	foreach($disks as $disksa) {
115
		$fstype = $disksa['fstype'];
116
		$size = $disksa['size'];
117
		$mountpoint = $disksa['mountpoint'];
118
		$disk = $disksa['disk'];
119
		if($disk <> $lastdisk) {
120
			$lastdisk = $disk;
121
			$numdisks++;
122
			$diskdefs .= "# disk {$disk}\n";
123
			$diskdefs .= "disk{$numdisks}={$disk}\n";
124
			$diskdefs .= "partition=all\n";
125
			$diskdefs .= "bootManager={$bootmanager}\n";
126
			$diskdefs .= "commitDiskPart\n\n";
127
		}
128
		$diskareas .= "disk{$numdisks}-part={$fstype} {$size} {$mountpoint} \n";
129
		if($encpass)
130
			$diskareas .= "encpass={$encpass}\n";
131
	}
132
	
133
	$config = <<<EOF
134
# Sample configuration file for an installation using pc-sysinstall
135
# This file was automatically generated by installer.php
136
 
137
installMode=fresh
138
installInteractive=yes
139
installType=FreeBSD
140
installMedium=LiveCD
141

    
142
# Set the disk parameters
143
{$diskdefs}
144

    
145
# Setup the disk label
146
# All sizes are expressed in MB
147
# Avail FS Types, UFS, UFS+S, UFS+J, ZFS, SWAP
148
# Size 0 means use the rest of the slice size
149
# Alternatively, you can append .eli to any of
150
# the above filesystem types to encrypt that disk.
151
# If you with to use a passphrase with this 
152
# encrypted partition, on the next line 
153
# the flag "encpass=" should be entered:
154
# encpass=mypass
155
# disk0-part=UFS 500 /boot
156
# disk0-part=UFS.eli 500 /
157
# disk0-part=UFS.eli 500 /usr
158
{$diskareas}
159

    
160
# Do it now!
161
commitDiskLabel
162

    
163
# Set if we are installing via optical, USB, or FTP
164
installType=FreeBSD
165

    
166
packageType=cpdup
167

    
168
# Optional Components
169
cpdupPaths=boot,COPYRIGHT,bin,conf,conf.default,dev,etc,home,kernels,libexec,lib,root,sbin,usr,var
170

    
171
# runExtCommand=chmod a+rx /usr/local/bin/after_installation_routines.sh ; cd / ; /usr/local/bin/after_installation_routines.sh
172
EOF;
173
	fwrite($fd, $config);
174
	fclose($fd);
175
	return;
176
}
177

    
178
function start_installation() {
179
	global $g, $fstype, $savemsg;
180
	if(file_exists("/tmp/install_complete"))
181
		return;
182
	$ps_running = exec("/bin/ps awwwux | /usr/bin/grep -v grep | /usr/bin/grep 'sh /tmp/installer.sh'");
183
	if($ps_running)	
184
		return;
185
	$fd = fopen("/tmp/installer.sh", "w");
186
	if(!$fd) {
187
		die(gettext("Could not open /tmp/installer.sh for writing"));
188
		exit;
189
	}
190
	fwrite($fd, "/bin/rm /tmp/.pc-sysinstall/pc-sysinstall.log 2>/dev/null\n");
191
	fwrite($fd, "/usr/sbin/pc-sysinstall/pc-sysinstall/pc-sysinstall.sh -c /usr/sbin/pc-sysinstall/examples/pfSense-install.cfg \n");
192
	fwrite($fd, "/bin/chmod a+rx /usr/local/bin/after_installation_routines.sh\n");
193
	fwrite($fd, "cd / && /usr/local/bin/after_installation_routines.sh\n");
194
	fwrite($fd, "/bin/mkdir /mnt/tmp\n");
195
	fwrite($fd, "/usr/bin/touch /tmp/install_complete\n");
196
	fclose($fd);
197
	exec("/bin/chmod a+rx /tmp/installer.sh");
198
	mwexec_bg("/bin/sh /tmp/installer.sh");
199
}
200

    
201
function installer_find_first_disk() {
202
	global $g, $fstype, $savemsg;
203
	$disk = `/usr/sbin/pc-sysinstall/pc-sysinstall/pc-sysinstall.sh disk-list | head -n1 | cut -d':' -f1`;
204
	return trim($disk);
205
}
206

    
207
function pcsysinstall_get_disk_info($diskname) {
208
	global $g, $fstype, $savemsg;
209
	$disk = explode("\n", `/usr/sbin/pc-sysinstall/pc-sysinstall/pc-sysinstall.sh disk-list`);
210
	$disks_array = array();
211
	foreach($disk as $d) {
212
		$disks_info = explode(":", $d);
213
		$tmp_array = array();
214
		if($disks_info[0] == $diskname) {
215
			$disk_info = explode("\n", `/usr/sbin/pc-sysinstall/pc-sysinstall/pc-sysinstall.sh disk-info {$disks_info[0]}`);
216
			$disk_info_split = explode("=", $disk_info);
217
			foreach($disk_info as $di) { 
218
				$di_s = explode("=", $di);
219
				if($di_s[0])
220
					$tmp_array[$di_s[0]] = $di_s[1];
221
			}
222
			$tmp_array['size']--;
223
			$tmp_array['disk'] = trim($disks_info[0]);
224
			$tmp_array['desc'] = trim(htmlentities($disks_info[1]));
225
			return $tmp_array;
226
		}
227
	}
228
}
229

    
230
// Return an array with all disks information.
231
function installer_find_all_disks() {
232
	global $g, $fstype, $savemsg;
233
	$disk = explode("\n", `/usr/sbin/pc-sysinstall/pc-sysinstall/pc-sysinstall.sh disk-list`);
234
	$disks_array = array();
235
	foreach($disk as $d) {
236
		if(!$d) 
237
			continue;
238
		$disks_info = explode(":", $d);
239
		$tmp_array = array();
240
		$disk_info = explode("\n", `/usr/sbin/pc-sysinstall/pc-sysinstall/pc-sysinstall.sh disk-info {$disks_info[0]}`);
241
		foreach($disk_info as $di) { 
242
			$di_s = explode("=", $di);
243
			if($di_s[0])
244
				$tmp_array[$di_s[0]] = $di_s[1];
245
		}
246
		$tmp_array['size']--;
247
		$tmp_array['disk'] = trim($disks_info[0]);
248
		$tmp_array['desc'] = trim(htmlentities($disks_info[1]));
249
		$disks_array[] = $tmp_array;
250
	}
251
	return $disks_array;
252
}
253

    
254
function update_installer_status() {
255
	global $g, $fstype, $savemsg;
256
	// Ensure status files exist
257
	if(!file_exists("/tmp/installer_installer_running"))
258
		touch("/tmp/installer_installer_running");
259
	$status = `cat /tmp/.pc-sysinstall/pc-sysinstall.log`;
260
	$status = str_replace("\n", "\\n", $status);
261
	$status = str_replace("\n", "\\r", $status);
262
	$status = str_replace("'", "\\'", $status);
263
	echo "document.forms[0].installeroutput.value='$status';\n";
264
	echo "document.forms[0].installeroutput.scrollTop = document.forms[0].installeroutput.scrollHeight;\n";	
265
	// Find out installer progress
266
	$progress = "5";
267
	if(strstr($status, "Running: dd")) 
268
		$progress = "6";
269
	if(strstr($status, "Running: gpart create -s GPT")) 
270
		$progress = "7";
271
	if(strstr($status, "Running: gpart bootcode")) 
272
		$progress = "7";
273
	if(strstr($status, "Running: newfs -U")) 
274
		$progress = "8";
275
	if(strstr($status, "Running: sync")) 
276
		$progress = "9";
277
	if(strstr($status, "/boot /mnt/boot")) 
278
		$progress = "10";
279
	if(strstr($status, "/COPYRIGHT /mnt/COPYRIGHT"))
280
		$progress = "11";
281
	if(strstr($status, "/bin /mnt/bin"))
282
		$progress = "12";
283
	if(strstr($status, "/conf /mnt/conf"))
284
		$progress = "15";
285
	if(strstr($status, "/conf.default /mnt/conf.default"))
286
		$progress = "20";
287
	if(strstr($status, "/dev /mnt/dev"))
288
		$progress = "25";
289
	if(strstr($status, "/etc /mnt/etc"))
290
		$progress = "30";
291
	if(strstr($status, "/home /mnt/home"))
292
		$progress = "35";
293
	if(strstr($status, "/kernels /mnt/kernels"))
294
		$progress = "40";
295
	if(strstr($status, "/libexec /mnt/libexec"))
296
		$progress = "50";
297
	if(strstr($status, "/lib /mnt/lib"))
298
		$progress = "60";
299
	if(strstr($status, "/root /mnt/root"))
300
		$progress = "70";
301
	if(strstr($status, "/sbin /mnt/sbin"))
302
		$progress = "75";
303
	if(strstr($status, "/sys /mnt/sys"))
304
		$progress = "80";
305
	if(strstr($status, "/usr /mnt/usr"))
306
		$progress = "95";
307
	if(strstr($status, "/usr /mnt/usr"))
308
		$progress = "90";
309
	if(strstr($status, "/var /mnt/var"))
310
		$progress = "95";
311
	if(strstr($status, "cap_mkdb /etc/login.conf"))
312
		$progress = "96";
313
	if(strstr($status, "Setting hostname"))
314
		$progress = "97";
315
	if(strstr($status, "umount -f /mnt"))
316
		$progress = "98";
317
	if(strstr($status, "umount -f /mnt"))
318
		$progress = "99";
319
	if(strstr($status, "Installation finished"))
320
		$progress = "100";
321
	// Check for error and bail if we see one.
322
	if(stristr($status, "error")) {
323
		$error = true;
324
		echo "\$('#installerrunning').html('<img class=\"infoboxnpimg\" src=\"/themes/{$g['theme']}/images/icons/icon_exclam.gif\"> <font size=\"2\"><b>An error occurred.  Aborting installation.  <a href=\"/installer\">Back</a> to webInstaller'); ";
325
		echo "\$('#progressbar').css('width','100%');\n";
326
		unlink_if_exists("/tmp/install_complete");
327
		return;
328
	}
329
	$running_old = trim(file_get_contents("/tmp/installer_installer_running"));
330
	if($installer_running <> "running") {
331
		$ps_running = exec("/bin/ps awwwux | /usr/bin/grep -v grep | /usr/bin/grep 'sh /tmp/installer.sh'");
332
		if($ps_running)	{
333
			$running = "\$('#installerrunning').html('<table><tr><td valign=\"middle\"><img src=\"/themes/{$g['theme']}/images/misc/loader.gif\"></td><td valign=\"middle\">&nbsp;<font size=\"2\"><b>Installer running ({$progress}% completed)...</td></tr></table>'); ";
334
			if($running_old <> $running) {
335
				echo $running;
336
				file_put_contents("/tmp/installer_installer_running", "$running");			
337
			}
338
		}
339
	}
340
	if($progress) 
341
		echo "\$('#progressbar').css('width','{$progress}%');\n";
342
	if(file_exists("/tmp/install_complete")) {
343
		echo "\$('#installerrunning').html('<img class=\"infoboxnpimg\" src=\"/themes/{$g['theme']}/images/icons/icon_exclam.gif\"> <font size=\"+1\">Installation completed.  Please <a href=\"/reboot.php\">reboot</a> to continue');\n";
344
		echo "\$('#pbdiv').fadeOut();\n";
345
		unlink_if_exists("/tmp/installer.sh");
346
		file_put_contents("/tmp/installer_installer_running", "finished");
347
	}
348
}
349

    
350
function update_installer_status_win($status) {
351
	global $g, $fstype, $savemsg;
352
	echo "<script type=\"text/javascript\">\n";
353
	echo "	\$('#installeroutput').val('" . str_replace(htmlentities($status), "\n", "") . "');\n";
354
	echo "</script>\n";
355
}
356

    
357
function begin_install() {
358
	global $g, $savemsg;
359
	if(file_exists("/tmp/install_complete"))
360
		return;
361
	unlink_if_exists("/tmp/install_complete");
362
	update_installer_status_win(sprintf(gettext("Beginning installation on disk %s."),$disk));
363
	start_installation();
364
}
365

    
366
function head_html() {
367
	global $g, $fstype, $savemsg;
368
	echo <<<EOF
369
<html>
370
	<head>
371
		<style type='text/css'>
372
			hr {
373
				border: 0;
374
				color: #000000;
375
				background-color: #000000;
376
				height: 1px;
377
				width: 100%;
378
				text-align: left;
379
			}
380
			a:link { 
381
				color: #000000;
382
				text-decoration:underline;
383
				font-size:14;
384
			}
385
			a:visited { 
386
				color: #000000;
387
				text-decoration:underline;
388
				font-size:14;
389
			}
390
			a:hover { 
391
				color: #FFFF00;
392
				text-decoration: none;
393
				font-size:14;
394
			}
395
			a:active { 
396
				color: #FFFF00;
397
				text-decoration:underline;
398
				font-size:14;
399
			}
400
		</style>
401
	</head>
402
EOF;
403

    
404
}
405

    
406
function body_html() {
407
	global $g, $fstype, $savemsg;
408
	$pgtitle = array("{$g['product_name']}", gettext("Installer"));
409
	include("head.inc");
410
	echo <<<EOF
411
	<body link="#0000CC" vlink="#0000CC" alink="#0000CC">
412
	<script type="text/javascript" src="/javascript/jquery-1.11.1.min.js"></script>
413
	<script type="text/javascript" src="/javascript/jquery-migrate-1.2.1.min.js"></script>
414
	<script type="text/javascript" src="/javascript/jquery/jquery-ui-1.11.1.min.js"></script>
415
	<script type="text/javascript">
416
		function getinstallerprogress() {
417
			url = '/installer/installer.php';
418
			pars = 'state=update_installer_status';
419
			callajax(url, pars, installcallback);
420
		}
421
		function callajax(url, pars, activitycallback) {
422
			jQuery.ajax(
423
				url,
424
				{
425
					type: 'post',
426
					data: pars,
427
					complete: activitycallback
428
				});
429
		}
430
		function installcallback(transport) {
431
			setTimeout('getinstallerprogress()', 2000);
432
			eval(transport.responseText);
433
		}
434
	</script>
435
EOF;
436

    
437
	if($one_two)
438
		echo "<p class=\"pgtitle\">{$pgtitle}</font></p>";
439

    
440
	if ($savemsg) print_info_box($savemsg); 
441
}
442

    
443
function end_html() {
444
	global $g, $fstype, $savemsg;
445
	echo "</form>";
446
	echo "</body>";
447
	echo "</html>";
448
}
449

    
450
function template() {
451
	global $g, $fstype, $savemsg;
452
	head_html();
453
	body_html();
454
	echo <<<EOF
455
	<div id="mainlevel">
456
		<table width="100%" border="0" cellpadding="0" cellspacing="0">
457
	 		<tr>
458
	    		<td>
459
					<div id="mainarea">
460
						<table class="tabcont" width="100%" border="0" cellpadding="0" cellspacing="0">
461
							<tr>
462
	     						<td class="tabcont" >
463
	      							<form action="installer.php" method="post">
464
									<div id="pfsensetemplate">
465

    
466

    
467
									</div>
468
	     						</td>
469
							</tr>
470
						</table>
471
					</div>
472
				</td>
473
			</tr>
474
		</table>
475
	</div>
476
EOF;
477
	end_html();
478
}
479

    
480
function verify_before_install() {
481
	global $g, $fstype, $savemsg;
482
	$encrypted_root = false;
483
	$non_encrypted_boot = false;
484
	$non_encrypted_notice = false;
485
	head_html();
486
	body_html();
487
	page_table_start($g['product_name'] . " installer - Verify final installation settings");
488
	// If we are visiting this step from anything but the row editor / custom install
489
	// then load the on disk layout contents if they are available.
490
	if(!$_REQUEST['fstype0'] && file_exists("/tmp/webInstaller_disk_layout.txt")) {
491
		$disks = unserialize(file_get_contents("/tmp/webInstaller_disk_layout.txt"));
492
		$bootmanager = unserialize(file_get_contents("/tmp/webInstaller_disk_bootmanager.txt"));
493
		$restored_layout_from_file = true;
494
		$restored_layout_txt = "The previous disk layout was restored from disk";
495
	} else {
496
		$disks = array();
497
	}
498
	if(!$bootmanager) 
499
		$bootmanager = $_REQUEST['bootmanager'];
500
	// echo "\n<!--" . print_r($_REQUEST, true) . " -->\n";
501
	$disk = pcsysinstall_get_disk_info(htmlspecialchars($_REQUEST['disk']));
502
	$disksize = format_bytes($disk['size'] * 1048576);
503
	// Loop through posted items and create an array
504
	for($x=0; $x<99; $x++) { // XXX: Make this more optimal
505
		if(!$_REQUEST['fstype' . $x])
506
			continue;
507
		$tmparray = array();
508
		if($_REQUEST['fstype' . $x] <> "SWAP") {
509
			$tmparray['mountpoint'] = $_REQUEST['mountpoint' . $x];
510
			// Check for encrypted slice /
511
			if(stristr($_REQUEST['fstype' . $x], ".eli")) {
512
				if($tmparray['mountpoint'] == "/") 
513
					$encrypted_root = true;
514
			}
515
			// Check if we have a non-encrypted /boot
516
			if($tmparray['mountpoint'] == "/boot") 	{
517
				if(!stristr($_REQUEST['fstype' . $x], ".eli"))
518
					$non_encrypted_boot = true;
519
			}
520
			if($tmparray['mountpoint'] == "/conf") {	
521
				$tmparray['mountpoint'] = "/conf{$x}";
522
				$error_txt[] = "/conf is not an allowed mount point and has been renamed to /conf{$x}.";
523
			}
524
		} else  {
525
			$tmparray['mountpoint'] = "none";
526
		}
527
		// If we have an encrypted /root and lack a non encrypted /boot, throw an error/warning
528
		if($encrypted_root && !$non_encrypted_boot && !$non_encrypted_notice) {
529
			$error_txt[] = "A non-encrypted /boot slice is required when encrypting the / slice";
530
			$non_encrypted_notice = true;
531
		}
532
		$tmparray['disk'] = $_REQUEST['disk' . $x];
533
		$tmparray['fstype'] = $_REQUEST['fstype' . $x];
534
		$tmparray['size'] = $_REQUEST['size' . $x];
535
		$tmparray['encpass'] = $_REQUEST['encpass' . $x];
536
		$disks[] = $tmparray;
537
	}
538
	// echo "\n<!-- " . print_r($disks, true) . " --> \n";
539
	$bootmanagerupper = strtoupper($bootmanager);
540
	echo <<<EOFAMBAC
541
	<form method="post" action="installer.php">
542
	<input type="hidden" name="fstype" value="{$fstype_echo}">
543
	<input type="hidden" name="disk" value="{$disk_echo}">
544
	<input type="hidden" name="state" value="begin_install">
545
	<input type="hidden" name="swapsize" value="{$swapsize}">
546
	<input type="hidden" name="encpass" value="{$encpass}">
547
	<input type="hidden" name="bootmanager" value="{$bootmanager}">
548
	<div id="mainlevel">
549
		<table width="800" border="0" cellpadding="0" cellspacing="0">
550
	 		<tr>
551
	    		<td>
552
					<div id="mainarea">
553
						<table width="100%" border="0" cellpadding="0" cellspacing="0">
554
							<tr>
555
	     						<td >
556
									<div>
557
										<center>
558
											<div id="pfsensetemplate">
559
												<table width='100%'>
560
EOFAMBAC;
561
												// If errors are found, throw the big red box.
562
												if ($error_txt) {
563
													echo "<tr><td colspan=\"5\">&nbsp;</td>";
564
													echo "<tr><td colspan=\"5\">";
565
													print_input_errors($error_txt);
566
													echo "</td></tr>";
567
												} else 
568
													echo "<tr><td>&nbsp;</td></tr>";
569

    
570
	echo <<<EOFAMBACBAF
571

    
572
												<tr><td colspan='5' align="center"><b>Boot manager: {$bootmanagerupper}</td></tr>
573
												<tr><td>&nbsp;</td></tr>
574
												<tr>
575
													<td align='left'>
576
														<b>Mount point</b>
577
													</td>
578
													<td align='left'>
579
														<b>Filesysytem type</b>
580
													</td>
581
													<td align='left'>
582
														<b>Disk</b>
583
													</td>
584
													<td align='left'>
585
														<b>Size</b>
586
													</td>
587
													<td align='left'>
588
														<b>Encryption password</b>
589
													</td>
590
												</tr>
591
												<tr><td colspan='5'><hr></td></tr>
592

    
593
EOFAMBACBAF;
594

    
595
													foreach($disks as $disk) {
596
														$desc = pcsysinstall_get_disk_info($disk['disk']);
597
														echo "<tr>";
598
														echo "<td>&nbsp;&nbsp;&nbsp;" . htmlspecialchars($disk['mountpoint']) . "</td>";
599
														echo "<td>" . htmlspecialchars($disk['fstype']) . "</td>";
600
														echo "<td>" . htmlspecialchars($disk['disk']) . " " . htmlspecialchars($desc['desc']) . "</td>";
601
														echo "<td>" . htmlspecialchars($disk['size']) . "</td>";
602
														echo "<td>" . htmlspecialchars($disk['encpass']) . "</td>";
603
														echo "</tr>";
604
													}
605

    
606
echo <<<EOFAMB
607
												<tr><td colspan="5"><hr></td></tr>
608
												</table>
609
											</div>
610
										</center>
611
									</div>
612
	     						</td>
613
							</tr>
614
						</table>
615
					</div>
616
					<center>
617
						<p/>
618
						<input type="button" value="Cancel" onClick="javascript:document.location='installer.php?state=custominstall';"> &nbsp;&nbsp;
619
EOFAMB;
620
						if(!$error_txt) 
621
						echo "<input type=\"submit\" value=\"Begin installation\"> <br />&nbsp;";
622
echo <<<EOFAMBASDF
623

    
624
					</center>
625
				</td>
626
			</tr>
627
		</table>
628
	</div>
629
EOFAMBASDF;
630

    
631

    
632
	page_table_end();
633
	end_html();
634
	write_out_pc_sysinstaller_config($disks, $bootmanager);
635
	// Serialize layout to disk so it can be read in later.
636
	file_put_contents("/tmp/webInstaller_disk_layout.txt", serialize($disks));
637
	file_put_contents("/tmp/webInstaller_disk_bootmanager.txt", serialize($bootmanager));
638
}
639

    
640
function installing_gui() {
641
	global $g, $fstype, $savemsg;
642
	head_html();
643
	body_html();
644
	echo "<form action=\"installer.php\" method=\"post\" state=\"step1_post\">";
645
	page_table_start();
646
	echo <<<EOF
647
	<center>
648
		<table width="100%">
649
		<tr><td>
650
			<div id="mainlevel">
651
				<table width="100%" border="0" cellpadding="0" cellspacing="0">
652
			 		<tr>
653
			    		<td>
654
							<div id="mainarea">
655
								<table width="100%" border="0" cellpadding="0" cellspacing="0">
656
									<tr>
657
			     						<td>
658
											<div id="pfsenseinstaller" width="100%">
659
												<div id='installerrunning' width='100%' style="padding:8px; border:1px dashed #000000">
660
													<table>
661
														<tr>
662
															<td valign="middle">
663
																<img src="/themes/{$g['theme']}/images/misc/loader.gif">
664
															</td>
665
															<td valign="middle">
666
																&nbsp;<font size="2"><b>Starting Installer...  Please wait...
667
															</td>
668
														</tr>
669
													</table>
670
												</div>
671
												<div id='pbdiv'>
672
													<br />
673
													<center>
674
													<table id='pbtable' height='15' width='640' border='0' colspacing='0' cellpadding='0' cellspacing='0'>
675
														<tr>
676
															<td background="/themes/{$g['theme']}/images/misc/bar_left.gif" height='15' width='5'>
677
															</td>
678
															<td>
679
																<table id="progholder" name="progholder" height='15' width='630' border='0' colspacing='0' cellpadding='0' cellspacing='0'>
680
																	<td background="/themes/{$g['theme']}/images/misc/bar_gray.gif" valign="top" align="left">
681
																		<img src='/themes/{$g['theme']}/images/misc/bar_blue.gif' width='0' height='15' name='progressbar' id='progressbar'>
682
																	</td>
683
																</table>
684
															</td>
685
															<td background="/themes/{$g['theme']}/images/misc/bar_right.gif" height='15' width='5'>
686
															</td>
687
														</tr>
688
													</table>
689
													<br />
690
												</div>
691
												<textarea name='installeroutput' id='installeroutput' rows="31" cols="90">
692
												</textarea>
693
											</div>
694
			     						</td>
695
									</tr>
696
								</table>
697
							</div>
698
						</td>
699
					</tr>
700
				</table>
701
			</div>
702
		</td></tr>
703
		</table>
704
	</center>
705
	<script type="text/javascript">setTimeout('getinstallerprogress()', 250);</script>
706

    
707
EOF;
708
	page_table_end();
709
	end_html();
710
}
711

    
712
function page_table_start($pgtitle = "") {
713
	global $g, $fstype, $savemsg;
714
	if($pgtitle == "") 
715
		$pgtitle = "{$g['product_name']} installer";
716
	echo <<<EOF
717
	<center>
718
		<img border="0" src="/themes/{$g['theme']}/images/logo.gif"></a><br />
719
		<table cellpadding="6" cellspacing="0" width="550" style="border:1px solid #000000">
720
		<tr height="10" bgcolor="#990000">
721
			<td style="border-bottom:1px solid #000000">
722
				<font color='white'>
723
					<b>
724
						{$pgtitle}
725
					</b>
726
				</font>
727
			</td>
728
		</tr>
729
		<tr>
730
			<td>
731

    
732
EOF;
733

    
734
}
735

    
736
function page_table_end() {
737
	global $g, $fstype, $savemsg;
738
	echo <<<EOF
739
			</td>
740
		</tr>
741
		</table>
742
	</center>
743

    
744
EOF;
745
	
746
}
747

    
748
function installer_custom() {
749
	global $g, $fstype, $savemsg;
750
	global $select_txt, $custom_disks;
751
	if(file_exists("/tmp/.pc-sysinstall/pc-sysinstall.log")) 
752
		unlink("/tmp/.pc-sysinstall/pc-sysinstall.log");
753
	$disks = installer_find_all_disks();
754
	// Pass size of disks down to javascript.
755
	$disk_sizes_js_txt = "var disk_sizes = new Array();\n";
756
	foreach($disks as $disk) 
757
		$disk_sizes_js_txt .= "disk_sizes['{$disk['disk']}'] = '{$disk['size']}';\n";
758
	head_html();
759
	body_html();
760
	page_table_start($g['product_name'] . " installer - Customize disk(s) layout");
761
	echo <<<EOF
762
		<script type="text/javascript">
763
			Array.prototype.in_array = function(p_val) {
764
				for(var i = 0, l = this.length; i < l; i++) {
765
					if(this[i] == p_val) {
766
						return true;
767
					}
768
				}
769
				return false;
770
			}
771
			function row_helper_dynamic_custom() {
772
				var totalsize = 0;
773
				{$disk_sizes_js_txt}
774
				// Run through all rows and process data
775
				for(var x = 0; x<99; x++) { //optimize me better
776
					if(\$('#fstype' + x).length) {
777
						if(\$('#size' + x).val() == '')
778
							\$('#size' + x).val(disk_sizes[\$('disk' + x).value]);
779
						var fstype = \$('#fstype' + x).val();
780
						if(fstype.substring(fstype.length - 4) == ".eli") {
781
							\$('#encpass' + x).prop('disabled',false);
782
							if(!encryption_warning_shown) {
783
								alert('NOTE: If you define a disk encryption password you will need to enter it on *EVERY* bootup!');
784
								encryption_warning_shown = true;
785
							}
786
						} else { 
787
							\$('#encpass' + x).prop('disabled',true);
788
						}
789
					}
790
					// Calculate size allocations
791
					if(\$('#size' + x).length) {
792
						if(parseInt($('#size' + x).val()) > 0)
793
							totalsize += parseInt($('#size' + x).val());
794
					}
795
				}
796
				// If the totalsize element exists, set it and disable
797
				if(\$('#totalsize').length) {
798
					if(\$('#totalsize').val() != totalsize) {
799
						// When size allocation changes, draw attention.
800
 						jQuery('#totalsize').effect('highlight');
801
						\$('#totalsize').val(totalsize);
802
					}
803
					\$('#totalsize').prop('disabled',true);
804
				}
805
				if(\$('#disktotals').length) {
806
					var disks_seen = new Array();
807
					var tmp_sizedisks = 0;
808
					var disksseen = 0;
809
					for(var xx = 0; xx<99; xx++) {
810
						if(\$('#disk' + xx).length) {
811
							if(!disks_seen.in_array(\$('#disk' + xx).val())) {
812
								tmp_sizedisks += parseInt(disk_sizes[\$('#disk' + xx).val()]);
813
								disks_seen[disksseen] = \$('#disk' + xx).val();
814
								disksseen++;
815
							}
816
						}
817
					\$('#disktotals').val(tmp_sizedisks);
818
					\$('#disktotals').prop('disabled',true);
819
					\$('#disktotals').css('color','#000000');
820
					var remaining = parseInt(\$('#disktotals').val()) - parseInt(\$('#totalsize').val());
821
						if(remaining == 0) {
822
							if(\$('#totalsize').length)
823
								\$('#totalsize').css({
824
									'background':'#00FF00',
825
									'color':'#000000'
826
								});
827
						} else {
828
							if(\$('#totalsize').length)
829
								\$('#totalsize').css({
830
									'background':'#FFFFFF',
831
									'color':'#000000'
832
								});
833
						}
834
						if(parseInt(\$('#totalsize').val()) > parseInt(\$('#disktotals').val())) {
835
							if(\$('#totalsize'))
836
								\$('#totalsize').css({
837
									'background':'#FF0000',
838
									'color':'#000000'
839
								});							
840
						}
841
						if(\$('#availalloc').length) {
842
							\$('#availalloc').prop('disabled',true);
843
							\$('#availalloc').val(remaining);
844
								\$('#availalloc').css({
845
									'background':'#FFFFFF',
846
									'color':'#000000'
847
								});							
848
						}
849
					}
850
				}
851
			}
852
		</script>
853
		<script type="text/javascript" src="/javascript/row_helper_dynamic.js"></script>
854
		<script type="text/javascript">
855
			// Setup rowhelper data types
856
			rowname[0] = "mountpoint";
857
			rowtype[0] = "textbox";
858
			rowsize[0] = "8";
859
			rowname[1] = "fstype";
860
			rowtype[1] = "select";
861
			rowsize[1] = "1";
862
			rowname[2] = "disk";
863
			rowtype[2] = "select";
864
			rowsize[2] = "1";
865
			rowname[3] = "size";
866
			rowtype[3] = "textbox";
867
			rowsize[3] = "8";
868
			rowname[4] = "encpass";
869
			rowtype[4] = "textbox";
870
			rowsize[4] = "8";
871
			field_counter_js = 5;
872
			rows = 1;
873
			totalrows = 1;
874
			loaded = 1;
875
			rowhelper_onChange = 	" onChange='javascript:row_helper_dynamic_custom()' ";
876
			rowhelper_onDelete = 	"row_helper_dynamic_custom(); ";
877
			rowhelper_onAdd = 		"row_helper_dynamic_custom();";
878
		</script>
879
		<form action="installer.php" method="post">
880
			<input type="hidden" name="state" value="verify_before_install">
881
			<div id="mainlevel">
882
				<center>
883
				<table width="100%" border="0" cellpadding="5" cellspacing="0">
884
			 		<tr>
885
			    		<td>
886
							<center>
887
							<div id="mainarea">
888
								<center>
889
								<table width="100%" border="0" cellpadding="5" cellspacing="5">
890
									<tr>
891
			     						<td>
892
											<div id="pfsenseinstaller">
893
												<center>
894
												<div id='loadingdiv'>
895
													<table>
896
														<tr>
897
															<td valign="center">
898
																<img src="/themes/{$g['theme']}/images/misc/loader.gif">
899
															</td>
900
															<td valign="center">
901
														 		&nbsp;Probing disks, please wait...
902
															</td>
903
														</tr>
904
													</table>
905
												</div>
906
EOF;
907
	ob_flush();
908
	// Read bootmanager setting from disk if found
909
	if(file_exists("/tmp/webInstaller_disk_bootmanager.txt"))
910
		$bootmanager = unserialize(file_get_contents("/tmp/webInstaller_disk_bootmanager.txt"));
911
	if($bootmanager == "none") 
912
		$noneselected = " SELECTED";
913
	if($bootmanager == "bsd") 
914
		$bsdeselected = " SELECTED";
915
	if(!$disks)  {
916
		$custom_txt = gettext("ERROR: Could not find any suitable disks for installation.");
917
	} else {
918
		// Prepare disk selection dropdown
919
		$custom_txt = <<<EOF
920
												<center>
921
												<table>
922
												<tr>
923
													<td align='right'>
924
														Boot manager:
925
													</td>
926
													<td>
927
														<select name='bootmanager'>
928
															<option value='none' $noneselected>
929
																None
930
															</option>
931
															<option value='bsd' $bsdeselected>
932
																BSD
933
															</option>
934
														</select>
935
													</td>
936
												</tr>
937
												</table>
938
												<hr>
939
												<table id='maintable'><tbody>
940
												<tr>
941
													<td align="middle">
942
														<b>Mount</b>
943
													</td>
944
													<td align='middle'>
945
														<b>Filesysytem</b>
946
													</td>
947
													<td align="middle">
948
														<b>Disk</b>
949
													</td>
950
													<td align="middle">
951
														<b>Size</b>
952
													</td>
953
													<td align="middle">
954
														<b>Encryption password</b>
955
													</td>
956
													<td>
957
														&nbsp;
958
													</td>
959
												</tr>
960
												<tr>
961

    
962
EOF;
963

    
964
		// Calculate swap disk sizes
965
		$memory = get_memory();
966
		$swap_size = $memory[0] * 2;
967
		$first_disk = trim(installer_find_first_disk());
968
		$disk_info = pcsysinstall_get_disk_info($first_disk);
969
		$size = $disk_info['size'];
970
		$first_disk_size = $size - $swap_size;
971

    
972
		// Debugging
973
		// echo "\n\n<!-- $first_disk - " . print_r($disk_info, true) . " - $size  - $first_disk_size -->\n\n";
974

    
975
		// Check to see if a on disk layout exists
976
		if(file_exists("/tmp/webInstaller_disk_layout.txt")) {
977
			$disks_restored = unserialize(file_get_contents("/tmp/webInstaller_disk_layout.txt"));
978
			$restored_layout_from_file = true;
979
			$restored_layout_txt = "<br />* The previous disk layout was restored from a previous session";
980
		}
981

    
982
		// If we restored disk layout(s) from a file then build the rows
983
		if($restored_layout_from_file == true) {
984
			$diskcounter = 0;
985
			foreach($disks_restored as $dr) {
986
				$custom_txt .= return_rowhelper_row("$diskcounter", $dr['mountpoint'], $dr['fstype'], $dr['disk'], $dr['size'], $dr['encpass']);
987
				$diskcounter++;
988
			}
989
		} else {		
990
			// Construct the default rows that outline the disks configuration.
991
			$custom_txt .= return_rowhelper_row("0", "/", "UFS+S", $first_disk, "{$first_disk_size}", "");
992
			$custom_txt .= return_rowhelper_row("1", "none", "SWAP", $first_disk, "$swap_size", "");
993
		}
994

    
995
		// tfoot and tbody are used by rowhelper
996
		$custom_txt .= "</tr>";
997
		$custom_txt .= "<tfoot></tfoot></tbody>";
998
		// Total allocation box
999
		$custom_txt .= "<tr><td></td><td></td><td align='right'>Total allocated:</td><td><input style='border:0px; background-color: #FFFFFF;' size='8' id='totalsize' name='totalsize'></td>";
1000
		// Add row button
1001
		$custom_txt .= "</td><td>&nbsp;</td><td>";
1002
		$custom_txt .= "<div id=\"addrowbutton\">";
1003
		$custom_txt .= "<a onclick=\"javascript:addRowTo('maintable', 'formfldalias'); return false;\" href=\"#\">";
1004
		$custom_txt .= "<img border=\"0\" src=\"/themes/{$g['theme']}/images/icons/icon_plus.gif\" alt=\"\" title=\"add another entry\" /></a>";
1005
		$custom_txt .= "</div>";
1006
		$custom_txt .= "</td></tr>";	
1007
		// Disk capacity box
1008
		$custom_txt .= "<tr><td></td><td></td><td align='right'>Disk(s) capacity total:</td><td><input style='border:0px; background-color: #FFFFFF;' size='8' id='disktotals' name='disktotals'></td></tr>";
1009
		// Remaining allocation box
1010
		$custom_txt .= "<tr><td></td><td></td><td align='right'>Available space for allocation:</td><td><input style='border:0px; background-color: #FFFFFF;' size='8' id='availalloc' name='availalloc'></td></tr>";
1011
		$custom_txt .= "</table>";
1012
		$custom_txt .= "<script type=\"text/javascript\">row_helper_dynamic_custom();</script>";
1013
	}
1014
	echo <<<EOF
1015

    
1016
												<tr>
1017
													<td colspan='4'>
1018
													<script type="text/javascript">
1019
														\$('#loadingdiv').css('visibility','hidden');
1020
													</script>
1021
													<div id='contentdiv' style="display:none;">
1022
														<p/>
1023
														{$custom_txt}<p/>
1024
														<hr><p/>
1025
														<input type="button" value="Cancel" onClick="javascript:document.location='/installer/installer.php';"> &nbsp;&nbsp
1026
														<input type="submit" value="Next">
1027
													</div>
1028
													<script type="text/javascript">
1029
														var encryption_warning_shown = false;
1030
														\$('#contentdiv').fadeIn();
1031
														row_helper_dynamic_custom();
1032
													</script>
1033
												</center>
1034
												</td></tr>
1035
												</table>
1036
											</div>
1037
			     						</td>
1038
									</tr>
1039
								</table>
1040
								</center>
1041
								<span class="vexpl">
1042
									<span class="red">
1043
										<strong>
1044
											NOTES:
1045
										</strong>
1046
									</span>
1047
									<br />* Sizes are in megabytes.
1048
									<br />* Mount points named /conf are not allowed.  Use /cf if you want to make a configuration slice/mount.
1049
									{$restored_layout_txt}
1050
								</span>
1051
								</strong>
1052
							</div>
1053
						</td>
1054
					</tr>
1055
				</table>
1056
			</div>
1057
			</center>
1058
			<script type="text/javascript">
1059
			<!--
1060
				newrow[1] = "{$select_txt}";
1061
				newrow[2] = "{$custom_disks}";
1062
			-->
1063
			</script>
1064
			
1065

    
1066
EOF;
1067
	page_table_end();
1068
	end_html();
1069
}
1070

    
1071
function installer_main() {
1072
	global $g, $fstype, $savemsg;
1073
	if(file_exists("/tmp/.pc-sysinstall/pc-sysinstall.log")) 
1074
		unlink("/tmp/.pc-sysinstall/pc-sysinstall.log");
1075
	head_html();
1076
	body_html();
1077
	$disk = installer_find_first_disk();
1078
	// Only enable ZFS if this exists.  The install will fail otherwise.
1079
	if(file_exists("/boot/gptzfsboot")) 
1080
		$zfs_enabled = "<tr bgcolor=\"#9A9A9A\"><td align=\"center\"><a href=\"installer.php?state=easy_install_zfs\">Easy installation of {$g['product_name']} using the ZFS filesystem on disk {$disk}</a></td></tr>";
1081
	page_table_start();
1082
	echo <<<EOF
1083
		<form action="installer.php" method="post" state="step1_post">
1084
			<div id="mainlevel">
1085
				<center>
1086
				<b><font face="arial" size="+2">Welcome to the {$g['product_name']} webInstaller!</b></font><p/>
1087
				<font face="arial" size="+1">This utility will install {$g['product_name']} to a hard disk, flash drive, etc.</font>
1088
				<table width="100%" border="0" cellpadding="5" cellspacing="0">
1089
			 		<tr>
1090
			    		<td>
1091
							<center>
1092
							<div id="mainarea">
1093
								<br />
1094
								<center>
1095
								Please select an installer option to begin:
1096
								<p/>
1097
								<table width="100%" border="0" cellpadding="5" cellspacing="5">
1098
									<tr>
1099
			     						<td>
1100
											<div id="pfsenseinstaller">
1101
												<center>
1102
EOF;
1103
	if(!$disk) {
1104
		echo gettext("ERROR: Could not find any suitable disks for installation.");
1105
		echo "</div></td></tr></table></div></table></div>";
1106
		end_html();
1107
		exit;
1108
	}
1109
	echo <<<EOF
1110

    
1111
													<table cellspacing="5" cellpadding="5" style="border: 1px dashed;">
1112
														<tr bgcolor="#CECECE"><td align="center">
1113
															<a href="installer.php?state=easy_install_ufs">Easy installation of {$g['product_name']} using the UFS filesystem on disk {$disk}</a>
1114
														</td></tr>
1115
													 	{$zfs_enabled}
1116
														<tr bgcolor="#AAAAAA"><td align="center">
1117
															<a href="installer.php?state=custominstall">Custom installation of {$g['product_name']}</a>
1118
														</td></tr>
1119
														<tr bgcolor="#CECECE"><td align="center">
1120
															<a href='/'>Cancel and return to Dashboard</a>
1121
														</td></tr>
1122
													</table>
1123
												</center>
1124
											</div>
1125
			     						</td>
1126
									</tr>
1127
								</table>
1128
							</div>
1129
						</td>
1130
					</tr>
1131
				</table>
1132
			</div>
1133
EOF;
1134
	page_table_end();
1135
	end_html();
1136
}
1137

    
1138
function return_rowhelper_row($rownum, $mountpoint, $fstype, $disk, $size, $encpass) {
1139
		global $g, $select_txt, $custom_disks, $savemsg;
1140
		$release = php_uname("r");
1141
		$release = trim($release[0]);
1142

    
1143
		// Mount point
1144
		$disks = installer_find_all_disks();
1145
		$custom_txt .= "<tr>";
1146
		$custom_txt .=  "<td><input size='8' id='mountpoint{$rownum}' name='mountpoint{$rownum}' value='{$mountpoint}'></td>";
1147

    
1148
		// Filesystem type array
1149
		$types = array(
1150
			'UFS' => 'UFS',
1151
			'UFS+S' => 'UFS + Softupdates',
1152
			'UFS.eli' => 'Encrypted UFS',
1153
			'UFS+S.eli' => 'Encrypted UFS + Softupdates',
1154
			'SWAP' => 'SWAP'
1155
		);
1156

    
1157
		// UFS + Journaling was introduced in 9.0
1158
		if($release == "9") {
1159
			$types['UFS+J'] = "UFS + Journaling";
1160
			$types['UFS+J.eli'] = "Encrypted UFS + Journaling";
1161
		}
1162
		
1163
		// Add ZFS Boot loader if it exists
1164
		if(file_exists("/boot/gptzfsboot")) {
1165
			$types['ZFS'] = "Zetabyte Filesystem";
1166
			$types['ZFS.eli'] = "Encrypted Zetabyte Filesystem";
1167
		}
1168

    
1169
		// fstype form field
1170
		$custom_txt .=  "<td><select onChange='javascript:row_helper_dynamic_custom()' id='fstype{$rownum}' name='fstype{$rownum}'>";
1171
		$select_txt = "";
1172
		foreach($types as $type => $desc) {
1173
			if($type == $fstype)
1174
				$SELECTED="SELECTED";
1175
			else 
1176
				$SELECTED="";
1177
			$select_txt .= "<option value='$type' $SELECTED>$desc</option>";
1178
		}
1179
		$custom_txt .= "{$select_txt}</select>\n";
1180
		$custom_txt .= "</td>";
1181
		
1182
		// Disk selection form field
1183
		$custom_txt .= "<td><select id='disk{$rownum}' name='disk{$rownum}'>\n";
1184
		$custom_disks = "";
1185
		foreach($disks as $dsk) {
1186
			$disksize_bytes = format_bytes($dsk['size'] * 1048576);
1187
			$disksize = $dsk['size'];
1188
			if($disk == $dsk['disk'])
1189
				$SELECTED="SELECTED";
1190
			else 
1191
				$SELECTED="";
1192
			$custom_disks .= "<option value='{$dsk['disk']}' $SELECTED>{$dsk['disk']} - {$dsk['desc']} - {$disksize}MB ({$disksize_bytes})</option>";
1193
		}
1194
		$custom_txt .= "{$custom_disks}</select></td>\n";
1195

    
1196
		// Slice size
1197
		$custom_txt .= "<td><input onChange='javascript:row_helper_dynamic_custom();' name='size{$rownum}' id='size{$rownum}' size='8' type='text' value='{$size}'></td>";
1198

    
1199
		// Encryption password
1200
		$custom_txt .= "<td>";
1201
		$custom_txt .= "<input id='encpass{$rownum}' name='encpass{$rownum}' size='8' value='{$encpass}'>";
1202
		$custom_txt .= "</td>";
1203
	
1204
		// Add Rowhelper + button
1205
		if($rownum > 0) 
1206
			$custom_txt .= "<td><a onclick=\"removeRow(this); return false;\" href=\"#\"><img border=\"0\" src=\"/themes/{$g['theme']}/images/icons/icon_x.gif\" alt=\"\" title=\"remove this entry\"/></a></td>";
1207

    
1208
		$custom_txt .= "</tr>";	
1209
		return $custom_txt;
1210
}
1211

    
1212
?>
(2-2/2)