Project

General

Profile

Download (37 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) 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
 * RISING 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	/bin/cat	/usr/sbin/fifolog_create	/bin/chmod
38
	pfSense_BUILDER_BINARIES:	/usr/bin/killall	/usr/sbin/pkg_info	/usr/sbin/pkg_delete	/bin/rm	/bin/ls
39
	pfSense_BUILDER_BINARIES:	/sbin/pfctl
40
	pfSense_MODULE:	pkg
41
*/
42

    
43
require_once("xmlrpc.inc");
44
if(file_exists("/cf/conf/use_xmlreader"))
45
	require_once("xmlreader.inc");
46
else
47
	require_once("xmlparse.inc");
48
require_once("service-utils.inc");
49
require_once("pfsense-utils.inc");
50
require_once("globals.inc");
51

    
52
if(!function_exists("update_status")) {
53
	function update_status($status) {
54
		echo $status . "\n";
55
	}
56
}
57
if(!function_exists("update_output_window")) {
58
	function update_output_window($status) {
59
		echo $status . "\n";
60
	}
61
}
62

    
63
safe_mkdir("/var/db/pkg");
64

    
65
$g['platform'] = trim(file_get_contents("/etc/platform"));
66
if($g['platform'] == "pfSense") {
67
	safe_mkdir("/usr/local/pkg");
68
	safe_mkdir("/usr/local/pkg/pf");
69
} else {
70
	if(!is_dir("/usr/local/pkg") or !is_dir("/usr/local/pkg/pf")) {
71
	conf_mount_rw();
72
	safe_mkdir("/usr/local/pkg");
73
	safe_mkdir("/usr/local/pkg/pf");	
74
	conf_mount_ro();
75
	}
76
}
77

    
78
$version = split("-", trim(file_get_contents("/etc/version")));
79
$ver = split("\.", $version[0]);
80
$g['version'] = intval($ver[1]);
81

    
82
/****f* pkg-utils/remove_package
83
 * NAME
84
 *   remove_package - Removes package from FreeBSD if it exists
85
 * INPUTS
86
 *   $packagestring	- name/string to check for
87
 * RESULT
88
 *   none
89
 * NOTES
90
 *   
91
 ******/
92
function remove_freebsd_package($packagestring) {
93
	$todel = substr(reverse_strrchr($packagestring, "."), 0, -1);
94
	exec("echo y | /usr/sbin/pkg_delete -x {$todel}");
95
}
96

    
97
/****f* pkg-utils/is_package_installed
98
 * NAME
99
 *   is_package_installed - Check whether a package is installed.
100
 * INPUTS
101
 *   $packagename	- name of the package to check
102
 * RESULT
103
 *   boolean	- true if the package is installed, false otherwise
104
 * NOTES
105
 *   This function is deprecated - get_pkg_id() can already check for installation.
106
 ******/
107
function is_package_installed($packagename) {
108
	$pkg = get_pkg_id($packagename);
109
	if($pkg == -1) return false;
110
	return true;
111
}
112

    
113
/****f* pkg-utils/get_pkg_id
114
 * NAME
115
 *   get_pkg_id - Find a package's numeric ID.
116
 * INPUTS
117
 *   $pkg_name	- name of the package to check
118
 * RESULT
119
 *   integer    - -1 if package is not found, >-1 otherwise
120
 ******/
121
function get_pkg_id($pkg_name) {
122
	global $config;
123

    
124
	if(is_array($config['installedpackages']['package'])) {
125
		$i = 0;
126
		foreach($config['installedpackages']['package'] as $pkg) {
127
			if($pkg['name'] == $pkg_name) return $i;
128
			$i++;
129
		}
130
	}
131
	return -1;
132
}
133

    
134
/****f* pkg-utils/get_pkg_info
135
 * NAME
136
 *   get_pkg_info - Retrive package information from pfsense.com.
137
 * INPUTS
138
 *   $pkgs - 'all' to retrive all packages, an array containing package names otherwise
139
 *   $info - 'all' to retrive all information, an array containing keys otherwise
140
 * RESULT
141
 *   $raw_versions - Array containing retrieved information, indexed by package name.
142
 ******/
143
function get_pkg_info($pkgs = 'all', $info = 'all') {
144
	global $g;
145
	$freebsd_version = str_replace("\n", "", `uname -r | cut -d'-' -f1 | cut -d'.' -f1`);
146
	$freebsd_machine = str_replace("\n", "", `uname -m`);
147
	$params = array(
148
		"pkg" => $pkgs, 
149
		"info" => $info, 
150
		"freebsd_version" => $freebsd_version,
151
		"freebsd_machine" => $freebsd_machine
152
	);
153
	$resp = call_pfsense_method('pfsense.get_pkgs', $params, 10);
154
	return $resp ? $resp : array();
155
}
156

    
157
function get_pkg_sizes($pkgs = 'all') {
158
	global $g;
159
	$params = array("pkg" => $pkgs);
160
	$msg = new XML_RPC_Message('pfsense.get_pkg_sizes', array(php_value_to_xmlrpc($params)));
161
	$xmlrpc_base_url = isset($config['system']['altpkgrepo']['enable']) ? $config['system']['altpkgrepo']['xmlrpcbaseurl'] : $g['xmlrpcbaseurl'];
162
	$cli = new XML_RPC_Client($g['xmlrpcpath'], $xmlrpc_base_url);
163
	$resp = $cli->send($msg, 10);
164
	if($resp and !$resp->faultCode()) {
165
		$raw_versions = $resp->value();
166
		return xmlrpc_value_to_php($raw_versions);
167
	} else {
168
		return array();
169
	}
170
}
171

    
172
/*
173
 * resync_all_package_configs() Force packages to setup their configuration and rc.d files.
174
 * This function may also print output to the terminal indicating progress.
175
 */
176
function resync_all_package_configs($show_message = false) {
177
	global $config, $restart_sync, $pkg_interface;
178
	$i = 0;
179
	log_error("Resyncing configuration for all packages.");
180
	if(!$config['installedpackages']['package']) return;
181
	if($show_message == true) print "Syncing packages:";
182
	foreach($config['installedpackages']['package'] as $package) {
183
		if (empty($package['name']))
184
			continue;
185
		if($show_message == true) print " " . $package['name'];
186
		get_pkg_depends($package['name'], "all");
187
		stop_service($package['name']);
188
		sync_package($i, true, true);
189
		if($restart_sync == true) {
190
			$restart_sync = false;
191
			if($pkg_interface == "console") 
192
				echo "\nSyncing packages:";
193
		}
194
		$i++;
195
	}
196
	if($show_message == true) print ".\n";
197
}
198

    
199
/*
200
 * is_freebsd_pkg_installed() - Check /var/db/pkg to determine whether or not a FreeBSD
201
 *				package is installed.
202
 */
203
function is_freebsd_pkg_installed($pkg) {
204
	global $g;
205
	if(in_array($pkg, return_dir_as_array("{$g['vardb_path']}/pkg")))
206
		return true;
207
	return false;
208
}
209

    
210
/*
211
 * get_pkg_depends($pkg_name, $filetype = ".xml", $format = "files", return_nosync = 1):  Return a package's dependencies.
212
 *
213
 * $filetype = "all" || ".xml", ".tgz", etc.
214
 * $format = "files" (full filenames) || "names" (stripped / parsed depend names)
215
 * $return_nosync = 1 (return depends that have nosync set) | 0 (ignore packages with nosync)
216
 *
217
 */
218
function get_pkg_depends($pkg_name, $filetype = ".xml", $format = "files", $return_nosync = 1) {
219
	global $config;
220
	require_once("notices.inc");
221
	$pkg_id = get_pkg_id($pkg_name);
222
	if(!is_numeric($pkg_name)) {
223
		if($pkg_id == -1) return -1; // This package doesn't really exist - exit the function.
224
	} else {
225
		if(!isset($config['installedpackages']['package'][$pkg_id])) return; // No package belongs to the pkg_id passed to this function.
226
	}
227
	$package = $config['installedpackages']['package'][$pkg_id];
228
	if(!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
229
		log_error("The {$package['name']} package is missing required dependencies and must be reinstalled." . $package['configurationfile']);
230
		install_package($package['name']);
231
		uninstall_package_from_name($package['name']);
232
		install_package($package['name']);
233
		return;
234
	}
235
	$pkg_xml = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
236
	if($pkg_xml['additional_files_needed'] != "") {
237
		foreach($pkg_xml['additional_files_needed'] as $item) {
238
			if (($return_nosync == 0) && (isset($item['nosync']))) continue; // Do not return depends with nosync set if not required.
239
			$depend_file = substr(strrchr($item['item']['0'], '/'),1); // Strip URLs down to filenames.
240
			$depend_name = substr(substr($depend_file,0,strpos($depend_file,".")+1),0,-1); // Strip filename down to dependency name.
241
			if (($filetype != "all") && (!preg_match("/{$filetype}/i", $depend_file))) continue;
242
			if ($item['prefix'] != "") {
243
				$prefix = $item['prefix'];
244
			} else {
245
				$prefix = "/usr/local/pkg/";
246
			}
247
			if(!file_exists($prefix . $depend_file))
248
				log_error("The {$package['name']} package is missing required dependencies and must be reinstalled.");
249
			switch ($format) {
250
				case "files":
251
				$depends[] = $depend_file;
252
			break;
253
            			case "names":
254
                		switch ($filetype) {
255

    
256
				case "all":
257
				if(preg_match("/\.xml/i", $depend_file)) {
258
					$depend_xml = parse_xml_config_pkg("/usr/local/pkg/" . $depend_file, "packagegui");
259
					$depends[] = $depend_xml['name'];
260
					break;
261
				} else {
262
					$depends[] = $depend_name; // If this dependency isn't package XML, use the stripped filename.
263
				break;
264
				}
265
				case ".xml":
266
				$depend_xml = parse_xml_config_pkg("/usr/local/pkg/" . $depend_file, "packagegui");
267
				$depends[] = $depend_xml['name'];
268
				break;
269
				default:
270
				$depends[] = $depend_name; // If we aren't looking for XML, use the stripped filename (it's all we have).
271
				break;
272
				}
273
			}
274
		}
275
		return $depends;
276
	}
277
}
278

    
279
function uninstall_package_from_name($pkg_name) {
280
	global $config;
281
	$id = get_pkg_id($pkg_name);
282
	$pkg_depends =& $config['installedpackages']['package'][$id]['depends_on_package'];
283
	delete_package($pkg_depends[0], $pkg_name);
284
	if (is_array($pkg_depends)) {
285
		foreach ($pkg_depends as $pkg_depend)
286
			remove_freebsd_package($pkg_depend);
287
	}
288
	delete_package_xml($pkg_name);
289
}
290

    
291
function force_remove_package($pkg_name) {
292
	global $config;
293
	delete_package_xml($pkg_name);
294
}
295

    
296
/*
297
 * sync_package($pkg_name, $sync_depends = true, $show_message = false) Force a package to setup its configuration and rc.d files.
298
 */
299
function sync_package($pkg_name, $sync_depends = true, $show_message = false) {
300
	global $config;
301
	require_once("notices.inc");
302
	if(!$config['installedpackages']['package']) return;
303
	if(!is_numeric($pkg_name)) {
304
		$pkg_id = get_pkg_id($pkg_name);
305
		if($pkg_id == -1) return -1; // This package doesn't really exist - exit the function.
306
	} else {
307
		$pkg_id = $pkg_name;
308
		if(!isset($config['installedpackages']['package'][$pkg_id]))
309
		return;  // No package belongs to the pkg_id passed to this function.
310
	}
311
        if (is_array($config['installedpackages']['package'][$pkg_id]))
312
			$package = $config['installedpackages']['package'][$pkg_id];
313
        else
314
			return; /* empty package tag */
315
	if(!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
316
		log_error("The {$package['name']} package is missing its configuration file and must be reinstalled.");
317
		force_remove_package($package['name']);
318
	} else {
319
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
320

    
321
		/* Bring in package include files */
322
		if (!empty($pkg_config['include_file'])) {
323
			$include_file = $pkg_config['include_file'];
324
			if (file_exists($include_file))
325
				require_once($include_file);
326
			else {
327
				/* XXX: What the heck is this?! */
328
				log_error("Could not locate {$include_file}.");
329
				install_package($package['name']);
330
				uninstall_package_from_name($package['name']);
331
				install_package($package['name']);
332
			}
333
		}
334

    
335
		/* XXX: Zend complains about the next line "Wrong break depth"
336
		 * The code is obviously wrong, but I'm not sure what it's supposed to do?
337
		 */
338
		if(isset($pkg_config['nosync'])) continue;
339
		if(!empty($pkg_config['custom_php_global_functions']))
340
			eval($pkg_config['custom_php_global_functions']);
341
		if(!empty($pkg_config['custom_php_resync_config_command']))
342
			eval($pkg_config['custom_php_resync_config_command']);
343
		if($sync_depends == true) {
344
			$depends = get_pkg_depends($pkg_name, ".xml", "files", 1); // Call dependency handler and do a little more error checking.
345
			if(is_array($depends)) {
346
				foreach($depends as $item) {
347
					if(!file_exists("/usr/local/pkg/" . $item)) {
348
						file_notice($package['name'], "The {$package['name']} package is missing required dependencies and must be reinstalled.", "Packages", "/pkg_mgr_install.php?mode=reinstallpkg&pkg={$package['name']}", 1);
349
						log_error("Could not find {$item}. Reinstalling package.");
350
						install_package($pkg_name);
351
						uninstall_package_from_name($pkg_name);
352
						install_package($pkg_name);
353
					} else {
354
						$item_config = parse_xml_config_pkg("/usr/local/pkg/" . $item, "packagegui");
355
						if(isset($item_config['nosync'])) continue;
356
						if($item_config['custom_php_command_before_form'] <> "") {
357
							eval($item_config['custom_php_command_before_form']);
358
						}
359
						if($item_config['custom_php_resync_config_command'] <> "") {
360
							eval($item_config['custom_php_resync_config_command']);
361
						}
362
						if($show_message == true) print " " . $item_config['name'];
363
					}
364
				}
365
			}
366
		}
367
	}
368
}
369

    
370
/*
371
 * pkg_fetch_recursive: Download and install a FreeBSD package and its dependencies. This function provides output to
372
 * 			a progress bar and output window.
373
 *
374
 * XXX: This function needs to return where a pkg_add fails. Our current error messages aren't very descriptive.
375
 */
376
function pkg_fetch_recursive($pkgname, $filename, $dependlevel = 0, $base_url = 'http://ftp2.freebsd.org/pub/FreeBSD/ports/i386/packages-5.4-release/Latest') {
377
	global $pkgent, $static_output, $g, $fd_log;
378
	$pkg_extension = strrchr($filename, '.');
379
	$static_output .= "\n" . str_repeat(" ", $dependlevel * 2) . $pkgname . " ";
380
	$fetchto = "{$g['tmp_path']}/apkg_" . $pkgname . $pkg_extension;
381
	download_file_with_progress_bar($base_url . '/' . $filename, $fetchto);
382
	$static_output .= " (extracting)";
383
	update_output_window($static_output);
384
		$slaveout = "";
385
	exec("/usr/bin/tar --fast-read -O -f {$fetchto} -x +CONTENTS 2>&1", $slaveout);
386
	$workingdir = preg_grep("/instmp/", $slaveout);
387
	$workingdir = $workingdir[0];
388
	$raw_depends_list = array_values(preg_grep("/\@pkgdep/", $slaveout));
389
	if($raw_depends_list != "") {
390
		if($pkgent['exclude_dependency'] != "")
391
			$raw_depends_list = array_values(preg_grep($pkgent['exclude_dependency'], PREG_GREP_INVERT));
392
		foreach($raw_depends_list as $adepend) {
393
			$working_depend = explode(" ", $adepend);
394
			//$working_depend = explode("-", $working_depend[1]);
395
			$depend_filename = $working_depend[1] . $pkg_extension;
396
			if(is_freebsd_pkg_installed($working_depend[1]) === false) {
397
				pkg_fetch_recursive($working_depend[1], $depend_filename, $dependlevel + 1, $base_url);
398
			} else {
399
//				$dependlevel++;
400
				$static_output .= "\n" . str_repeat(" ", $dependlevel * 2) . $working_depend[1] . " ";
401
				@fwrite($fd_log, $working_depend[1] . "\n");
402
			}
403
		}
404
	}
405
	$pkgaddout = "";
406
	exec("cat {$g['tmp_path']}/y | /usr/sbin/pkg_add -fv {$fetchto} 2>&1", $pkgaddout);
407
	@fwrite($fd_log, $pkgname . " " . print_r($pkgaddout, true) . "\n");
408
	return true;
409
}
410

    
411
function install_package($package, $pkg_info = "") {
412
	global $g, $config, $pkg_interface, $fd_log, $static_output, $pkg_interface, $restart_sync;
413
	if($pkg_interface == "console") 	
414
		echo "\n";
415
	/* open logfiles and begin installation */
416
	if(!$fd_log) {
417
		if(!$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_{$package}.log", "w")) {
418
			update_output_window("Warning, could not open log for writing.");
419
		}
420
	}
421
	/* fetch package information if needed */
422
	if(!$pkg_info or !is_array($pkg_info[$package])) {
423
		$pkg_info = get_pkg_info(array($package));
424
		$pkg_info = $pkg_info[$package]; // We're only dealing with one package, so we can strip away the extra array.
425
	}
426
	@fwrite($fd_log, "Beginning package installation.\n");
427
	log_error('Beginning package installation for ' . $pkg_info['name'] . '.');
428
	update_status("Beginning package installation for " . $pkg_info['name'] . "...");	
429
	/* fetch the package's configuration file */
430
	if($pkg_info['config_file'] != "") {
431
		$static_output .= "Downloading package configuration file... ";
432
		update_output_window($static_output);
433
		@fwrite($fd_log, "Downloading package configuration file...\n");
434
		$fetchto = substr(strrchr($pkg_info['config_file'], '/'), 1);
435
		download_file_with_progress_bar($pkg_info['config_file'], '/usr/local/pkg/' . $fetchto);
436
		if(!file_exists('/usr/local/pkg/' . $fetchto)) {
437
			@fwrite($fd_log, "ERROR! Unable to fetch package configuration file. Aborting installation.\n");
438
			if($pkg_interface == "console") {
439
				print "\nERROR! Unable to fetch package configuration file. Aborting package installation.\n";
440
				return;
441
			} else {
442
				$static_output .= "failed!\n\nInstallation aborted.";
443
				update_output_window($static_output);
444
				echo "<br>Show <a href=\"pkg_mgr_install.php?showlog=true\">install log</a></center>";
445
			 	return -1;
446
			}
447
		}
448
		$static_output .= "done.\n";
449
		update_output_window($static_output);
450
	}
451
	/* add package information to config.xml */
452
	$pkgid = get_pkg_id($pkg_info['name']);
453
	$static_output .= "Saving updated package information... ";
454
	update_output_window($static_output);
455
	if($pkgid == -1) {
456
		$config['installedpackages']['package'][] = $pkg_info;
457
		$changedesc = "Installed {$pkg_info['name']} package.";
458
		$to_output = "done.\n";
459
	} else {
460
		$config['installedpackages']['package'][$pkgid] = $pkg_info;
461
		$changedesc = "Overwrote previous installation of {$pkg_info['name']}.";
462
		$to_output = "overwrite!\n";
463
	}
464
	/* XXX: Fix inclusion of config.inc that causes data loss! */
465
	write_config();
466
	$static_output .= $to_output;
467
	update_output_window($static_output);
468
	/* install other package components */
469
	install_package_xml($package);
470
	$static_output .= "Writing configuration... ";
471
	update_output_window($static_output);
472
	write_config($changedesc);
473
	$static_output .= "done.\n";
474
	update_output_window($static_output);
475
	$static_output .= "Starting service.\n";
476
	update_output_window($static_output);
477
	if($pkg_info['after_install_info']) 
478
		update_output_window($pkg_info['after_install_info']);	
479
	start_service($pkg_info['config_file']);
480
	$restart_sync = true;
481
}
482

    
483
function get_after_install_info($package) {
484
	global $pkg_info;
485
	/* fetch package information if needed */
486
	if(!$pkg_info or !is_array($pkg_info[$package])) {
487
		$pkg_info = get_pkg_info(array($package));
488
		$pkg_info = $pkg_info[$package]; // We're only dealing with one package, so we can strip away the extra array.
489
	}
490
	if($pkg_info['after_install_info'])
491
		return $pkg_info['after_install_info'];
492
}
493

    
494
function eval_once($toeval) {
495
	global $evaled;
496
	if(!$evaled) $evaled = array();
497
	$evalmd5 = md5($toeval);
498
	if(!in_array($evalmd5, $evaled)) {
499
		@eval($toeval);
500
		$evaled[] = $evalmd5;
501
	}
502
	return;
503
}
504

    
505
function install_package_xml($pkg) {
506
	global $g, $config, $fd_log, $static_output, $pkg_interface;
507
	if(($pkgid = get_pkg_id($pkg)) == -1) {
508
		$static_output .= "The {$pkg} package is not installed.\n\nInstallation aborted.";
509
		update_output_window($static_output);
510
		if($pkg_interface <> "console") {
511
			echo "\n<script language=\"JavaScript\">document.progressbar.style.visibility='hidden';</script>";
512
			echo "\n<script language=\"JavaScript\">document.progholder.style.visibility='hidden';</script>";
513
		}
514
		sleep(1);
515
		return;
516
	} else {
517
		$pkg_info = $config['installedpackages']['package'][$pkgid];
518
	}
519
	/* set up logging if needed */
520
	if(!$fd_log) {
521
		if(!$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_{$pkg}.log", "w")) {
522
			update_output_window("Warning, could not open log for writing.");
523
		}
524
	}
525

    
526
	/* set up package logging streams */
527
	if($pkg_info['logging']) {
528
		mwexec("/usr/sbin/fifolog_create -s 32768 {$g['varlog_path']}/{$pkg_info['logging']['logfilename']}");
529
		chmod($g['varlog_path'] . '/' . $pkg_info['logging']['logfilename'], 0600);
530
		@fwrite($fd_log, "Adding text to file /etc/syslog.conf\n");
531
		if(is_process_running("syslogd"))
532
			mwexec("killall syslogd");
533
		system_syslogd_start();
534
	}
535

    
536
	/* make 'y' file */
537
	$fd = fopen("{$g['tmp_path']}/y", "w");
538
	for($line = 0; $line < 10; $line++) {
539
		fwrite($fd, "y\n");
540
	}
541
	fclose($fd);
542

    
543
	/* pkg_add the package and its dependencies */
544
	if($pkg_info['depends_on_package_base_url'] != "") {
545
		if($pkg_interface == "console") 
546
			echo "\n";
547
		update_status("Installing " . $pkg_info['name'] . " and its dependencies.");
548
		$static_output .= "Downloading " . $pkg_info['name'] . " and its dependencies... ";
549
		$static_orig = $static_output;
550
		$static_output .= "\n";
551
		update_output_window($static_output);
552
		foreach((array) $pkg_info['depends_on_package'] as $pkgdep) {
553
			$pkg_name = substr(reverse_strrchr($pkgdep, "."), 0, -1);
554
			if(isset($pkg_info['skip_install_checks'])) {
555
				$pkg_installed = true;
556
			} else {
557
				$pkg_installed = is_freebsd_pkg_installed($pkg_name);
558
			}
559
			if($pkg_installed == false)
560
				pkg_fetch_recursive($pkg_name, $pkgdep, 0, $pkg_info['depends_on_package_base_url']);
561
			$static_output = $static_orig . "done.\nChecking for successful package installation... ";
562
			update_output_window($static_output);
563
			/* make sure our package was successfully installed */
564
			if($pkg_installed == false)
565
				$pkg_installed = is_freebsd_pkg_installed($pkg_name);
566
			if($pkg_installed == true) {
567
				$static_output .= "done.\n";
568
				update_output_window($static_output);
569
				fwrite($fd_log, "pkg_add successfully completed.\n");
570
			} else {
571
				$static_output .= "of {$pkg_name} failed!\n\nInstallation aborted.";
572
				update_output_window($static_output);
573
				fwrite($fd_log, "Package WAS NOT installed properly.\n");
574
				fclose($fd_log);
575
				if($pkg_interface <> "console") {
576
					echo "\n<script language=\"JavaScript\">document.progressbar.style.visibility='hidden';</script>";
577
					echo "\n<script language=\"JavaScript\">document.progholder.style.visibility='hidden';</script>";
578
				}
579
				sleep(1);
580
				die;
581
			}
582
		}
583
	}
584
	$configfile = substr(strrchr($pkg_info['config_file'], '/'), 1);
585
	if(file_exists("/usr/local/pkg/" . $configfile)) {
586
		$static_output .= "Loading package configuration... ";
587
		update_output_window($static_output);
588
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $configfile, "packagegui");
589
		$static_output .= "done.\n";
590
		update_output_window($static_output);
591
		$static_output .= "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
		update_output_window($static_output);
595
		/* modify system files */
596
		if(is_array($pkg_config['modify_system']['item'])) {
597
			$static_output .= "\tSystem files... ";
598
			update_output_window($static_output);
599
			foreach($pkg_config['modify_system']['item'] as $ms) {
600
				if($ms['textneeded']) {
601
					add_text_to_file($ms['modifyfilename'], $ms['textneeded']);
602
				}
603
			}
604
			$static_output .= "done.\n";
605
			update_output_window($static_output);
606
		}
607
		/* download additional files */
608
		if(is_array($pkg_config['additional_files_needed'])) {
609
			$static_output .= "\tAdditional files... ";
610
			$static_orig = $static_output;
611
			update_output_window($static_output);
612
			foreach($pkg_config['additional_files_needed'] as $afn) {
613
				$filename = get_filename_from_url($afn['item'][0]);
614
				if($afn['chmod'] <> "") {
615
					$pkg_chmod = $afn['chmod'];
616
				} else {
617
					$pkg_chmod = "";
618
				}
619
				if($afn['prefix'] <> "") {
620
					$prefix = $afn['prefix'];
621
				} else {
622
					$prefix = "/usr/local/pkg/";
623
				}
624
				if(!is_dir($prefix)) 
625
					safe_mkdir($prefix);
626
 				$static_output .= $filename . " ";
627
                                update_output_window($static_output);
628
				download_file_with_progress_bar($afn['item'][0], $prefix . $filename);
629
				if(stristr($filename, ".tgz") <> "") {
630
					fwrite($fd_log, "Extracting tarball to -C for " . $filename . "...\n");
631
					$tarout = "";
632
					exec("/usr/bin/tar xvzf " . $prefix . $filename . " -C / 2>&1", $tarout);
633
					fwrite($fd_log, print_r($tarout, true) . "\n");
634
				}
635
				if($pkg_chmod <> "") {
636
					fwrite($fd_log, "Changing file mode to {$pkg_chmod} for {$prefix}{$filename}\n");
637
					chmod($prefix . $filename, $pkg_chmod);
638
					system("/bin/chmod {$pkg_chmod} {$prefix}{$filename}");
639
				}
640
				$static_output = $static_orig;
641
                                update_output_window($static_output);
642
			}
643
			$static_output .= "done.\n";
644
			update_output_window($static_output);
645
		}
646
		/*   if a require exists, include it.  this will
647
		 *   show us where an error exists in a package
648
		 *   instead of making us blindly guess
649
		 */
650
		if($pkg_config['include_file'] <> "") {
651
			$static_output = "Loading package instructions...";
652
			update_output_window($static_output);
653
			fwrite($fd_log, "require_once('{$pkg_config['include_file']}')\n");
654
			require_once($pkg_config['include_file']);
655
		}
656
		/* sidebar items */
657
		if(is_array($pkg_config['menu'])) {
658
			$static_output .= "\tMenu items... ";
659
			update_output_window($static_output);
660
			foreach($pkg_config['menu'] as $menu) {
661
				if(is_array($config['installedpackages']['menu']))
662
					foreach($config['installedpackages']['menu'] as $amenu)
663
						if($amenu['name'] == $menu['name'])
664
							continue 2;
665
				$config['installedpackages']['menu'][] = $menu;
666
			}
667
			$static_output .= "done.\n";
668
			update_output_window($static_output);
669
		}
670
		/* integrated tab items */
671
		if(is_array($pkg_config['tabs']['tab'])) {
672
			$static_output .= "\tIntegrated Tab items... ";
673
			update_output_window($static_output);
674
			foreach($pkg_config['tabs']['tab'] as $tab) {
675
				if(is_array($config['installedpackages']['tab']))
676
					foreach($config['installedpackages']['tab'] as $atab)
677
						if($atab['name'] == $tab['name'])
678
							continue 2;
679
				$config['installedpackages']['tab'][] = $tab;
680
			}
681
			$static_output .= "done.\n";
682
			update_output_window($static_output);
683
		}
684
		/* services */
685
		if(is_array($pkg_config['service'])) {
686
			$static_output .= "\tServices... ";
687
			update_output_window($static_output);
688
			foreach($pkg_config['service'] as $service) {
689
				$config['installedpackages']['service'][] = $service;
690
			}
691
			$static_output .= "done.\n";
692
			update_output_window($static_output);
693
		}
694
		/* custom commands */
695
		$static_output .= "\tCustom commands... ";
696
		update_output_window($static_output);
697
		if($pkg_config['custom_php_global_functions'] <> "") {
698
			$static_output = "Executing custom_php_global_functions()...";
699
			update_output_window($static_output);
700
			eval_once($pkg_config['custom_php_global_functions']);
701
		}
702
		if($pkg_config['custom_php_install_command']) {
703
			$static_output = "Executing custom_php_install_command()...";
704
			update_output_window($static_output);
705
			eval_once($pkg_config['custom_php_install_command']);
706
		}
707
		if($pkg_config['custom_php_resync_config_command'] <> "") {
708
			$static_output = "Executing custom_php_resync_config_command()...";
709
			update_output_window($static_output);
710
			eval_once($pkg_config['custom_php_resync_config_command']);
711
		}
712
		$static_output .= "done.\n";
713
		update_output_window($static_output);
714
	} else {
715
		$static_output .= "Loading package configuration... failed!\n\nInstallation aborted.";
716
		update_output_window($static_output);
717
		fwrite($fd_log, "Unable to load package configuration. Installation aborted.\n");
718
		fclose($fd_log);
719
		if($pkg_interface <> "console") {
720
			echo "\n<script language=\"JavaScript\">document.progressbar.style.visibility='hidden';</script>";
721
			echo "\n<script language=\"JavaScript\">document.progholder.style.visibility='hidden';</script>";
722
		}
723
		sleep(1);
724
		return;
725
	}
726
}
727

    
728
function delete_package($pkg, $pkgid) {
729
	global $g, $config, $fd_log, $static_output;
730
	update_status("Removing package...");
731
	$static_output .= "Removing package... ";
732
	update_output_window($static_output);
733
	$pkgid = get_pkg_id($pkgid);
734
	$pkg_info = $config['installedpackages']['package'][$pkgid];
735

    
736
	$configfile = $pkg_info['configurationfile'];
737
	if(file_exists("/usr/local/pkg/" . $configfile)) {
738
		$static_output .= "\nLoading package configuration $configfile... ";
739
		update_output_window($static_output);
740
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $configfile, "packagegui");
741
		/*   if a require exists, include it.  this will
742
		 *   show us where an error exists in a package
743
		 *   instead of making us blindly guess
744
		 */
745
		if($pkg_config['include_file'] <> "") {
746
			$static_output .= "\nLoading package instructions...\n";
747
			update_output_window($static_output);
748
			require_once($pkg_config['include_file']);
749
		}
750
	}
751
	$static_output .= "\nStarting package deletion for {$pkg_info['name']}...\n";
752
	update_output_window($static_output);
753
	if (!empty($pkg))
754
		delete_package_recursive($pkg);
755
	$static_output .= "done.\n";
756
	update_output_window($static_output);
757
	return;
758
}
759

    
760
function delete_package_recursive($pkg) {
761
	global $config, $g;
762
	$fd = fopen("{$g['tmp_path']}/y", "w");
763
	for($line = 0; $line < 10; $line++) {
764
		fwrite($fd, "y\n");
765
	}
766
	fclose($fd);
767
	$pkg = substr(reverse_strrchr($pkg, "."), 0, -1);
768
	$info = "";
769
	exec("/usr/sbin/pkg_info -r {$pkg} 2>&1", $info);
770
	remove_freebsd_package($pkg);
771
	$pkgdb = "";
772
	exec("/bin/ls /var/db/pkg", $pkgdb);
773
	foreach($info as $line) {
774
		$depend = trim(array_pop(explode(":", $line)));
775
		if(in_array($depend, $pkgdb)) 
776
			delete_package_recursive($depend);
777
	}
778
	return;
779
}
780

    
781
function delete_package_xml($pkg) {
782
	global $g, $config, $fd_log, $static_output, $pkg_interface;
783
	conf_mount_rw();
784

    
785
	if(($pkgid = get_pkg_id($pkg)) == -1) {
786
		$static_output .= "The {$pkg} package is not installed.\n\nDeletion aborted.";
787
		update_output_window($static_output);
788
		if($pkg_interface <> "console") {
789
			echo "\n<script language=\"JavaScript\">document.progressbar.style.visibility='hidden';</script>";
790
			echo "\n<script language=\"JavaScript\">document.progholder.style.visibility='hidden';</script>";
791
		}
792
		ob_flush();
793
		sleep(1);
794
		return;
795
	}
796
	/* set up logging if needed */
797
	if(!$fd_log) {
798
		if(!$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_{$pkg}.log", "w")) {
799
			update_output_window("Warning, could not open log for writing.");
800
		}
801
	}
802
	update_status("Removing {$pkg} components...");
803
	fwrite($fd_log, "Removing {$pkg} package... ");
804
	$static_output .= "Removing {$pkg} components...\n";
805
	update_output_window($static_output);
806
	/* parse package configuration */
807
	$packages = &$config['installedpackages']['package'];
808
	$tabs =& $config['installedpackages']['tab'];
809
	$menus =& $config['installedpackages']['menu'];
810
	$services = &$config['installedpackages']['service'];
811
	if(file_exists("/usr/local/pkg/" . $packages[$pkgid]['configurationfile'])) {
812
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" . $packages[$pkgid]['configurationfile'], "packagegui");
813
		/* remove tab items */
814
		if(is_array($pkg_config['tabs'])) {
815
			$static_output .= "\tMenu items... ";
816
			update_output_window($static_output);
817
			if(is_array($pkg_config['tabs']['tab']) && is_array($tabs)) {
818
				foreach($pkg_config['tabs']['tab'] as $tab) {
819
					foreach($tabs as $key => $insttab)
820
						if($insttab['name'] == $tab['name'])
821
							unset($tabs[$key]);
822
				}
823
			}
824
			$static_output .= "done.\n";
825
			update_output_window($static_output);
826
		}
827
		/* remove menu items */
828
		if(is_array($pkg_config['menu'])) {
829
			$static_output .= "\tMenu items... ";
830
			update_output_window($static_output);
831
			if (is_array($pkg_config['menu']) && is_array($menus)) {
832
				foreach($pkg_config['menu'] as $menu) {
833
					foreach($menus as $key => $instmenu)
834
						if($instmenu['name'] == $menu['name'])
835
							unset($menus[$key]);
836
				}
837
			}
838
			$static_output .= "done.\n";
839
			update_output_window($static_output);
840
		}
841
		/* remove services */
842
		if(is_array($pkg_config['service'])) {
843
			$static_output .= "\tServices... ";
844
			update_output_window($static_output);
845
			if (is_array($pkg_config['service']) && is_array($services)) {
846
				foreach($pkg_config['service'] as $service) {
847
					foreach($services as $key => $instservice) {
848
						if($instservice['name'] == $service['name']) {
849
							stop_service($service['name']);
850
							unset($services[$key]);
851
						}
852
					}
853
				}
854
			}
855
			$static_output .= "done.\n";
856
			update_output_window($static_output);
857
		}
858
		/*   if a require exists, include it.  this will
859
		 *   show us where an error exists in a package
860
		 *   instead of making us blindly guess
861
		 */
862
		if($pkg_config['include_file'] <> "") {
863
			$static_output = "Loading package instructions...";
864
			update_output_window($static_output);
865
			fwrite($fd_log, "require_once(\"{$pkg_config['include_file']}\")\n");
866
			if(file_exists($pkg_config['include_file']))
867
				require_once($pkg_config['include_file']);
868
			fwrite($fd_log, "require_once(\"{$pkg_config['include_file']}\") included\n");
869
		}
870
		/* evalate this package's global functions and pre deinstall commands */
871
		if($pkg_config['custom_php_global_functions'] <> "")
872
			eval_once($pkg_config['custom_php_global_functions']);
873
		if($pkg_config['custom_php_pre_deinstall_command'] <> "")
874
			eval_once($pkg_config['custom_php_pre_deinstall_command']);
875
		/* remove all additional files */
876
		if(is_array($pkg_config['additional_files_needed'])) {
877
			$static_output .= "\tAuxiliary files... ";
878
			update_output_window($static_output);
879
			foreach($pkg_config['additional_files_needed'] as $afn) {
880
				$filename = get_filename_from_url($afn['item'][0]);
881
				if($afn['prefix'] <> "") {
882
					$prefix = $afn['prefix'];
883
				} else {
884
					$prefix = "/usr/local/pkg/";
885
				}
886
				unlink_if_exists($prefix . $filename);
887
				if(file_exists($prefix . $filename))
888
				    mwexec("rm -rf {$prefix}{$filename}");
889
			}
890
			$static_output .= "done.\n";
891
			update_output_window($static_output);
892
		}
893
		/* system files */
894
		if(is_array($pkg_config['modify_system']['item'])) {
895
			$static_output .= "\tSystem files... ";
896
			update_output_window($static_output);
897
			foreach($pkg_config['modify_system']['item'] as $ms) {
898
				if($ms['textneeded']) remove_text_from_file($ms['modifyfilename'], $ms['textneeded']);
899
			}
900
			$static_output .= "done.\n";
901
			update_output_window($static_output);
902
		}
903
		/* syslog */
904
		if($pkg_config['logging']['logfile_name'] <> "") {
905
			$static_output .= "\tSyslog entries... ";
906
			update_output_window($static_output);
907
			remove_text_from_file("/etc/syslog.conf", $pkg_config['logging']['facilityname'] . "\t\t\t\t" . $pkg_config['logging']['logfilename']);
908
			$static_output .= "done.\n";
909
			update_output_window($static_output);
910
		}
911
		/* deinstall commands */
912
		if($pkg_config['custom_php_deinstall_command'] <> "") {
913
			$static_output .= "\tDeinstall commands... ";
914
			update_output_window($static_output);
915
			eval_once($pkg_config['custom_php_deinstall_command']);
916
			$static_output .= "done.\n";
917
			update_output_window($static_output);
918
		}
919
		if($pkg_config['include_file'] <> "") {
920
                        $static_output = "\tRemoving pacakge instructions...";
921
                        update_output_window($static_output);
922
                        fwrite($fd_log, "Remove '{$pkg_config['include_file']}'\n");
923
                        unlink_if_exists("/usr/local/pkg/" . $pkg_config['include_file']);
924
			$static_output .= "done.\n";
925
                        update_output_window($static_output);
926
			
927
                }
928
		/* package XML file */
929
		$static_output .= "\tPackage XML... ";
930
		update_output_window($static_output);
931
		unlink_if_exists("/usr/local/pkg/" . $packages[$pkgid]['configurationfile']);
932
		$static_output .= "done.\n";
933
		update_output_window($static_output);
934
	}
935
	/* remove config.xml entries */
936
	$static_output .= "\tConfiguration... ";
937
	update_output_window($static_output);
938
	unset($config['installedpackages']['package'][$pkgid]);
939
	$static_output .= "done.\n";
940
	update_output_window($static_output);
941
	write_config("Removed {$pkg} package.");
942
	/* file cleanup */
943
	$ctag = file("/etc/crontab");
944
	foreach($ctag as $line) {
945
		if(trim($line) != "") $towrite[] = $line;
946
	}
947
	$tmptab = fopen("{$g['tmp_path']}/crontab", "w");
948
	foreach($towrite as $line) {
949
		fwrite($tmptab, $line);
950
	}
951
	fclose($tmptab);
952

    
953
	// Go RW again since the write_config above will put it back to RO
954
	conf_mount_rw();
955
	rename("{$g['tmp_path']}/crontab", "/etc/crontab");
956
	conf_mount_ro();
957
}
958

    
959
function expand_to_bytes($size) {
960
	$conv = array(
961
			"G" =>	"3",
962
			"M" =>  "2",
963
			"K" =>  "1",
964
			"B" =>  "0"
965
		);
966
	$suffix = substr($size, -1);
967
	if(!in_array($suffix, array_keys($conv))) return $size;
968
	$size = substr($size, 0, -1);
969
	for($i = 0; $i < $conv[$suffix]; $i++) {
970
		$size *= 1024;
971
	}
972
	return $size;
973
}
974

    
975
function get_pkg_db() {
976
	global $g;
977
	return return_dir_as_array($g['vardb_path'] . '/pkg');
978
}
979

    
980
function walk_depend($depend, $pkgdb = "", $alreadyseen = "") {
981
	if(!$pkgdb)
982
		$pkgdb = get_pkg_db();
983
	if(!is_array($alreadyseen))
984
		$alreadyseen = array();
985
	if (!is_array($depend))
986
		$depend = array();
987
	foreach($depend as $adepend) {
988
		$pkgname = reverse_strrchr($adepend['name'], '.');
989
		if(in_array($pkgname, $alreadyseen)) {
990
			continue;
991
		} elseif(!in_array($pkgname, $pkgdb)) {
992
			$size += expand_to_bytes($adepend['size']);
993
			$alreadyseen[] = $pkgname;
994
			if(is_array($adepend['depend'])) $size += walk_depend($adepend['depend'], $pkgdb, $alreadyseen);
995
		}
996
	}
997
	return $size;
998
}
999

    
1000
function get_package_install_size($pkg = 'all', $pkg_info = "") {
1001
	global $config, $g;
1002
	if((!is_array($pkg)) and ($pkg != 'all'))
1003
		$pkg = array($pkg);
1004
	$pkgdb = get_pkg_db();
1005
	if(!$pkg_info)
1006
		$pkg_info = get_pkg_sizes($pkg);
1007
	foreach($pkg as $apkg) {
1008
		if(!$pkg_info[$apkg]) continue;
1009
		$toreturn[$apkg] = expand_to_bytes(walk_depend(array($pkg_info[$apkg]), $pkgdb));
1010
	}
1011
	return $toreturn;
1012
}
1013

    
1014
function squash_from_bytes($size, $round = "") {
1015
	$conv = array(1 => "B", "K", "M", "G");
1016
	foreach($conv as $div => $suffix) {
1017
		$sizeorig = $size;
1018
		if(($size /= 1024) < 1) {
1019
			if($round) {
1020
				$sizeorig = round($sizeorig, $round);
1021
			}
1022
			return $sizeorig . $suffix;
1023
		}
1024
	}
1025
	return;
1026
}
1027

    
1028
?>
(30-30/50)