Project

General

Profile

Download (28 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
	Copyright (C) 2010 Ermal Luçi
11
	Copyright (C) 2005-2006 Colin Smith (ethethlay@gmail.com)
12
	All rights reserved.
13
	Redistribution and use in source and binary forms, with or without
14
	modification, are permitted provided that the following conditions are met:
15

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

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

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

    
34
 */
35

    
36
/*
37
	pfSense_BUILDER_BINARIES:	/usr/bin/cd	/usr/bin/tar	/usr/sbin/fifolog_create	/bin/chmod
38
	pfSense_BUILDER_BINARIES:	/usr/sbin/pkg_add	/usr/sbin/pkg_info	/usr/sbin/pkg_delete	/bin/rm
39
	pfSense_MODULE:	pkg
40
*/
41

    
42
require_once("globals.inc");
43
require_once("service-utils.inc");
44

    
45
if (file_exists("/cf/conf/use_xmlreader")) {
46
	require_once("xmlreader.inc");
47
} else {
48
	require_once("xmlparse.inc");
49
}
50

    
51
require_once("pfsense-utils.inc");
52

    
53
if (!function_exists("pkg_debug")) {
54
	/* set up logging if needed */
55
	function pkg_debug($msg) {
56
		global $g, $debug, $fd_log;
57

    
58
		if (!$debug) {
59
			return;
60
		}
61

    
62
		if (!$fd_log) {
63
			if (!$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_debug.log", "w")) {
64
				update_output_window("Warning, could not open log for writing.");
65
			}
66
		}
67
		@fwrite($fd_log, $msg);
68
	}
69
}
70

    
71
global $g;
72
if (!isset($g['platform'])) {
73
	$g['platform'] = trim(file_get_contents("/etc/platform"));
74
}
75

    
76
/* Remove pkg_prefix from package name if it's present */
77
function pkg_remove_prefix(&$pkg_name) {
78
	global $g;
79

    
80
	if (substr($pkg_name, 0, strlen($g['pkg_prefix'])) == $g['pkg_prefix']) {
81
		$pkg_name = substr($pkg_name, strlen($g['pkg_prefix']));
82
	}
83
}
84

    
85
/* Execute a pkg call */
86
function pkg_call($params, $mute = false) {
87
	global $static_output, $g, $config;
88

    
89
	if (empty($params)) {
90
		return false;
91
	}
92

    
93
	$user_agent = $g['product_name'] . '/' . $g['product_version'];
94
	if (!isset($config['system']['host_uuid'])) {
95
		$user_agent .= ' : ' . get_single_sysctl('kern.hostuuid');
96
	}
97

    
98
	$env = array(
99
		"HTTP_USER_AGENT" => $user_agent,
100
		"ASSUME_ALWAYS_YES" => "true"
101
	);
102

    
103
	$debug_fifo = $g['tmp_path'] . "/pkg-debug.fifo";
104
	if (!file_exists($debug_fifo)) {
105
		posix_mkfifo($debug_fifo, 0600);
106
	}
107

    
108
	if (filetype($debug_fifo) == 'fifo') {
109
		$env["EVENT_PIPE"] = $debug_fifo;
110
	}
111

    
112
	$descriptorspec = array(
113
		1 => array("pipe", "w"), /* stdout */
114
		2 => array("pipe", "w")  /* stderr */
115
	);
116

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

    
120
	if (!is_resource($process)) {
121
		return false;
122
	}
123

    
124
	stream_set_blocking($pipes[1], 0);
125
	stream_set_blocking($pipes[2], 0);
126

    
127
	/* XXX: should be a tunnable? */
128
	$timeout = 300; // seconds
129
	$error_log = '';
130

    
131
	do {
132
		$write = array();
133
		$read = array($pipes[1], $pipes[2]);
134
		$except = array();
135

    
136
		$stream = stream_select($read, $write, $except, null, $timeout);
137
		if ($stream !== FALSE && $stream > 0) {
138
			foreach ($read as $pipe) {
139
				$content = stream_get_contents($pipe);
140
				if ($content == '') {
141
					continue;
142
				}
143
				if ($pipe === $pipes[1]) {
144
					if (!$mute) {
145
						$static_output .= $content;
146
						update_output_window($static_output);
147
					}
148
					flush();
149
				} else if ($pipe === $pipes[2]) {
150
					$error_log .= $content;
151
				}
152
			}
153
		}
154
		$status = proc_get_status($process);
155
	} while ($status['running']);
156
	fclose($pipes[1]);
157
	fclose($pipes[2]);
158
	proc_close($process);
159

    
160
	$rc = $status['exitcode'];
161

    
162
	pkg_debug("pkg_call(): rc = {$rc}\n");
163
	if ($rc == 0) {
164
		return true;
165
	}
166

    
167
	pkg_debug("pkg_call(): error_log\n{$error_log}\n");
168
	if (!$mute) {
169
		$static_output .= "\n\n" . sprintf(gettext("ERROR!!! An error occurred on pkg execution (rc = %d) with parameters '%s':"), $rc, $params) . "\n" . $error_log;
170
		update_output_window($static_output);
171
	}
172
	return false;
173
}
174

    
175
/* Execute pkg with $params, fill stdout and stderr and return pkg rc */
176
function pkg_exec($params, &$stdout, &$stderr) {
177
	global $g, $config;
178

    
179
	if (empty($params)) {
180
		return -1;
181
	}
182

    
183
	$user_agent = $g['product_name'] . '/' . $g['product_version'];
184
	if (!isset($config['system']['host_uuid'])) {
185
		$user_agent .= ' : ' . get_single_sysctl('kern.hostuuid');
186
	}
187

    
188
	$env = array(
189
		"HTTP_USER_AGENT" => $user_agent,
190
		"ASSUME_ALWAYS_YES" => "true"
191
	);
192

    
193
	$debug_fifo = $g['tmp_path'] . "/pkg-debug.fifo";
194
	if (!file_exists($debug_fifo)) {
195
		posix_mkfifo($debug_fifo, 0600);
196
	}
197

    
198
	if (filetype($debug_fifo) == 'fifo') {
199
		$env["EVENT_PIPE"] = $debug_fifo;
200
	}
201

    
202
	$descriptorspec = array(
203
		1 => array("pipe", "w"), /* stdout */
204
		2 => array("pipe", "w")  /* stderr */
205
	);
206

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

    
210
	if (!is_resource($process)) {
211
		return -1;
212
	}
213

    
214
	$stdout = '';
215
	while (($l = fgets($pipes[1])) !== FALSE) {
216
		$stdout .= $l;
217
	}
218
	fclose($pipes[1]);
219

    
220
	$stderr = '';
221
	while (($l = fgets($pipes[2])) !== FALSE) {
222
		$stderr .= $l;
223
	}
224
	fclose($pipes[2]);
225

    
226
	return proc_close($process);
227
}
228

    
229
/* Check if package is installed */
230
function is_pkg_installed($pkg_name) {
231
	global $g;
232

    
233
	pkg_remove_prefix($pkg_name);
234

    
235
	return pkg_call("info -e " . $g['pkg_prefix'] . $pkg_name, true);
236
}
237

    
238
/* Install package, $pkg_name should not contain prefix */
239
function pkg_install($pkg_name) {
240
	global $g;
241
	$result = false;
242

    
243
	pkg_remove_prefix($pkg_name);
244

    
245
	pkg_debug("Installing package {$pkg_name}\n");
246
	if (!is_pkg_installed($pkg_name)) {
247
		$result = pkg_call("install -y " . $g['pkg_prefix'] . $pkg_name);
248
		/* Cleanup cacke to free disk space */
249
		pkg_call("clean -y");
250
	}
251

    
252
	return $result;
253
}
254

    
255
/* Delete package from FreeBSD, $pkg_name should not contain prefix */
256
function pkg_delete($pkg_name) {
257
	global $g;
258

    
259
	pkg_remove_prefix($pkg_name);
260

    
261
	pkg_debug("Removing package {$pkg_name}\n");
262
	if (is_pkg_installed($pkg_name)) {
263
		pkg_call("delete -y " . $g['pkg_prefix'] . $pkg_name);
264
		/* Cleanup unecessary dependencies */
265
		pkg_call("autoremove -y");
266
	}
267
}
268

    
269
/* Check if package is present in config.xml */
270
function is_package_installed($package_name) {
271
	return (get_package_id($package_name) != -1);
272
}
273

    
274
/* Find package array index */
275
function get_package_id($package_name) {
276
	global $config;
277

    
278
	if (!is_array($config['installedpackages']['package'])) {
279
		return -1;
280
	}
281

    
282
	foreach ($config['installedpackages']['package'] as $idx => $pkg) {
283
		if ($pkg['name'] == $package_name) {
284
			return $idx;
285
		}
286
	}
287

    
288
	return -1;
289
}
290

    
291
/* Keep backward compatibility since snort/suricata use this function */
292
function get_pkg_id($package_name) {
293
	return get_package_id($package_name);
294
}
295

    
296
/* Return internal_name when it's defined, otherwise, returns name */
297
function get_package_internal_name($package_data) {
298
	if (isset($package_data['internal_name']) && ($package_data['internal_name'] != "")) {
299
		/* e.g. name is Ipguard-dev, internal name is ipguard */
300
		return $package_data['internal_name'];
301
	} else {
302
		return $package_data['name'];
303
	}
304
}
305

    
306
/* Get information about packages */
307
function get_pkg_info($pkgs = 'all', $info = 'all') {
308
	global $g, $static_output;
309

    
310
	$out = '';
311
	$err = '';
312

    
313
	if ($pkgs == 'all') {
314
		$pkgs = $g['pkg_prefix'];
315
	}
316

    
317
	/* Make sure repo metadata is up2date */
318
	$static_output .= "\n" . gettext("Updating package repository metadada...") . "\n";
319
	update_status($static_output);
320
	if (!pkg_call("update")) {
321
		$static_output .= "\n" . gettext("ERROR: An error occurred when updating packages repository. Aborting...") . "\n";
322
		update_status($static_output);
323
		return array();
324
	}
325

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

    
328
	if ($rc != 0) {
329
		$static_output .= "\n" . gettext("ERROR: Error trying to get packages list. Aborting...") . "\n";
330
		$static_output .= $err;
331
		update_status($static_output);
332
		return array();
333
	}
334

    
335
	$result = array();
336
	$pkgs_info = explode("\n", $out);
337
	foreach ($pkgs_info as $pkg_info_json) {
338
		$pkg_info = json_decode($pkg_info_json, true);
339
		if (!isset($pkg_info['name'])) {
340
			continue;
341
		}
342

    
343
		$result[] = $pkg_info;
344
		unset($pkg_info);
345
	}
346

    
347
	return $result;
348
}
349

    
350
/*
351
 * resync_all_package_configs() Force packages to setup their configuration and rc.d files.
352
 * This function may also print output to the terminal indicating progress.
353
 */
354
function resync_all_package_configs($show_message = false) {
355
	global $config, $pkg_interface, $g;
356

    
357
	log_error(gettext("Resyncing configuration for all packages."));
358

    
359
	if (!is_array($config['installedpackages']['package'])) {
360
		return;
361
	}
362

    
363
	if ($show_message == true) {
364
		echo "Syncing packages:";
365
	}
366

    
367
	conf_mount_rw();
368

    
369
	foreach ($config['installedpackages']['package'] as $idx => $package) {
370
		if (empty($package['name'])) {
371
			continue;
372
		}
373
		if ($show_message == true) {
374
			echo " " . $package['name'];
375
		}
376
		if (platform_booting() != true) {
377
			stop_service(get_package_internal_name($package));
378
		}
379
		sync_package($package['name']);
380
		if ($pkg_interface == "console") {
381
			echo "\n" . gettext("Syncing packages:");
382
		}
383
	}
384

    
385
	if ($show_message == true) {
386
		echo " done.\n";
387
	}
388

    
389
	@unlink("/conf/needs_package_sync");
390
	conf_mount_ro();
391
}
392

    
393
function uninstall_package($package_name) {
394
	global $config, $static_output;
395

    
396
	$internal_name = $package_name;
397
	$id = get_package_id($package_name);
398
	if ($id >= 0) {
399
		$internal_name = get_package_internal_name($config['installedpackages']['package'][$id]);
400
		stop_service($internal_name);
401
	}
402

    
403
	if (is_pkg_installed($internal_name)) {
404
		$static_output .= "Removing package...\n";
405
		update_output_window($static_output);
406
		pkg_delete($internal_name);
407
	} else {
408
		delete_package_xml($package_name);
409
	}
410

    
411
	$static_output .= gettext("done.") . "\n";
412
	update_output_window($static_output);
413
}
414

    
415
/* Run <custom_php_resync_config_command> */
416
function sync_package($package_name) {
417
	global $config, $builder_package_install;
418

    
419
	// If this code is being called by pfspkg_installer
420
	// which the builder system uses then return (ignore).
421
	if ($builder_package_install) {
422
		return;
423
	}
424

    
425
	if (empty($config['installedpackages']['package'])) {
426
		return;
427
	}
428

    
429
	if (($pkg_id = get_package_id($package_name)) == -1) {
430
		return; // This package doesn't really exist - exit the function.
431
	}
432

    
433
	if (!is_array($config['installedpackages']['package'][$pkg_id])) {
434
		return;  // No package belongs to the pkg_id passed to this function.
435
	}
436

    
437
	$package =& $config['installedpackages']['package'][$pkg_id];
438
	if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
439
		log_error(sprintf(gettext("The %s package is missing its configuration file and must be reinstalled."), $package['name']));
440
		delete_package_xml($package['name']);
441
		return;
442
	}
443

    
444
	$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
445
	if (isset($pkg_config['nosync'])) {
446
		return;
447
	}
448

    
449
	/* Bring in package include files */
450
	if (!empty($pkg_config['include_file'])) {
451
		$include_file = $pkg_config['include_file'];
452
		if (file_exists($include_file)) {
453
			require_once($include_file);
454
		} else {
455
			log_error("Reinstalling package {$package['name']} because its include file({$include_file}) is missing!");
456
			uninstall_package($package['name']);
457
			if (install_package($package['name']) != 0) {
458
				log_error("Reinstalling package {$package['name']} failed. Take appropriate measures!!!");
459
				return;
460
			}
461
			if (file_exists($include_file)) {
462
				require_once($include_file);
463
			} else {
464
				return;
465
			}
466
		}
467
	}
468

    
469
	if (!empty($pkg_config['custom_php_global_functions'])) {
470
		eval($pkg_config['custom_php_global_functions']);
471
	}
472
	if (!empty($pkg_config['custom_php_resync_config_command'])) {
473
		eval($pkg_config['custom_php_resync_config_command']);
474
	}
475
}
476

    
477
/* Read info.xml installed by package and return an array */
478
function read_package_config($package_name) {
479
	global $g;
480

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

    
483
	if (!file_exists($pkg_info_xml)) {
484
		return false;
485
	}
486

    
487
	$pkg_info = parse_xml_config_pkg($pkg_info_xml, 'pfsensepkgs');
488

    
489
	if (empty($pkg_info)) {
490
		return false;
491
	}
492

    
493
	/* it always returns an array with 1 item */
494
	return $pkg_info['package'][0];
495
}
496

    
497
function get_after_install_info($package_name) {
498
	$pkg_config = read_package_config($package_name);
499

    
500
	if (isset($pkg_config['after_install_info'])) {
501
		return $pkg_config['after_install_info'];
502
	}
503

    
504
	return '';
505
}
506

    
507
function eval_once($toeval) {
508
	global $evaled;
509
	if (!$evaled) {
510
		$evaled = array();
511
	}
512
	$evalmd5 = md5($toeval);
513
	if (!in_array($evalmd5, $evaled)) {
514
		@eval($toeval);
515
		$evaled[] = $evalmd5;
516
	}
517
	return;
518
}
519

    
520
function install_package($package_name) {
521
	global $g, $config, $static_output, $pkg_interface;
522

    
523
	if ($pkg_interface == "console") {
524
		echo "\n";
525
	}
526

    
527
	return pkg_install($package_name);
528
}
529

    
530
function install_package_xml($package_name) {
531
	global $g, $config, $static_output, $pkg_interface;
532

    
533
	if ($pkg_interface == "console") {
534
		echo "\n";
535
	}
536

    
537
	if (($pkg_info = read_package_config($package_name)) == false) {
538
		return false;
539
	}
540

    
541
	/* safe side. Write config below will send to ro again. */
542
	conf_mount_rw();
543

    
544
	pkg_debug(gettext("Beginning package installation.") . "\n");
545
	log_error(sprintf(gettext('Beginning package installation for %s .'), $pkg_info['name']));
546
	$static_output .= sprintf(gettext("Beginning package installation for %s .\n"), $pkg_info['name']);
547
	update_status($static_output);
548

    
549
	/* add package information to config.xml */
550
	$pkgid = get_package_id($pkg_info['name']);
551
	$static_output .= gettext("Saving updated package information...") . " ";
552
	update_output_window($static_output);
553
	if ($pkgid == -1) {
554
		$config['installedpackages']['package'][] = $pkg_info;
555
		$changedesc = sprintf(gettext("Installed %s package."), $pkg_info['name']);
556
		$to_output = gettext("done.") . "\n";
557
	} else {
558
		$config['installedpackages']['package'][$pkgid] = $pkg_info;
559
		$changedesc = sprintf(gettext("Overwrote previous installation of %s."), $pkg_info['name']);
560
		$to_output = gettext("overwrite!") . "\n";
561
	}
562
	unlink_if_exists('/conf/needs_package_sync');
563
	conf_mount_ro();
564
	write_config("Intermediate config write during package install for {$pkg_info['name']}.");
565
	$static_output .= $to_output;
566
	update_output_window($static_output);
567

    
568
	if (($pkgid = get_package_id($package_name)) == -1) {
569
		$static_output .= sprintf(gettext("The %s package is not installed.%sInstallation aborted."), $package_name, "\n\n");
570
		update_output_window($static_output);
571
		if ($pkg_interface <> "console") {
572
			echo "\n<script>document.getElementById('progressbar').style.visibility='hidden';</script>";
573
			echo "\n<script>document.getElementById('progholder').style.visibility='hidden';</script>";
574
		}
575

    
576
		uninstall_package($package_name);
577
		write_config($changedesc);
578
		log_error(sprintf(gettext("Failed to install package: %s."), $pkg_info['name']));
579
		$static_output .= gettext("Failed to install package.") . "\n";
580
		update_output_window($static_output);
581
		return false;
582
	}
583

    
584
	$configfile = substr(strrchr($pkg_info['config_file'], '/'), 1);
585
	if (file_exists("/usr/local/pkg/" . $configfile)) {
586
		$static_output .= gettext("Loading package configuration... ");
587
		update_output_window($static_output);
588
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $configfile, "packagegui");
589
		$static_output .= gettext("done.") . "\n";
590
		update_output_window($static_output);
591
		$static_output .= gettext("Configuring package components...\n");
592
		if (!empty($pkg_config['filter_rules_needed'])) {
593
			$config['installedpackages']['package'][$pkgid]['filter_rule_function'] = $pkg_config['filter_rules_needed'];
594
		}
595
		update_output_window($static_output);
596
		/* modify system files */
597

    
598
		/*   if a require exists, include it.  this will
599
		 *   show us where an error exists in a package
600
		 *   instead of making us blindly guess
601
		 */
602
		$missing_include = false;
603
		if ($pkg_config['include_file'] <> "") {
604
			$static_output .= gettext("Loading package instructions...") . "\n";
605
			update_output_window($static_output);
606
			if (file_exists($pkg_config['include_file'])) {
607
				pkg_debug("require_once('{$pkg_config['include_file']}')\n");
608
				require_once($pkg_config['include_file']);
609
			} else {
610
				pkg_debug("Missing include {$pkg_config['include_file']}\n");
611
				$missing_include = true;
612
				$static_output .= "Include " . basename($pkg_config['include_file']) . " is missing!\n";
613
				update_output_window($static_output);
614

    
615
				uninstall_package($package_name);
616
				write_config($changedesc);
617
				log_error(sprintf(gettext("Failed to install package: %s."), $pkg_info['name']));
618
				$static_output .= gettext("Failed to install package.") . "\n";
619
				update_output_window($static_output);
620
				return false;
621
			}
622
		}
623

    
624
		/* custom commands */
625
		$static_output .= gettext("Custom commands...") . "\n";
626
		update_output_window($static_output);
627
		if ($missing_include == false) {
628
			if ($pkg_config['custom_php_global_functions'] <> "") {
629
				$static_output .= gettext("Executing custom_php_global_functions()...");
630
				update_output_window($static_output);
631
				eval_once($pkg_config['custom_php_global_functions']);
632
				$static_output .= gettext("done.") . "\n";
633
				update_output_window($static_output);
634
			}
635
			if ($pkg_config['custom_php_install_command']) {
636
				$static_output .= gettext("Executing custom_php_install_command()...");
637
				update_output_window($static_output);
638
				eval_once($pkg_config['custom_php_install_command']);
639
				$static_output .= gettext("done.") . "\n";
640
				update_output_window($static_output);
641
			}
642
			if ($pkg_config['custom_php_resync_config_command'] <> "") {
643
				$static_output .= gettext("Executing custom_php_resync_config_command()...");
644
				update_output_window($static_output);
645
				eval_once($pkg_config['custom_php_resync_config_command']);
646
				$static_output .= gettext("done.") . "\n";
647
				update_output_window($static_output);
648
			}
649
		}
650
		/* sidebar items */
651
		if (is_array($pkg_config['menu'])) {
652
			$static_output .= gettext("Menu items... ");
653
			update_output_window($static_output);
654
			foreach ($pkg_config['menu'] as $menu) {
655
				if (is_array($config['installedpackages']['menu'])) {
656
					foreach ($config['installedpackages']['menu'] as $amenu) {
657
						if ($amenu['name'] == $menu['name']) {
658
							continue 2;
659
						}
660
					}
661
				} else {
662
					$config['installedpackages']['menu'] = array();
663
				}
664
				$config['installedpackages']['menu'][] = $menu;
665
			}
666
			$static_output .= gettext("done.") . "\n";
667
			update_output_window($static_output);
668
		}
669
		/* services */
670
		if (is_array($pkg_config['service'])) {
671
			$static_output .= gettext("Services... ");
672
			update_output_window($static_output);
673
			foreach ($pkg_config['service'] as $service) {
674
				if (is_array($config['installedpackages']['service'])) {
675
					foreach ($config['installedpackages']['service'] as $aservice) {
676
						if ($aservice['name'] == $service['name']) {
677
							continue 2;
678
						}
679
					}
680
				} else {
681
					$config['installedpackages']['service'] = array();
682
				}
683
				$config['installedpackages']['service'][] = $service;
684
			}
685
			$static_output .= gettext("done.") . "\n";
686
			update_output_window($static_output);
687
		}
688
	} else {
689
		pkg_debug("Unable to find config file\n");
690
		$static_output .= gettext("Loading package configuration... failed!") . "\n\n" . gettext("Installation aborted.");
691
		update_output_window($static_output);
692
		pkg_debug(gettext("Unable to load package configuration. Installation aborted.") ."\n");
693
		if ($pkg_interface <> "console") {
694
			echo "\n<script>document.getElementById('progressbar').style.visibility='hidden';</script>";
695
			echo "\n<script>document.getElementById('progholder').style.visibility='hidden';</script>";
696
		}
697

    
698
		uninstall_package($package_name);
699
		write_config($changedesc);
700
		log_error(sprintf(gettext("Failed to install package: %s."), $pkg_info['name']));
701
		$static_output .= gettext("Failed to install package.") . "\n";
702
		update_output_window($static_output);
703
		return false;
704
	}
705

    
706
	/* set up package logging streams */
707
	if ($pkg_info['logging']) {
708
		system_syslogd_start();
709
	}
710

    
711
	$static_output .= gettext("Writing configuration... ");
712
	update_output_window($static_output);
713
	write_config($changedesc);
714
	log_error(sprintf(gettext("Successfully installed package: %s."), $pkg_info['name']));
715
	$static_output .= gettext("done.") . "\n";
716
	update_output_window($static_output);
717
	if ($pkg_info['after_install_info']) {
718
		update_output_window($pkg_info['after_install_info']);
719
	}
720

    
721
	return true;
722
}
723

    
724
function delete_package($package_name) {
725
	global $config, $g, $static_output;
726

    
727
	if (!is_package_installed($package_name)) {
728
		return;
729
	}
730

    
731
	$static_output .= sprintf(gettext("Starting package deletion for %s..."), $package_name);
732
	update_output_window($static_output);
733

    
734
	pkg_delete($package_name);
735
	$static_output .= "done.\n";
736
	update_output_window($static_output);
737

    
738
	return;
739
}
740

    
741
function delete_package_xml($package_name, $when = "post-deinstall") {
742
	global $g, $config, $static_output, $pkg_interface;
743

    
744
	conf_mount_rw();
745

    
746
	$pkgid = get_package_id($package_name);
747
	if ($pkgid == -1) {
748
		$static_output .= sprintf(gettext("The %s package is not installed.%sDeletion aborted."), $package_name, "\n\n");
749
		update_output_window($static_output);
750
		if ($pkg_interface <> "console") {
751
			echo "\n<script>document.getElementById('progressbar').style.visibility='hidden';</script>";
752
			echo "\n<script>document.getElementById('progholder').style.visibility='hidden';</script>";
753
		}
754
		ob_flush();
755
		sleep(1);
756
		conf_mount_ro();
757
		return;
758
	}
759
	pkg_debug(sprintf(gettext("Removing %s package... "), $package_name));
760
	$static_output .= sprintf(gettext("Removing %s components..."), $package_name) . "\n";
761
	update_output_window($static_output);
762
	/* parse package configuration */
763
	$packages = &$config['installedpackages']['package'];
764
	$menus =& $config['installedpackages']['menu'];
765
	$services = &$config['installedpackages']['service'];
766
	$pkg_info =& $packages[$pkgid];
767
	if (file_exists("/usr/local/pkg/" . $pkg_info['configurationfile'])) {
768
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $packages[$pkgid]['configurationfile'], "packagegui");
769
		/* remove menu items */
770
		if (is_array($pkg_config['menu'])) {
771
			$static_output .= gettext("Menu items... ");
772
			update_output_window($static_output);
773
			if (is_array($pkg_config['menu']) && is_array($menus)) {
774
				foreach ($pkg_config['menu'] as $menu) {
775
					foreach ($menus as $key => $instmenu) {
776
						if ($instmenu['name'] == $menu['name']) {
777
							unset($menus[$key]);
778
							break;
779
						}
780
					}
781
				}
782
			}
783
			$static_output .= gettext("done.") . "\n";
784
			update_output_window($static_output);
785
		}
786
		/* remove services */
787
		if (is_array($pkg_config['service'])) {
788
			$static_output .= gettext("Services... ");
789
			update_output_window($static_output);
790
			if (is_array($pkg_config['service']) && is_array($services)) {
791
				foreach ($pkg_config['service'] as $service) {
792
					foreach ($services as $key => $instservice) {
793
						if ($instservice['name'] == $service['name']) {
794
							if (platform_booting() != true) {
795
								stop_service($service['name']);
796
							}
797
							if ($service['rcfile']) {
798
								$prefix = RCFILEPREFIX;
799
								if (!empty($service['prefix'])) {
800
									$prefix = $service['prefix'];
801
								}
802
								if (file_exists("{$prefix}{$service['rcfile']}")) {
803
									@unlink("{$prefix}{$service['rcfile']}");
804
								}
805
							}
806
							unset($services[$key]);
807
						}
808
					}
809
				}
810
			}
811
			$static_output .= gettext("done.") . "\n";
812
			update_output_window($static_output);
813
		}
814
		/*
815
		 * XXX: Otherwise inclusion of config.inc again invalidates actions taken.
816
		 * 	Same is done during installation.
817
		 */
818
		write_config("Intermediate config write during package removal for {$package_name}.");
819

    
820
		/*
821
		 * If a require exists, include it.  this will
822
		 * show us where an error exists in a package
823
		 * instead of making us blindly guess
824
		 */
825
		$missing_include = false;
826
		if ($pkg_config['include_file'] <> "") {
827
			$static_output .= gettext("Loading package instructions...") . "\n";
828
			update_output_window($static_output);
829
			if (file_exists($pkg_config['include_file'])) {
830
				pkg_debug("require_once(\"{$pkg_config['include_file']}\")\n");
831
				require_once($pkg_config['include_file']);
832
			} else {
833
				pkg_debug("Missing include {$pkg_config['include_file']}\n");
834
				$missing_include = true;
835
				update_output_window($static_output);
836
				$static_output .= "Include file " . basename($pkg_config['include_file']) . " could not be found for inclusion.\n";
837
			}
838
		}
839
		/* ermal
840
		 * NOTE: It is not possible to handle parse errors on eval.
841
		 * So we prevent it from being run at all to not interrupt all the other code.
842
		 */
843
		if ($when == "deinstall" && $missing_include == false) {
844
			/* evaluate this package's global functions and pre deinstall commands */
845
			if ($pkg_config['custom_php_global_functions'] <> "") {
846
				eval_once($pkg_config['custom_php_global_functions']);
847
			}
848
			if ($pkg_config['custom_php_pre_deinstall_command'] <> "") {
849
				eval_once($pkg_config['custom_php_pre_deinstall_command']);
850
			}
851
		}
852
		/* deinstall commands */
853
		if ($when == "post-deinstall" && $pkg_config['custom_php_deinstall_command'] <> "") {
854
			$static_output .= gettext("Deinstall commands... ");
855
			update_output_window($static_output);
856
			if ($missing_include == false) {
857
				eval_once($pkg_config['custom_php_deinstall_command']);
858
				$static_output .= gettext("done.") . "\n";
859
			} else {
860
				$static_output .= "\nNot executing custom deinstall hook because an include is missing.\n";
861
			}
862
			update_output_window($static_output);
863
		}
864
	}
865
	/* syslog */
866
	if (is_array($pkg_info['logging']) && $pkg_info['logging']['logfile_name'] <> "") {
867
		$static_output .= "Syslog entries... ";
868
		update_output_window($static_output);
869
		remove_text_from_file("/etc/syslog.conf", $pkg_info['logging']['facilityname'] . "\t\t\t\t" . $pkg_info['logging']['logfilename']);
870
		system_syslogd_start();
871
		@unlink("{$g['varlog_path']}/{$pkg_info['logging']['logfilename']}");
872
		$static_output .= "done.\n";
873
		update_output_window($static_output);
874
	}
875

    
876
	conf_mount_ro();
877
	/* remove config.xml entries */
878
	$static_output .= gettext("Configuration... ");
879
	update_output_window($static_output);
880
	unset($config['installedpackages']['package'][$pkgid]);
881
	$static_output .= gettext("done.") . "\n";
882
	update_output_window($static_output);
883
	write_config("Removed {$package_name} package.\n");
884
}
885

    
886
function pkg_reinstall_all() {
887
	global $g, $config;
888

    
889
	// XXX: implement
890
	return;
891
}
892

    
893
function stop_packages() {
894
	require_once("config.inc");
895
	require_once("functions.inc");
896
	require_once("filter.inc");
897
	require_once("shaper.inc");
898
	require_once("captiveportal.inc");
899
	require_once("pkg-utils.inc");
900
	require_once("pfsense-utils.inc");
901
	require_once("service-utils.inc");
902

    
903
	global $config, $g;
904

    
905
	log_error("Stopping all packages.");
906

    
907
	$rcfiles = glob(RCFILEPREFIX . "*.sh");
908
	if (!$rcfiles) {
909
		$rcfiles = array();
910
	} else {
911
		$rcfiles = array_flip($rcfiles);
912
		if (!$rcfiles) {
913
			$rcfiles = array();
914
		}
915
	}
916

    
917
	if (is_array($config['installedpackages']['package'])) {
918
		foreach ($config['installedpackages']['package'] as $package) {
919
			echo " Stopping package {$package['name']}...";
920
			$internal_name = get_package_internal_name($package);
921
			stop_service($internal_name);
922
			unset($rcfiles[RCFILEPREFIX . strtolower($internal_name) . ".sh"]);
923
			echo "done.\n";
924
		}
925
	}
926

    
927
	foreach ($rcfiles as $rcfile => $number) {
928
		$shell = @popen("/bin/sh", "w");
929
		if ($shell) {
930
			echo " Stopping {$rcfile}...";
931
			if (!@fwrite($shell, "{$rcfile} stop >>/tmp/bootup_messages 2>&1")) {
932
				if ($shell) {
933
					pclose($shell);
934
				}
935
				$shell = @popen("/bin/sh", "w");
936
			}
937
			echo "done.\n";
938
			pclose($shell);
939
		}
940
	}
941
}
942

    
943
function verify_all_package_servers() {
944
	// XXX: Remove it after GUI is ready
945
	return true;
946
}
947

    
948
function check_package_server_ssl() {
949
	// XXX: Remove it after GUI is ready
950
	return true;
951
}
952

    
953
?>
(41-41/68)