Project

General

Profile

Download (30.4 KB) Statistics
| Branch: | Tag: | Revision:
1
<?php
2
/****h* pfSense/pkg-utils
3
	NAME
4
		pkg-utils.inc - Package subsystem
5
	DESCRIPTION
6
		This file contains various functions used by the pfSense package system.
7
	HISTORY
8
		$Id$
9
*/
10
/* ====================================================================
11
 *	Copyright (c)  2004-2015  Electric Sheep Fencing, LLC. All rights reserved.
12
 *	Copyright (c)  2004, 2005 Scott Ullrich
13
 *	Copyright (c)  2005-2006 Colin Smith (ethethlay@gmail.com)
14
 *
15
 *	Redistribution and use in source and binary forms, with or without modification,
16
 *	are permitted provided that the following conditions are met:
17
 *
18
 *	1. Redistributions of source code must retain the above copyright notice,
19
 *		this list of conditions and the following disclaimer.
20
 *
21
 *	2. Redistributions in binary form must reproduce the above copyright
22
 *		notice, this list of conditions and the following disclaimer in
23
 *		the documentation and/or other materials provided with the
24
 *		distribution.
25
 *
26
 *	3. All advertising materials mentioning features or use of this software
27
 *		must display the following acknowledgment:
28
 *		"This product includes software developed by the pfSense Project
29
 *		 for use in the pfSense software distribution. (http://www.pfsense.org/).
30
 *
31
 *	4. The names "pfSense" and "pfSense Project" must not be used to
32
 *		 endorse or promote products derived from this software without
33
 *		 prior written permission. For written permission, please contact
34
 *		 coreteam@pfsense.org.
35
 *
36
 *	5. Products derived from this software may not be called "pfSense"
37
 *		nor may "pfSense" appear in their names without prior written
38
 *		permission of the Electric Sheep Fencing, LLC.
39
 *
40
 *	6. Redistributions of any form whatsoever must retain the following
41
 *		acknowledgment:
42
 *
43
 *	"This product includes software developed by the pfSense Project
44
 *	for use in the pfSense software distribution (http://www.pfsense.org/).
45
 *
46
 *	THIS SOFTWARE IS PROVIDED BY THE pfSense PROJECT ``AS IS'' AND ANY
47
 *	EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
48
 *	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
49
 *	PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE pfSense PROJECT OR
50
 *	ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
51
 *	SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
52
 *	NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
53
 *	LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
54
 *	HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
55
 *	STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56
 *	ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
57
 *	OF THE POSSIBILITY OF SUCH DAMAGE.
58
 *
59
 *	====================================================================
60
 *
61
 */
62
/*
63
	pfSense_BUILDER_BINARIES:	/usr/bin/cd /usr/bin/tar	/usr/sbin/fifolog_create	/bin/chmod
64
	pfSense_BUILDER_BINARIES:	/usr/sbin/pkg_add	/usr/sbin/pkg_info	/usr/sbin/pkg_delete	/bin/rm
65
	pfSense_MODULE: pkg
66
*/
67

    
68
require_once("globals.inc");
69
require_once("service-utils.inc");
70

    
71
if (file_exists("/cf/conf/use_xmlreader")) {
72
	require_once("xmlreader.inc");
73
} else {
74
	require_once("xmlparse.inc");
75
}
76

    
77
require_once("pfsense-utils.inc");
78

    
79
if (!function_exists("pkg_debug")) {
80
	/* set up logging if needed */
81
	function pkg_debug($msg) {
82
		global $g, $debug, $fd_log;
83

    
84
		if (!$debug) {
85
			return;
86
		}
87

    
88
		if (!$fd_log) {
89
			if (!$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_debug.log", "w")) {
90
				update_output_window("Warning, could not open log for writing.");
91
			}
92
		}
93
		@fwrite($fd_log, $msg);
94
	}
95
}
96

    
97
global $g;
98
if (!isset($g['platform'])) {
99
	$g['platform'] = trim(file_get_contents("/etc/platform"));
100
}
101

    
102
/* Remove pkg_prefix from package name if it's present */
103
function pkg_remove_prefix(&$pkg_name) {
104
	global $g;
105

    
106
	if (substr($pkg_name, 0, strlen($g['pkg_prefix'])) == $g['pkg_prefix']) {
107
		$pkg_name = substr($pkg_name, strlen($g['pkg_prefix']));
108
	}
109
}
110

    
111
/* Execute pkg update when it's necessary */
112
function pkg_update($force = false) {
113
	global $g;
114

    
115
	$now = strftime('%s');
116
	if (!$force) {
117
		$last_update_file="{$g['varrun_path']}/{$g['product_name']}-upgrade-last-update";
118

    
119
		if (file_exists($last_update_file)) {
120
			$last_update = rtrim(file_get_contents($last_update_file), "\n");
121
			if (!is_numericint($last_update)) {
122
				$last_update = 0;
123
			}
124
		}
125

    
126
		if ($last_update > 0) {
127
			if ($now > $last_update && ($now - $last_update) <= (60 * 60)) {
128
				return true;
129
			}
130
		}
131
	}
132

    
133
	$rc = pkg_call("update");
134

    
135
	if ($rc) {
136
		file_put_contents($last_update_file, $now . "\n");
137
	}
138

    
139
	return $rc;
140
}
141

    
142
/* Execute a pkg call */
143
function pkg_call($params, $mute = false) {
144
	global $static_output, $g, $config;
145

    
146
	if (empty($params)) {
147
		return false;
148
	}
149

    
150
	$user_agent = $g['product_name'] . '/' . $g['product_version'];
151
	if (!isset($config['system']['host_uuid'])) {
152
		$user_agent .= ' : ' . get_single_sysctl('kern.hostuuid');
153
	}
154

    
155
	$env = array(
156
		"HTTP_USER_AGENT" => $user_agent,
157
		"ASSUME_ALWAYS_YES" => "true",
158
		"REPO_AUTOUPDATE" => "false"
159
	);
160

    
161
	$debug_fifo = $g['tmp_path'] . "/pkg-debug.fifo";
162
	if (!file_exists($debug_fifo)) {
163
		posix_mkfifo($debug_fifo, 0600);
164
	}
165

    
166
	if (filetype($debug_fifo) == 'fifo') {
167
		$env["EVENT_PIPE"] = $debug_fifo;
168
	}
169

    
170
	$descriptorspec = array(
171
		1 => array("pipe", "w"), /* stdout */
172
		2 => array("pipe", "w")	 /* stderr */
173
	);
174

    
175
	pkg_debug("pkg_call(): {$params}\n");
176
	$process = proc_open("/usr/sbin/pkg {$params}", $descriptorspec, $pipes, '/', $env);
177

    
178
	if (!is_resource($process)) {
179
		return false;
180
	}
181

    
182
	stream_set_blocking($pipes[1], 0);
183
	stream_set_blocking($pipes[2], 0);
184

    
185
	/* XXX: should be a tunnable? */
186
	$timeout = 300; // seconds
187
	$error_log = '';
188
	$started = time();
189
	$maxwaittime = 10; // Number of seconds to wait for a response fromteh pacakge we are calling
190

    
191
	do {
192
		$write = array();
193
		$read = array($pipes[1], $pipes[2]);
194
		$except = array();
195

    
196
		$stream = stream_select($read, $write, $except, null, $timeout);
197
		if ($stream !== FALSE && $stream > 0) {
198
			foreach ($read as $pipe) {
199
				$content = stream_get_contents($pipe);
200
				if ($content == '') {
201
					continue;
202
				}
203
				if ($pipe === $pipes[1]) {
204
					if (!$mute) {
205
						$static_output .= $content;
206
						update_output_window($static_output);
207
					}
208
					flush();
209
				} else if ($pipe === $pipes[2]) {
210
					$error_log .= $content;
211
				}
212
			}
213
		}
214

    
215
		$status = proc_get_status($process);
216

    
217
		$now = time();
218

    
219
		if(($now - $started) >= $maxwaittime) {
220
			$rc = -1;
221
			proc_terminate($process);
222
			break;
223
		}
224

    
225
	} while ($status['running']);
226

    
227
	fclose($pipes[1]);
228
	fclose($pipes[2]);
229
	proc_close($process);
230

    
231
	if(!isset($rc)) {
232
		$rc = $status['exitcode'];
233
	}
234

    
235
	pkg_debug("pkg_call(): rc = {$rc}\n");
236
	if ($rc == 0) {
237
		return true;
238
	}
239

    
240
	pkg_debug("pkg_call(): error_log\n{$error_log}\n");
241
	if (!$mute) {
242
		$static_output .= "\n\n" . sprintf(gettext("ERROR!!! An error occurred on pkg execution (rc = %d) with parameters '%s':"), $rc, $params) . "\n" . $error_log;
243
		update_output_window($static_output);
244
	}
245

    
246
	return false;
247
}
248

    
249
/* Execute pkg with $params, fill stdout and stderr and return pkg rc */
250
function pkg_exec($params, &$stdout, &$stderr) {
251
	global $g, $config;
252

    
253
	if (empty($params)) {
254
		return -1;
255
	}
256

    
257
	$user_agent = $g['product_name'] . '/' . $g['product_version'];
258
	if (!isset($config['system']['host_uuid'])) {
259
		$user_agent .= ' : ' . get_single_sysctl('kern.hostuuid');
260
	}
261

    
262
	$env = array(
263
		"HTTP_USER_AGENT" => $user_agent,
264
		"ASSUME_ALWAYS_YES" => "true",
265
		"REPO_AUTOUPDATE" => "false"
266
	);
267

    
268
	$debug_fifo = $g['tmp_path'] . "/pkg-debug.fifo";
269
	if (!file_exists($debug_fifo)) {
270
		posix_mkfifo($debug_fifo, 0600);
271
	}
272

    
273
	if (filetype($debug_fifo) == 'fifo') {
274
		$env["EVENT_PIPE"] = $debug_fifo;
275
	}
276

    
277
	$descriptorspec = array(
278
		1 => array("pipe", "w"), /* stdout */
279
		2 => array("pipe", "w")	 /* stderr */
280
	);
281

    
282
	pkg_debug("pkg_exec(): {$params}\n");
283
	$process = proc_open("/usr/sbin/pkg {$params}", $descriptorspec, $pipes, '/', $env);
284

    
285
	if (!is_resource($process)) {
286
		return -1;
287
	}
288

    
289
	$stdout = '';
290
	while (($l = fgets($pipes[1])) !== FALSE) {
291
		$stdout .= $l;
292
	}
293
	fclose($pipes[1]);
294

    
295
	$stderr = '';
296
	while (($l = fgets($pipes[2])) !== FALSE) {
297
		$stderr .= $l;
298
	}
299
	fclose($pipes[2]);
300

    
301
	return proc_close($process);
302
}
303

    
304
/* Check if package is installed */
305
function is_pkg_installed($pkg_name) {
306
	global $g;
307

    
308
	pkg_remove_prefix($pkg_name);
309

    
310
	return pkg_call("info -e " . $g['pkg_prefix'] . $pkg_name, true);
311
}
312

    
313
/* Install package, $pkg_name should not contain prefix */
314
function pkg_install($pkg_name) {
315
	global $g;
316
	$result = false;
317

    
318
	pkg_remove_prefix($pkg_name);
319

    
320
	pkg_debug("Installing package {$pkg_name}\n");
321
	if (!is_pkg_installed($pkg_name)) {
322
		$result = pkg_call("install -y " . $g['pkg_prefix'] . $pkg_name);
323
		/* Cleanup cacke to free disk space */
324
		pkg_call("clean -y");
325
	}
326

    
327
	return $result;
328
}
329

    
330
/* Delete package from FreeBSD, $pkg_name should not contain prefix */
331
function pkg_delete($pkg_name) {
332
	global $g;
333

    
334
	pkg_remove_prefix($pkg_name);
335

    
336
	pkg_debug("Removing package {$pkg_name}\n");
337
	if (is_pkg_installed($pkg_name)) {
338
		pkg_call("delete -y " . $g['pkg_prefix'] . $pkg_name);
339
		/* Cleanup unecessary dependencies */
340
		pkg_call("autoremove -y");
341
	}
342
}
343

    
344
/* Check if package is present in config.xml */
345
function is_package_installed($package_name) {
346
	return (get_package_id($package_name) != -1);
347
}
348

    
349
/* Find package array index */
350
function get_package_id($package_name) {
351
	global $config;
352

    
353
	if (!is_array($config['installedpackages']['package'])) {
354
		return -1;
355
	}
356

    
357
	foreach ($config['installedpackages']['package'] as $idx => $pkg) {
358
		if ($pkg['name'] == $package_name ||
359
			get_package_internal_name($pkg) == $package_name) {
360
			return $idx;
361
		}
362
	}
363

    
364
	return -1;
365
}
366

    
367
/* Keep backward compatibility since snort/suricata use this function */
368
function get_pkg_id($package_name) {
369
	return get_package_id($package_name);
370
}
371

    
372
/* Return internal_name when it's defined, otherwise, returns name */
373
function get_package_internal_name($package_data) {
374
	if (isset($package_data['internal_name']) && ($package_data['internal_name'] != "")) {
375
		/* e.g. name is Ipguard-dev, internal name is ipguard */
376
		return $package_data['internal_name'];
377
	} else {
378
		return $package_data['name'];
379
	}
380
}
381

    
382
// Get information about packages.
383
function get_pkg_info($pkgs = 'all', $info = 'all') {
384
	global $g, $static_output, $input_errors;
385

    
386
	$out = '';
387
	$err = '';
388

    
389
	if ($pkgs == 'all') {
390
		$pkgs = $g['pkg_prefix'];
391
	}
392

    
393

    
394
	/* Make sure repo metadata is up2date */
395
	$static_output .= "\n" . gettext("Updating package repository metadada...") . "\n";
396
	update_status($static_output);
397

    
398
	if (!pkg_update()) {
399
		$input_errors[] = gettext("ERROR: An error occurred when updating packages repository. Aborting...") . "\n";
400
		$static_output .= "\n" . gettext("ERROR: An error occurred when updating packages repository. Aborting...") . "\n";
401
		update_status($static_output);
402
		return array();
403
	}
404

    
405

    
406
	$rc = pkg_exec("search -U --raw-format json-compact " . $pkgs, $out, $err);
407

    
408
	if ($rc != 0) {
409
		$static_output .= "\n" . gettext("ERROR: Error trying to get packages list. Aborting...") . "\n";
410
		$static_output .= $err;
411
		$input_errors[] =  gettext("ERROR: Error trying to get packages list. Aborting...") . "\n";
412
		$input_errors[] =  $err;
413
		update_status($static_output);
414
		return array();
415
	}
416

    
417
	$result = array();
418
	$pkgs_info = explode("\n", $out);
419
	foreach ($pkgs_info as $pkg_info_json) {
420
		$pkg_info = json_decode($pkg_info_json, true);
421
		if (!isset($pkg_info['name'])) {
422
			continue;
423
		}
424

    
425
		$result[] = $pkg_info;
426
		unset($pkg_info);
427
	}
428

    
429
	return $result;
430
}
431

    
432
/*
433
 * resync_all_package_configs() Force packages to setup their configuration and rc.d files.
434
 * This function may also print output to the terminal indicating progress.
435
 */
436
function resync_all_package_configs($show_message = false) {
437
	global $config, $pkg_interface, $g;
438

    
439
	log_error(gettext("Resyncing configuration for all packages."));
440

    
441
	if (!is_array($config['installedpackages']['package'])) {
442
		return;
443
	}
444

    
445
	if ($show_message == true) {
446
		echo "Syncing packages:";
447
	}
448

    
449
	conf_mount_rw();
450

    
451
	foreach ($config['installedpackages']['package'] as $idx => $package) {
452
		if (empty($package['name'])) {
453
			continue;
454
		}
455
		if ($show_message == true) {
456
			echo " " . $package['name'];
457
		}
458
		if (platform_booting() != true) {
459
			stop_service(get_package_internal_name($package));
460
		}
461
		sync_package($package['name']);
462
		if ($pkg_interface == "console") {
463
			echo "\n" . gettext("Syncing packages:");
464
		}
465
	}
466

    
467
	if ($show_message == true) {
468
		echo " done.\n";
469
	}
470

    
471
	@unlink("/conf/needs_package_sync");
472
	conf_mount_ro();
473
}
474

    
475
function uninstall_package($package_name) {
476
	global $config, $static_output;
477

    
478
	$internal_name = $package_name;
479
	$id = get_package_id($package_name);
480
	if ($id >= 0) {
481
		$internal_name = get_package_internal_name($config['installedpackages']['package'][$id]);
482
		stop_service($internal_name);
483
	}
484

    
485
	if (is_pkg_installed($internal_name)) {
486
		$static_output .= "Removing package...\n";
487
		update_output_window($static_output);
488
		pkg_delete($internal_name);
489
	} else {
490
		delete_package_xml($package_name);
491
	}
492

    
493
	$static_output .= gettext("done.") . "\n";
494
	update_output_window($static_output);
495
}
496

    
497
/* Run <custom_php_resync_config_command> */
498
function sync_package($package_name) {
499
	global $config, $builder_package_install;
500

    
501
	// If this code is being called by pfspkg_installer
502
	// which the builder system uses then return (ignore).
503
	if ($builder_package_install) {
504
		return;
505
	}
506

    
507
	if (empty($config['installedpackages']['package'])) {
508
		return;
509
	}
510

    
511
	if (($pkg_id = get_package_id($package_name)) == -1) {
512
		return; // This package doesn't really exist - exit the function.
513
	}
514

    
515
	if (!is_array($config['installedpackages']['package'][$pkg_id])) {
516
		return;	 // No package belongs to the pkg_id passed to this function.
517
	}
518

    
519
	$package =& $config['installedpackages']['package'][$pkg_id];
520
	if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
521
		log_error(sprintf(gettext("The %s package is missing its configuration file and must be reinstalled."), $package['name']));
522
		delete_package_xml($package['name']);
523
		return;
524
	}
525

    
526
	$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
527
	if (isset($pkg_config['nosync'])) {
528
		return;
529
	}
530

    
531
	/* Bring in package include files */
532
	if (!empty($pkg_config['include_file'])) {
533
		$include_file = $pkg_config['include_file'];
534
		if (file_exists($include_file)) {
535
			require_once($include_file);
536
		} else {
537
			log_error("Reinstalling package {$package['name']} because its include file({$include_file}) is missing!");
538
			uninstall_package($package['name']);
539
			if (install_package($package['name']) != 0) {
540
				log_error("Reinstalling package {$package['name']} failed. Take appropriate measures!!!");
541
				return;
542
			}
543
			if (file_exists($include_file)) {
544
				require_once($include_file);
545
			} else {
546
				return;
547
			}
548
		}
549
	}
550

    
551
	if (!empty($pkg_config['custom_php_global_functions'])) {
552
		eval($pkg_config['custom_php_global_functions']);
553
	}
554
	if (!empty($pkg_config['custom_php_resync_config_command'])) {
555
		eval($pkg_config['custom_php_resync_config_command']);
556
	}
557
}
558

    
559
/* Read info.xml installed by package and return an array */
560
function read_package_config($package_name) {
561
	global $g;
562

    
563
	$pkg_info_xml = '/usr/local/share/' . $g['pkg_prefix'] . $package_name . '/info.xml';
564

    
565
	if (!file_exists($pkg_info_xml)) {
566
		return false;
567
	}
568

    
569
	$pkg_info = parse_xml_config_pkg($pkg_info_xml, 'pfsensepkgs');
570

    
571
	if (empty($pkg_info)) {
572
		return false;
573
	}
574

    
575
	/* it always returns an array with 1 item */
576
	return $pkg_info['package'][0];
577
}
578

    
579
function get_after_install_info($package_name) {
580
	$pkg_config = read_package_config($package_name);
581

    
582
	if (isset($pkg_config['after_install_info'])) {
583
		return $pkg_config['after_install_info'];
584
	}
585

    
586
	return '';
587
}
588

    
589
function eval_once($toeval) {
590
	global $evaled;
591
	if (!$evaled) {
592
		$evaled = array();
593
	}
594
	$evalmd5 = md5($toeval);
595
	if (!in_array($evalmd5, $evaled)) {
596
		@eval($toeval);
597
		$evaled[] = $evalmd5;
598
	}
599
	return;
600
}
601

    
602
function install_package($package_name) {
603
	global $g, $config, $static_output, $pkg_interface;
604

    
605
	if ($pkg_interface == "console") {
606
		echo "\n";
607
	}
608

    
609
	return pkg_install($package_name);
610
}
611

    
612
function install_package_xml($package_name) {
613
	global $g, $config, $static_output, $pkg_interface;
614

    
615
	if (($pkg_info = read_package_config($package_name)) == false) {
616
		return false;
617
	}
618

    
619
	/* safe side. Write config below will send to ro again. */
620
	conf_mount_rw();
621

    
622
	pkg_debug(gettext("Beginning package installation.") . "\n");
623
	log_error(sprintf(gettext('Beginning package installation for %s .'), $pkg_info['name']));
624

    
625
	/* add package information to config.xml */
626
	$pkgid = get_package_id($pkg_info['name']);
627
	$static_output .= gettext("Saving updated package information...") . " ";
628
	update_output_window($static_output);
629
	if ($pkgid == -1) {
630
		$config['installedpackages']['package'][] = $pkg_info;
631
		$changedesc = sprintf(gettext("Installed %s package."), $pkg_info['name']);
632
		$to_output = gettext("done.") . "\n";
633
	} else {
634
		$config['installedpackages']['package'][$pkgid] = $pkg_info;
635
		$changedesc = sprintf(gettext("Overwrote previous installation of %s."), $pkg_info['name']);
636
		$to_output = gettext("overwrite!") . "\n";
637
	}
638
	unlink_if_exists('/conf/needs_package_sync');
639
	write_config("Intermediate config write during package install for {$pkg_info['name']}.");
640
	conf_mount_ro();
641
	$static_output .= $to_output;
642
	update_output_window($static_output);
643

    
644
	if (($pkgid = get_package_id($package_name)) == -1) {
645
		$static_output .= sprintf(gettext("The %s package is not installed.%sInstallation aborted."), $package_name, "\n\n");
646
		update_output_window($static_output);
647
		if ($pkg_interface <> "console") {
648
			echo "\n<script>document.getElementById('progressbar').style.visibility='hidden';</script>";
649
			echo "\n<script>document.getElementById('progholder').style.visibility='hidden';</script>";
650
		}
651

    
652
		uninstall_package($package_name);
653
		write_config($changedesc);
654
		log_error(sprintf(gettext("Failed to install package: %s."), $pkg_info['name']));
655
		$static_output .= gettext("Failed to install package.") . "\n";
656
		update_output_window($static_output);
657
		return false;
658
	}
659

    
660
	$configfile = substr(strrchr($pkg_info['config_file'], '/'), 1);
661
	if (file_exists("/usr/local/pkg/" . $configfile)) {
662
		$static_output .= gettext("Loading package configuration... ");
663
		update_output_window($static_output);
664
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $configfile, "packagegui");
665
		$static_output .= gettext("done.") . "\n";
666
		update_output_window($static_output);
667
		$static_output .= gettext("Configuring package components...\n");
668
		if (!empty($pkg_config['filter_rules_needed'])) {
669
			$config['installedpackages']['package'][$pkgid]['filter_rule_function'] = $pkg_config['filter_rules_needed'];
670
		}
671
		update_output_window($static_output);
672
		/* modify system files */
673

    
674
		/* if a require exists, include it.  this will
675
		 * show us where an error exists in a package
676
		 * instead of making us blindly guess
677
		 */
678
		$missing_include = false;
679
		if ($pkg_config['include_file'] <> "") {
680
			$static_output .= gettext("Loading package instructions...") . "\n";
681
			update_output_window($static_output);
682
			if (file_exists($pkg_config['include_file'])) {
683
				pkg_debug("require_once('{$pkg_config['include_file']}')\n");
684
				require_once($pkg_config['include_file']);
685
			} else {
686
				pkg_debug("Missing include {$pkg_config['include_file']}\n");
687
				$missing_include = true;
688
				$static_output .= "Include " . basename($pkg_config['include_file']) . " is missing!\n";
689
				update_output_window($static_output);
690

    
691
				uninstall_package($package_name);
692
				write_config($changedesc);
693
				log_error(sprintf(gettext("Failed to install package: %s."), $pkg_info['name']));
694
				$static_output .= gettext("Failed to install package.") . "\n";
695
				update_output_window($static_output);
696
				return false;
697
			}
698
		}
699

    
700
		/* custom commands */
701
		$static_output .= gettext("Custom commands...") . "\n";
702
		update_output_window($static_output);
703
		if ($missing_include == false) {
704
			if ($pkg_config['custom_php_global_functions'] <> "") {
705
				$static_output .= gettext("Executing custom_php_global_functions()...");
706
				update_output_window($static_output);
707
				eval_once($pkg_config['custom_php_global_functions']);
708
				$static_output .= gettext("done.") . "\n";
709
				update_output_window($static_output);
710
			}
711
			if ($pkg_config['custom_php_install_command']) {
712
				$static_output .= gettext("Executing custom_php_install_command()...");
713
				update_output_window($static_output);
714
				eval_once($pkg_config['custom_php_install_command']);
715
				$static_output .= gettext("done.") . "\n";
716
				update_output_window($static_output);
717
			}
718
			if ($pkg_config['custom_php_resync_config_command'] <> "") {
719
				$static_output .= gettext("Executing custom_php_resync_config_command()...");
720
				update_output_window($static_output);
721
				eval_once($pkg_config['custom_php_resync_config_command']);
722
				$static_output .= gettext("done.") . "\n";
723
				update_output_window($static_output);
724
			}
725
		}
726
		/* sidebar items */
727
		if (is_array($pkg_config['menu'])) {
728
			$static_output .= gettext("Menu items... ");
729
			update_output_window($static_output);
730
			foreach ($pkg_config['menu'] as $menu) {
731
				if (is_array($config['installedpackages']['menu'])) {
732
					foreach ($config['installedpackages']['menu'] as $amenu) {
733
						if ($amenu['name'] == $menu['name']) {
734
							continue 2;
735
						}
736
					}
737
				} else {
738
					$config['installedpackages']['menu'] = array();
739
				}
740
				$config['installedpackages']['menu'][] = $menu;
741
			}
742
			$static_output .= gettext("done.") . "\n";
743
			update_output_window($static_output);
744
		}
745
		/* services */
746
		if (is_array($pkg_config['service'])) {
747
			$static_output .= gettext("Services... ");
748
			update_output_window($static_output);
749
			foreach ($pkg_config['service'] as $service) {
750
				if (is_array($config['installedpackages']['service'])) {
751
					foreach ($config['installedpackages']['service'] as $aservice) {
752
						if ($aservice['name'] == $service['name']) {
753
							continue 2;
754
						}
755
					}
756
				} else {
757
					$config['installedpackages']['service'] = array();
758
				}
759
				$config['installedpackages']['service'][] = $service;
760
			}
761
			$static_output .= gettext("done.") . "\n";
762
			update_output_window($static_output);
763
		}
764
	} else {
765
		pkg_debug("Unable to find config file\n");
766
		$static_output .= gettext("Loading package configuration... failed!") . "\n\n" . gettext("Installation aborted.");
767
		update_output_window($static_output);
768
		pkg_debug(gettext("Unable to load package configuration. Installation aborted.") ."\n");
769
		if ($pkg_interface <> "console") {
770
			echo "\n<script>document.getElementById('progressbar').style.visibility='hidden';</script>";
771
			echo "\n<script>document.getElementById('progholder').style.visibility='hidden';</script>";
772
		}
773

    
774
		uninstall_package($package_name);
775
		write_config($changedesc);
776
		log_error(sprintf(gettext("Failed to install package: %s."), $pkg_info['name']));
777
		$static_output .= gettext("Failed to install package.") . "\n";
778
		update_output_window($static_output);
779
		return false;
780
	}
781

    
782
	/* set up package logging streams */
783
	if ($pkg_info['logging']) {
784
		system_syslogd_start();
785
	}
786

    
787
	$static_output .= gettext("Writing configuration... ");
788
	update_output_window($static_output);
789
	write_config($changedesc);
790
	log_error(sprintf(gettext("Successfully installed package: %s."), $pkg_info['name']));
791
	$static_output .= gettext("done.") . "\n";
792
	update_output_window($static_output);
793
	if ($pkg_info['after_install_info']) {
794
		update_output_window($pkg_info['after_install_info']);
795
	}
796

    
797
	return true;
798
}
799

    
800
function delete_package($package_name) {
801
	global $config, $g, $static_output;
802

    
803
	if (!is_package_installed($package_name)) {
804
		return;
805
	}
806

    
807
	$static_output .= sprintf(gettext("Starting package deletion for %s..."), $package_name);
808
	update_output_window($static_output);
809

    
810
	pkg_delete($package_name);
811
	$static_output .= "done.\n";
812
	update_output_window($static_output);
813

    
814
	return;
815
}
816

    
817
function delete_package_xml($package_name, $when = "post-deinstall") {
818
	global $g, $config, $static_output, $pkg_interface;
819

    
820
	conf_mount_rw();
821

    
822
	$pkgid = get_package_id($package_name);
823
	if ($pkgid == -1) {
824
		$static_output .= sprintf(gettext("The %s package is not installed.%sDeletion aborted."), $package_name, "\n\n");
825
		update_output_window($static_output);
826
		if ($pkg_interface <> "console") {
827
			echo "\n<script>document.getElementById('progressbar').style.visibility='hidden';</script>";
828
			echo "\n<script>document.getElementById('progholder').style.visibility='hidden';</script>";
829
		}
830
		ob_flush();
831
		sleep(1);
832
		conf_mount_ro();
833
		return;
834
	}
835
	pkg_debug(sprintf(gettext("Removing %s package... "), $package_name));
836
	$static_output .= sprintf(gettext("Removing %s components..."), $package_name) . "\n";
837
	update_output_window($static_output);
838
	/* parse package configuration */
839
	$packages = &$config['installedpackages']['package'];
840
	$menus =& $config['installedpackages']['menu'];
841
	$services = &$config['installedpackages']['service'];
842
	$pkg_info =& $packages[$pkgid];
843
	if (file_exists("/usr/local/pkg/" . $pkg_info['configurationfile'])) {
844
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $packages[$pkgid]['configurationfile'], "packagegui");
845
		/* remove menu items */
846
		if (is_array($pkg_config['menu'])) {
847
			$static_output .= gettext("Menu items... ");
848
			update_output_window($static_output);
849
			if (is_array($pkg_config['menu']) && is_array($menus)) {
850
				foreach ($pkg_config['menu'] as $menu) {
851
					foreach ($menus as $key => $instmenu) {
852
						if ($instmenu['name'] == $menu['name']) {
853
							unset($menus[$key]);
854
							break;
855
						}
856
					}
857
				}
858
			}
859
			$static_output .= gettext("done.") . "\n";
860
			update_output_window($static_output);
861
		}
862
		/* remove services */
863
		if (is_array($pkg_config['service'])) {
864
			$static_output .= gettext("Services... ");
865
			update_output_window($static_output);
866
			if (is_array($pkg_config['service']) && is_array($services)) {
867
				foreach ($pkg_config['service'] as $service) {
868
					foreach ($services as $key => $instservice) {
869
						if ($instservice['name'] == $service['name']) {
870
							if (platform_booting() != true) {
871
								stop_service($service['name']);
872
							}
873
							if ($service['rcfile']) {
874
								$prefix = RCFILEPREFIX;
875
								if (!empty($service['prefix'])) {
876
									$prefix = $service['prefix'];
877
								}
878
								if (file_exists("{$prefix}{$service['rcfile']}")) {
879
									@unlink("{$prefix}{$service['rcfile']}");
880
								}
881
							}
882
							unset($services[$key]);
883
						}
884
					}
885
				}
886
			}
887
			$static_output .= gettext("done.") . "\n";
888
			update_output_window($static_output);
889
		}
890
		/*
891
		 * XXX: Otherwise inclusion of config.inc again invalidates actions taken.
892
		 *	Same is done during installation.
893
		 */
894
		write_config("Intermediate config write during package removal for {$package_name}.");
895

    
896
		/*
897
		 * If a require exists, include it.	 this will
898
		 * show us where an error exists in a package
899
		 * instead of making us blindly guess
900
		 */
901
		$missing_include = false;
902
		if ($pkg_config['include_file'] <> "") {
903
			$static_output .= gettext("Loading package instructions...") . "\n";
904
			update_output_window($static_output);
905
			if (file_exists($pkg_config['include_file'])) {
906
				pkg_debug("require_once(\"{$pkg_config['include_file']}\")\n");
907
				require_once($pkg_config['include_file']);
908
			} else {
909
				pkg_debug("Missing include {$pkg_config['include_file']}\n");
910
				$missing_include = true;
911
				update_output_window($static_output);
912
				$static_output .= "Include file " . basename($pkg_config['include_file']) . " could not be found for inclusion.\n";
913
			}
914
		}
915
		/* ermal
916
		 * NOTE: It is not possible to handle parse errors on eval.
917
		 * So we prevent it from being run at all to not interrupt all the other code.
918
		 */
919
		if ($when == "deinstall" && $missing_include == false) {
920
			/* evaluate this package's global functions and pre deinstall commands */
921
			if ($pkg_config['custom_php_global_functions'] <> "") {
922
				eval_once($pkg_config['custom_php_global_functions']);
923
			}
924
			if ($pkg_config['custom_php_pre_deinstall_command'] <> "") {
925
				eval_once($pkg_config['custom_php_pre_deinstall_command']);
926
			}
927
		}
928
		/* deinstall commands */
929
		if ($when == "post-deinstall" && $pkg_config['custom_php_deinstall_command'] <> "") {
930
			$static_output .= gettext("Deinstall commands... ");
931
			update_output_window($static_output);
932
			if ($missing_include == false) {
933
				eval_once($pkg_config['custom_php_deinstall_command']);
934
				$static_output .= gettext("done.") . "\n";
935
			} else {
936
				$static_output .= "\nNot executing custom deinstall hook because an include is missing.\n";
937
			}
938
			update_output_window($static_output);
939
		}
940
	}
941
	/* syslog */
942
	$need_syslog_restart = false;
943
	if (is_array($pkg_info['logging']) && $pkg_info['logging']['logfilename'] <> "") {
944
		$static_output .= "Syslog entries... ";
945
		update_output_window($static_output);
946
		@unlink("{$g['varlog_path']}/{$pkg_info['logging']['logfilename']}");
947
		$static_output .= "done.\n";
948
		update_output_window($static_output);
949
		$need_syslog_restart = true;
950
	}
951

    
952
	/* remove config.xml entries */
953
	$static_output .= gettext("Configuration... ");
954
	update_output_window($static_output);
955
	unset($config['installedpackages']['package'][$pkgid]);
956
	$static_output .= gettext("done.") . "\n";
957
	update_output_window($static_output);
958
	write_config("Removed {$package_name} package.\n");
959

    
960
	/* remove package entry from /etc/syslog.conf if needed */
961
	/* this must be done after removing the entries from config.xml */
962
	if ($need_syslog_restart) {
963
		system_syslogd_start();
964
	}
965

    
966
	conf_mount_ro();
967
}
968

    
969
function pkg_reinstall_all() {
970
	global $g, $config;
971

    
972
	// XXX: implement
973
	return;
974
}
975

    
976
function stop_packages() {
977
	require_once("config.inc");
978
	require_once("functions.inc");
979
	require_once("filter.inc");
980
	require_once("shaper.inc");
981
	require_once("captiveportal.inc");
982
	require_once("pkg-utils.inc");
983
	require_once("pfsense-utils.inc");
984
	require_once("service-utils.inc");
985

    
986
	global $config, $g;
987

    
988
	log_error("Stopping all packages.");
989

    
990
	$rcfiles = glob(RCFILEPREFIX . "*.sh");
991
	if (!$rcfiles) {
992
		$rcfiles = array();
993
	} else {
994
		$rcfiles = array_flip($rcfiles);
995
		if (!$rcfiles) {
996
			$rcfiles = array();
997
		}
998
	}
999

    
1000
	if (is_array($config['installedpackages']['package'])) {
1001
		foreach ($config['installedpackages']['package'] as $package) {
1002
			echo " Stopping package {$package['name']}...";
1003
			$internal_name = get_package_internal_name($package);
1004
			stop_service($internal_name);
1005
			unset($rcfiles[RCFILEPREFIX . strtolower($internal_name) . ".sh"]);
1006
			echo "done.\n";
1007
		}
1008
	}
1009

    
1010
	foreach ($rcfiles as $rcfile => $number) {
1011
		$shell = @popen("/bin/sh", "w");
1012
		if ($shell) {
1013
			echo " Stopping {$rcfile}...";
1014
			if (!@fwrite($shell, "{$rcfile} stop >>/tmp/bootup_messages 2>&1")) {
1015
				if ($shell) {
1016
					pclose($shell);
1017
				}
1018
				$shell = @popen("/bin/sh", "w");
1019
			}
1020
			echo "done.\n";
1021
			pclose($shell);
1022
		}
1023
	}
1024
}
1025

    
1026
function verify_all_package_servers() {
1027
	// XXX: Remove it after GUI is ready
1028
	return true;
1029
}
1030

    
1031
function check_package_server_ssl() {
1032
	// XXX: Remove it after GUI is ready
1033
	return true;
1034
}
1035

    
1036
?>
(41-41/67)