Project

General

Profile

Download (32.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) 2005 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
require_once("xmlrpc.inc");
36
require_once("xmlparse.inc");
37

    
38
/* add package specific listtags to XML parser */
39
$listtags = array_merge($listtags, array("onetoone", "queue", "rule", "servernat", "alias", "additional_files_needed", "tab", "template", "menu", "rowhelperfield", "service", "step", "package", "columnitem", "option", "item", "field", "package"));
40

    
41
require_once("pfsense-utils.inc");
42
require_once("globals.inc");
43

    
44
/*
45
safe_mkdir("/var/db/pkg");
46
safe_mkdir("/usr/local/pkg");
47
safe_mkdir("/usr/local/pkg/pf");
48
*/
49

    
50
/****f* pkg-utils/is_package_installed
51
 * NAME
52
 *   is_package_installed - Check whether a package is installed.
53
 * INPUTS
54
 *   $packagename	- name of the package to check
55
 * RESULT
56
 *   boolean	- true if the package is installed, false otherwise
57
 * NOTES
58
 *   This function is deprecated - get_pkg_id() can already check for installation.
59
 ******/
60
function is_package_installed($packagename) {
61
	$pkg = get_pkg_id($packagename);
62
	if($pkg == -1) return false;
63
	return true;
64
}
65
            
66
/****f* pkg-utils/get_pkg_id
67
 * NAME
68
 *   get_pkg_id - Find a package's numeric ID.
69
 * INPUTS
70
 *   $pkg_name	- name of the package to check
71
 * RESULT
72
 *   integer    - -1 if package is not found, >-1 otherwise
73
 ******/
74
function get_pkg_id($pkg_name) {
75
    global $config;
76
    if(is_array($config['installedpackages']['package'])) {
77
        $i = 0;
78
        foreach($config['installedpackages']['package'] as $pkg) {
79
            if($pkg['name'] == $pkg_name) return $i;
80
            $i++;
81
        }
82
    }
83
    return -1;
84
}
85

    
86
/****f* pkg-utils/get_pkg_info
87
 * NAME
88
 *   get_pkg_info - Retrive package information from pfsense.com.
89
 * INPUTS
90
 *   $pkgs - 'all' to retrive all packages, an array containing package names otherwise
91
 *   $info - 'all' to retrive all information, an array containing keys otherwise
92
 * RESULT
93
 *   $raw_versions - Array containing retrieved information, indexed by package name.
94
 ******/
95
function get_pkg_info($pkgs = 'all', $info = 'all') {
96
	global $g;
97
        $params = array("pkg" => $pkgs, "info" => $info);
98
        $msg = new XML_RPC_Message('pfsense.get_pkgs', array(php_value_to_xmlrpc($params)));
99
        $cli = new XML_RPC_Client($g['xmlrpcpath'], $g['xmlrpcbaseurl']);
100
        $resp = $cli->send($msg, 10);
101
	if($resp and !$resp->faultCode()) {
102
        	$raw_versions = $resp->value();
103
		return xmlrpc_value_to_php($raw_versions);
104
	} else {
105
		return array();
106
	}
107
}
108

    
109
function get_pkg_sizes($pkgs = 'all') {
110
	global $g;
111
        $params = array("pkg" => $pkgs);
112
        $msg = new XML_RPC_Message('pfsense.get_pkg_sizes', array(php_value_to_xmlrpc($params)));
113
        $cli = new XML_RPC_Client($g['xmlrpcpath'], $g['xmlrpcbaseurl']);
114
        $resp = $cli->send($msg, 10);  
115
        if($resp and !$resp->faultCode()) {
116
                $raw_versions = $resp->value();
117
                return xmlrpc_value_to_php($raw_versions);
118
        } else {
119
                return array();
120
        } 
121
}
122

    
123
/*
124
 * resync_all_package_configs() Force packages to setup their configuration and rc.d files.
125
 * This function may also print output to the terminal indicating progress.
126
 */
127
function resync_all_package_configs($show_message = false) {
128
    global $config;
129
    $i = 0;
130
    log_error("Resyncing configuration for all packages.");
131
    if(!$config['installedpackages']['package']) return;
132
    if($show_message == true) print "Syncing packages:";
133
    foreach($config['installedpackages']['package'] as $package) {
134
        if($show_message == true) print " " . $package['name'];
135
        sync_package($i, true, true);
136
        $i++;
137
    }
138
    if($show_message == true) print ".\n";
139
}
140

    
141
/*
142
 * is_freebsd_pkg_installed() - Check /var/db/pkg to determine whether or not a FreeBSD
143
 *				package is installed.
144
 */
145
function is_freebsd_pkg_installed($pkg) {
146
	global $g;
147
	if(in_array($pkg, return_dir_as_array("{$g['vardb_path']}/pkg"))) return true;
148
	return false;
149
}
150

    
151
/*
152
 * get_pkg_depends($pkg_name, $filetype = ".xml", $format = "files", return_nosync = 1):  Return a package's dependencies.
153
 *
154
 * $filetype = "all" || ".xml", ".tgz", etc.
155
 * $format = "files" (full filenames) || "names" (stripped / parsed depend names)
156
 * $return_nosync = 1 (return depends that have nosync set) | 0 (ignore packages with nosync)
157
 *
158
 */
159
function get_pkg_depends($pkg_name, $filetype = ".xml", $format = "files", $return_nosync = 1) {
160
    global $config;                                                                             
161
    if(!is_numeric($pkg_name)) {
162
        $pkg_id = get_pkg_id($pkg_name);
163
        if($pkg_id == -1) return -1; // This package doesn't really exist - exit the function.
164
    } else {                                                                                  
165
        if(!isset($config['installedpackages']['package'][$pkg_id])) return; // No package belongs to the pkg_id passed to this function.
166
    }                                                                                                                                    
167
    $package = $config['installedpackages']['package'][$pkg_id];
168
    if(!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
169
        file_notice($package['name'], "The {$package['name']} package is missing its configuration file and must be reinstalled.", "Packages", "/pkg_mgr_install.php?mode=reinstallpkg&pkg={$package['name']}", 1);
170
		return;
171
	}
172
	$pkg_xml = parse_xml_config("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
173
    if($pkg_xml['additional_files_needed'] != "") {                                                  
174
        foreach($pkg_xml['additional_files_needed'] as $item) {
175
            if (($return_nosync == 0) && (isset($item['nosync']))) continue; // Do not return depends with nosync set if not required.
176
            $depend_file = substr(strrchr($item['item']['0'], '/'),1); // Strip URLs down to filenames.
177
            $depend_name = substr(substr($depend_file,0,strpos($depend_file,".")+1),0,-1); // Strip filename down to dependency name.
178
            if (($filetype != "all") && (!preg_match("/${filetype}/i", $depend_file))) continue;
179
            if ($item['prefix'] != "") {
180
                $prefix = $item['prefix'];
181
            } else {
182
                $prefix = "/usr/local/pkg/";
183
            }
184
            if(!file_exists($prefix . $pkg_name)) {
185
				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);
186
            }
187
            switch ($format) {
188
            case "files":
189
                $depends[] = $depend_file;
190
                break;
191
            case "names":
192
                switch ($filetype) {
193
                case "all":
194
                    if(preg_match("/\.xml/i", $depend_file)) {
195
                        $depend_xml = parse_xml_config("/usr/local/pkg/" . $depend_file, "packagegui");
196
                        $depends[] = $depend_xml['name'];
197
                        break;
198
                    } else {
199
                        $depends[] = $depend_name; // If this dependency isn't package XML, use the stripped filename.
200
                        break;
201
                    }
202
                case ".xml":
203
                    $depend_xml = parse_xml_config("/usr/local/pkg/" . $depend_file, "packagegui");
204
                    $depends[] = $depend_xml['name'];
205
                    break;
206
                default:
207
                    $depends[] = $depend_name; // If we aren't looking for XML, use the stripped filename (it's all we have).
208
                    break;
209
                }
210
            }
211
        }
212
        return $depends;
213
    }
214
}
215

    
216
/*
217
 * sync_package($pkg_name, $sync_depends = true, $show_message = false) Force a package to setup its configuration and rc.d files.
218
 */
219
function sync_package($pkg_name, $sync_depends = true, $show_message = false) {
220
    global $config;
221

    
222
    if(!file_exists("/usr/local/pkg")) mwexec("/bin/mkdir -p /usr/local/pkg/pf");
223
    if(!$config['installedpackages']['package']) return;                         
224
    if(!is_numeric($pkg_name)) {                        
225
        $pkg_id = get_pkg_id($pkg_name);
226
        if($pkg_id == -1) return -1; // This package doesn't really exist - exit the function.
227
    } else {                                                                                  
228
        $pkg_id = $pkg_name;
229
        if(!isset($config['installedpackages']['package'][$pkg_id]))
230
            return;  // No package belongs to the pkg_id passed to this function.
231
    }                                                                            
232
    $package = $config['installedpackages']['package'][$pkg_id];
233
    if(!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
234
    	file_notice($package['name'], "The {$package['name']} package is missing its configuration file and must be reinstalled.", "Packages", "/pkg_mgr_install.php?mode=reinstallpkg&pkg={$package['name']}", 1);
235
    } else {
236
        $pkg_config = parse_xml_config("/usr/local/pkg/" . $package['configurationfile'], "packagegui");
237
		if(isset($pkg_config['nosync'])) continue;                                                          
238
		if($pkg['custom_php_global_functions'] <> "")            
239
	        eval($pkg['custom_php_global_functions']);
240
	    if($pkg_config['custom_php_command_before_form'] <> "")
241
	        eval($pkg_config['custom_php_command_before_form']);
242
	    if($pkg_config['custom_php_resync_config_command'] <> "")
243
	        eval($pkg_config['custom_php_resync_config_command']);
244
	    if($sync_depends == true) {
245
	        $depends = get_pkg_depends($pkg_name, ".xml", "files", 1); // Call dependency handler and do a little more error checking.
246
	        if(is_array($depends)) {
247
	            foreach($depends as $item) {
248
					if(!file_exists("/usr/local/pkg" . $item)) {
249
						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);
250
					} else {
251
		                $item_config = parse_xml_config("/usr/local/pkg/" . $item, "packagegui");
252
		                if(isset($item_config['nosync'])) continue;
253
		                if($item_config['custom_php_command_before_form'] <> "") {
254
		                    eval($item_config['custom_php_command_before_form']);
255
		                }
256
		                if($item_config['custom_php_resync_config_command'] <> "") {
257
		                    eval($item_config['custom_php_resync_config_command']);
258
		                }
259
		                if($show_message == true) print " " . $item_config['name'];
260
                  }
261
              }
262
          }
263
      }
264
    }
265
}
266

    
267
/*
268
 * pkg_fetch_recursive: Download and install a FreeBSD package and its dependencies. This function provides output to
269
 * 			a progress bar and output window.
270
 *
271
 * XXX: This function needs to return where a pkg_add fails. Our current error messages aren't very descriptive.
272
 */
273
function pkg_fetch_recursive($pkgname, $filename, $dependlevel = 0, $base_url = 'http://ftp2.freebsd.org/pub/FreeBSD/ports/i386/packages-5.4-release/Latest') {
274
        global $pkgent, $static_status, $static_output, $g, $pkg_interface, $fd_log;
275
        $pkg_extension = strrchr($filename, '.');
276
        $static_output .= "\n" . str_repeat(" ", $dependlevel * 2) . $pkgname . " ";
277
        $fetchto = "/tmp/apkg_" . $pkgname . $pkg_extension;
278
	download_file_with_progress_bar($base_url . '/' . $filename, $fetchto);
279
        exec("/usr/bin/tar --fast-read -O -f {$fetchto} -x +CONTENTS", $slaveout);
280
        $workingdir = preg_grep("/instmp/", $slaveout);
281
        $workingdir = $workingdir[0];
282
        $raw_depends_list = array_values(preg_grep("/\@pkgdep/", $slaveout));
283
        if($raw_depends_list != "") {
284
                if($pkgent['exclude_dependency'] != "")
285
                        $raw_depends_list = array_values(preg_grep($pkent['exclude_dependency'], PREG_GREP_INVERT));
286
                foreach($raw_depends_list as $adepend) {
287
                        $working_depend = explode(" ", $adepend);
288
                        //$working_depend = explode("-", $working_depend[1]);
289
                        $depend_filename = $working_depend[1] . $pkg_extension;
290
                        if(is_freebsd_pkg_installed($working_depend[1]) === false) {
291
                                pkg_fetch_recursive($working_depend[1], $depend_filename, $dependlevel + 1, $base_url);
292
                        } else {
293
                                $dependlevel++;
294
                                $static_output .= "\n" . str_repeat(" ", $dependlevel * 2) . $working_depend[1] . " ";
295
                                @fwrite($fd_log, $working_depend[1] . "\n");
296
                        }
297
                }
298
        }
299
        exec("cat {$g['tmp_path']}/y | /usr/sbin/pkg_add -fv {$fetchto} 2>&1", $pkgaddout);
300
        @fwrite($fd_log, $pkgname . " " . print_r($pkgaddout, true) . "\n");
301
        return true;
302
}
303

    
304
function download_file_with_progress_bar($url_file, $destination_file) {
305
        global $ch, $fout, $file_size, $downloaded, $counter, $pkg_interface;
306
        $file_size  = 1;
307
        $downloaded = 1;
308
        /* open destination file */
309
        $fout = fopen($destination_file, "wb");
310

    
311
        /*
312
                Originally by Author: Keyvan Minoukadeh
313
                Modified by Scott Ullrich to return Content-Length size
314
        */
315

    
316
        $ch = curl_init();
317
        curl_setopt($ch, CURLOPT_URL, $url_file);
318
        curl_setopt($ch, CURLOPT_HEADERFUNCTION, 'read_header');
319
        curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'read_body');
320
        curl_setopt($ch, CURLOPT_NOPROGRESS, '1');
321

    
322
        curl_exec($ch);
323
        fclose($fout);
324
        curl_close($ch);
325

    
326
        return 1;
327
}
328

    
329
function read_header($ch, $string) {
330
        global $file_size, $ch, $fout;
331
        $length = strlen($string);
332
        ereg("(Content-Length:) (.*)", $string, $regs);
333
        if($regs[2] <> "") {
334
                $file_size = intval($regs[2]);
335
        }
336
        return $length;
337
}
338

    
339
function read_body($ch, $string) {
340
        global $fout, $file_size, $downloaded, $counter, $sendto, $static_output, $lastseen, $pkg_interface;
341
        $length = strlen($string);
342
        $downloaded += intval($length);
343
        $downloadProgress = round(100 * (1 - $downloaded / $file_size), 0);
344
        $downloadProgress = 100 - $downloadProgress;
345
	if($lastseen <> $downloadProgress and $downloadProgress < 101) {
346
                if($sendto == "status") {
347
                        $tostatus = $static_status . $downloadProgress . "%";
348
                        update_status($tostatus);
349
                } else {
350
                        $tooutput = $static_output . $downloadProgress . "%";
351
                        update_output_window($tooutput);
352
                }
353
                update_progress_bar($downloadProgress);
354
                $lastseen = $downloadProgress;
355
        }
356
	fwrite($fout, $string);
357
	return $length;
358
}
359

    
360
function install_package($package, $pkg_info = "") {
361
	global $g, $config, $pkg_interface, $fd_log, $static_output;
362
	/* open logfiles and begin installation */
363
	if(!$fd_log) {
364
		if(!$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_{$pkg}.log", "w")) {
365
			update_output_window("Warning, could not open log for writing.");
366
		}
367
	}
368
	@fwrite($fd_log, "Beginning package installation.\n");
369
	log_error('Beginning package installation for ' . $package . '.');
370
	update_status("Beginning package installation for " . $package . "...");
371
	/* fetch package information if needed */
372
	if(!$pkg_info or !is_array($pkg_info[$package])) {
373
		$pkg_info = get_pkg_info(array($package));
374
		$pkg_info = $pkg_info[$package]; // We're only dealing with one package, so we can strip away the extra array.
375
	}
376
	/* set up package logging streams */
377
	if($pkg_info['logging']) {
378
		mwexec("/usr/sbin/clog -i -s 32768 {$g['varlog_path']}/{$pkg_info['logging']['logfilename']}");
379
		chmod($g['varlog_path'] . '/' . $pkg_info['logging']['logfilename'], 0600);
380
		@fwrite($fd_log, "Adding text to file /etc/syslog.conf\n");
381
		system_syslogd_start();
382
	}
383
	/* fetch the package's configuration file */
384
	if($pkg_info['config_file'] != "") {
385
		$static_output .= "Downloading package configuration file... ";
386
		update_output_window($static_output);
387
		@fwrite($fd_log, "Downloading package configuration file...\n");
388
		$fetchto = substr(strrchr($pkg_info['config_file'], '/'), 1);
389
		download_file_with_progress_bar($pkg_info['config_file'], '/usr/local/pkg/' . $fetchto);
390
		if(!file_exists('/usr/local/pkg/' . $fetchto)) {
391
			@fwrite($fd_log, "ERROR! Unable to fetch package configuration file. Aborting installation.\n");
392
			if($pkg_interface == "console") {
393
				print "\nERROR! Unable to fetch package configuration file. Aborting package installation.\n";
394
				return;
395
			} else {
396
				$static_output .= "failed!\n\nInstallation aborted.";
397
				update_output_window($static_output);
398
				echo "<br>Show <a href=\"pkg_mgr_install.php?showlog=true\">install log</a></center>";
399
			 	exit;
400
			}
401
		}
402
		$static_output .= "done.\n";
403
		update_output_window($static_output);
404
	}
405
	/* make 'y' file */
406
	$fd = fopen("{$g['tmp_path']}/y", "w");
407
	for($line = 0; $line < 10; $line++) {
408
		fwrite($fd, "y\n");
409
	}
410
	fclose($fd);
411

    
412
	/* pkg_add the package and its dependencies */
413
	if($pkg_info['depends_on_package_base_url'] != "") {
414
		update_status("Installing " . $pkg_info['name'] . " and its dependencies.");
415
		$static_output .= "Downloading " . $pkg_info['name'] . " and its dependencies... ";
416
		$static_orig = $static_output;
417
		$static_output .= "\n";
418
		update_output_window($static_output);
419
		$pkg_name = substr(reverse_strrchr($pkg_info['depends_on_package'], "."), 0, -1);
420
		if(isset($pkg_info['skip_install_checks'])) {
421
			$pkg_installed = true;
422
		} else {
423
			$pkg_installed = is_freebsd_pkg_installed($pkg_name);
424
		}
425
		if($pkg_installed == false) pkg_fetch_recursive($pkg_name, $pkg_info['depends_on_package'], 0, $pkg_info['depends_on_package_base_url']);
426
		$static_output = $static_orig . "done.\nChecking for successful package installation... ";
427
		update_output_window($static_output);
428
		/* make sure our package was successfully installed */
429
		if($pkg_installed == false) $pkg_installed = is_freebsd_pkg_installed($pkg_name);
430
		if($pkg_installed == true) {
431
			$static_output .= "done.\n";
432
			update_output_window($static_output);
433
			fwrite($fd_log, "pkg_add successfully completed.\n");
434
		} else {
435
			$static_output .= "failed!\n\nInstallation aborted.";
436
			update_output_window($static_output);
437
			fwrite($fd_log, "Package WAS NOT installed properly.\n");
438
			fclose($fd_log);
439
			echo "\n<script language=\"JavaScript\">document.progressbar.style.visibility='hidden';</script>";
440
			echo "\n<script language=\"JavaScript\">document.progholder.style.visibility='hidden';</script>";
441
			sleep(1);
442
			die;
443
		}
444
	}
445
	/* add package information to config.xml */
446
	$pkgid = get_pkg_id($pkg_info['name']);
447
	$static_output .= "Saving updated package information... ";
448
	update_output_window($static_output);
449
	if($pkgid == -1) {
450
		$config['installedpackages']['package'][] = $pkg_info;
451
		$changedesc = "Installed {$pkg_info['name']} package.";
452
		$to_output = "done.\n";
453
	} else {
454
		$config['installedpackages']['package'][$pkgid] = $pkg_info;
455
		$changedesc = "Overwrote previous installation of {$pkg_info['name']}.";
456
		$to_output = "overwrite!\n";
457
	}
458
	$static_output .= $to_output;
459
	update_output_window($static_output);
460
	/* install other package components */
461
	install_package_xml($package);
462
	$static_output .= "Writing configuration... ";
463
	update_output_window($static_output);
464
	write_config($changedesc);
465
	$static_output .= "done.";
466
	update_output_window($static_output);
467
}
468

    
469
function eval_once($toeval) {
470
	global $evaled;
471
	if(!$evaled) $evaled = array();
472
	$evalmd5 = md5($toeval);
473
	if(!in_array($evalmd5, $evaled)) {
474
		eval($toeval);
475
		$evaled[] = $evalmd5;
476
	}
477
	return;
478
}
479
	
480

    
481
function install_package_xml($pkg) {
482
	global $g, $config, $fd_log, $static_output;
483
	if(($pkgid = get_pkg_id($pkg)) == -1) {
484
		$static_output .= "The {$pkg} package is not installed.\n\nInstallation aborted.";
485
		update_output_window($static_output);
486
		echo "\n<script language=\"JavaScript\">document.progressbar.style.visibility='hidden';</script>";
487
		echo "\n<script language=\"JavaScript\">document.progholder.style.visibility='hidden';</script>";
488
		sleep(1);
489
		return;
490
	} else {
491
		$pkg_info = $config['installedpackages']['package'][$pkgid];
492
	}
493
	/* set up logging if needed */
494
	if(!$fd_log) {
495
		if(!$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_{$pkg}.log", "w")) {
496
			update_output_window("Warning, could not open log for writing.");
497
		}
498
	}
499

    
500
	$configfile = substr(strrchr($pkg_info['config_file'], '/'), 1);
501
	if(file_exists("/usr/local/pkg/" . $configfile)) {
502
		$static_output .= "Loading package configuration... ";
503
		update_output_window($static_output);
504
		$pkg_config = parse_xml_config("/usr/local/pkg/" . $configfile, "packagegui");
505
		$static_output .= "done.\n";
506
		update_output_window($static_output);
507
		$static_output .= "Configuring package components...\n";
508
		update_output_window($static_output);
509
		/* modify system files */
510
		if($pkg_config['modify_system']['item'] <> "") {
511
			$static_output .= "\tSystem files... ";
512
			update_output_window($static_output);
513
			foreach($pkg_config['modify_system']['item'] as $ms) {
514
				if($ms['textneeded']) {
515
					add_text_to_file($ms['modifyfilename'], $ms['textneeded']);
516
				}
517
			}
518
			$static_output .= "done.\n";
519
			update_output_window($static_output);
520
		}
521
		/* download additional files */
522
		if($pkg_config['additional_files_needed'] <> "") {
523
			$static_output .= "\tAdditional files... ";
524
			$static_orig = $static_output;
525
			update_output_window($static_output);
526
			foreach($pkg_config['additional_files_needed'] as $afn) {
527
				$filename = get_filename_from_url($afn['item'][0]);
528
				if($afn['chmod'] <> "") {
529
					$pkg_chmod = $afn['chmod'];
530
				} else {
531
					$pkg_chmod = "";
532
				}
533
				if($afn['prefix'] <> "") {
534
					$prefix = $afn['prefix'];
535
				} else {
536
					$prefix = "/usr/local/pkg/";
537
				}
538
				$static_output .= $filename . " ";
539
                                update_output_window($static_output);
540
				download_file_with_progress_bar($afn['item'][0], $prefix . $filename);
541
				if(stristr($filename, ".tgz") <> "") {
542
					fwrite($fd_log, "Extracting tarball to -C for " . $filename . "...\n");
543
					exec("/usr/bin/tar xvzf " . $prefix . $filename . " -C / 2>&1", $tarout);
544
					fwrite($fd_log, print_r($tarout, true) . "\n");
545
				}
546
				if($pkg_chmod <> "") {
547
					fwrite($fd_log, "Changing file mode to {$pkg_chmod} for {$prefix}{$filename}\n");
548
					chmod($prefix . $filename, $pkg_chmod);
549
					system("/bin/chmod {$pkg_chmod} {$prefix}{$filename}");
550
				}
551
				$static_output = $static_orig;
552
                                update_output_window($static_output);
553
			}
554
			$static_output .= "done.\n";
555
			update_output_window($static_output);
556
		}
557
		/* sidebar items */
558
		if($pkg_config['menu'] != "") {
559
			$static_output .= "\tMenu items... ";
560
			update_output_window($static_output);
561
			foreach($pkg_config['menu'] as $menu) {
562
				$config['installedpackages']['menu'][] = $menu;
563
			}
564
			$static_output .= "done.\n";
565
			update_output_window($static_output);
566
		}
567
		/* custom commands */
568
		if($pkg_config['custom_php_install_command'] <> "") {
569
			$static_output .= "\tCustom commands... ";
570
			update_output_window($static_output);
571
			if($pkg_config['custom_php_global_functions'] <> "") {
572
				eval_once($pkg_config['custom_php_global_functions']);
573
			}
574
			fwrite($fd_log, "Executing post install commands...\n");
575
			eval_once($pkg_config['custom_php_install_command']);
576
			$static_output .= "done.\n";
577
			update_output_window($static_output);
578
		}
579
		/* call our before form property since we may be declaring functions
580
		   in it that are called later */
581
		if($pkg_config['custom_php_command_before_form'] <> "") {
582
			eval_once($pkg_config['custom_php_command_before_form']);
583
		}
584
		/* call our resync function */
585
		if($pkg_config['custom_php_resync_config_command'] <> "") {
586
			eval_once($pkg_config['custom_php_resync_config_command']);
587
		}
588
	} else {
589
		$static_output .= "Loading package configuration... failed!\n\nInstallation aborted.";
590
		update_output_window($static_output);
591
		fwrite($fd_log, "Unable to load package configuration. Installation aborted.\n");
592
                fclose($fd_log);
593
                echo "\n<script language=\"JavaScript\">document.progressbar.style.visibility='hidden';</script>";
594
                echo "\n<script language=\"JavaScript\">document.progholder.style.visibility='hidden';</script>";
595
                sleep(1);
596
		return;
597
	}
598
}
599

    
600
function delete_package($pkg) {
601
	global $g, $config, $fd_log, $static_output;
602
	update_status("Removing package...");
603
	$static_output .= "Removing package... ";
604
	update_output_window($static_output);
605
	delete_package_recursive($pkg);
606
	$static_output .= "done.\n";
607
	update_output_window($static_output);
608
	return;
609
}
610

    
611
function delete_package_recursive($pkg) {
612
	exec("/usr/sbin/pkg_info -r " . $pkg . " 2>&1", $info);
613
	exec("cat {$g['tmp_path']}/y | /usr/sbin/pkg_delete " . $pkg ." > /dev/null 2>&1");
614
	exec("/bin/ls /var/db/pkg", $pkgdb);
615
	if(stristr($info[0], "can't find package") != false) return;
616
	foreach($info as $line) {
617
		$depend = trim(array_pop(explode(":", $line)));
618
		if(in_array($depend, $pkgdb)) delete_package_recursive($depend);
619
	}
620
	$fd = fopen("{$g['tmp_path']}/y", "w");
621
	for($line = 0; $line < 10; $line++) {
622
		fwrite($fd, "y\n");
623
	}
624
	fclose($fd);
625
	return;
626
}
627

    
628
function delete_package_xml($pkg) {
629
	global $g, $config, $fd_log, $static_output;
630
	if(($pkgid = get_pkg_id($pkg)) == -1) {
631
                $static_output .= "The {$pkg} package is not installed.\n\nDeletion aborted.";
632
                update_output_window($static_output);
633
                echo "\n<script language=\"JavaScript\">document.progressbar.style.visibility='hidden';</script>";
634
                echo "\n<script language=\"JavaScript\">document.progholder.style.visibility='hidden';</script>";
635
                sleep(1);
636
                return;
637
        }
638
	/* set up logging if needed */
639
        if(!$fd_log) {
640
                if(!$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_{$pkg}.log", "w")) {
641
                        update_output_window("Warning, could not open log for writing.");
642
                }
643
        }
644
	update_status("Removing {$pkg} components...");
645
	fwrite($fd_log, "Removing {$pkg} package... ");
646
	$static_output .= "Removing {$pkg} components...\n";
647
	update_output_window($static_output);
648
	/* parse package configuration */
649
	$packages = &$config['installedpackages']['package'];
650
	$menus = &$config['installedpackages']['menu'];
651
	if(file_exists("/usr/local/pkg/" . $packages[$pkgid]['configurationfile'])) {
652
		$pkg_config = parse_xml_config("/usr/local/pkg/" . $packages[$pkgid]['configurationfile'], "packagegui");
653
		/* remove menu items */
654
		if(is_array($pkg_config['menu'])) {
655
			$static_output .= "\tMenu items... ";
656
			update_output_window($static_output);
657
			foreach($menus as $menu) $instmenus[] = $menu['name'];
658
			foreach($pkg_config['menu'] as $menu) {
659
				foreach($instmenus as $key => $instmenu) {
660
					if($instmenu == $menu['name']) unset($menus[$key]);
661
				}
662
			}
663
			$static_output .= "done.\n";
664
			update_output_window($static_output);
665
		}
666
		/* evalate this package's global functions and pre deinstall commands */
667
		if($pkg_config['custom_php_global_functions'] <> "")
668
			eval_once($pkg_config['custom_php_global_functions']);
669
		if($pkg_config['custom_php_pre_deinstall_command'] <> "") 
670
			eval_once($pkg_config['custom_php_pre_deinstall_command']);
671
		/* remove all additional files */
672
		if($pkg_config['additional_files_needed'] <> "") {
673
			$static_output .= "\tAuxiliary files... ";
674
			update_output_window($static_output);
675
			foreach($pkg_config['additional_files_needed'] as $afn) {
676
				$filename = get_filename_from_url($afn['item'][0]);
677
				if($afn['prefix'] <> "") {
678
					$prefix = $afn['prefix'];
679
				} else {
680
					$prefix = "/usr/local/pkg/";
681
				}
682
				unlink_if_exists($prefix . $filename);
683
				if(file_exists($prefix . $filename))
684
				    mwexec("rm -rf {$prefix}{$filename}");
685
			}
686
			$static_output .= "done.\n";
687
			update_output_window($static_output);
688
		}
689
		/* system files */
690
		if($pkg_config['modify_system']['item'] <> "") {
691
			$static_output .= "\tSystem files... ";
692
			update_output_window($static_output);
693
			foreach($pkg_config['modify_system']['item'] as $ms) {
694
				if($ms['textneeded']) remove_text_from_file($ms['modifyfilename'], $ms['textneeded']);
695
			}
696
			$static_output .= "done.\n";
697
			update_output_window($static_output);
698
		}
699
		/* syslog */
700
		if($pkg_config['logging']['logfile_name'] <> "") {
701
			$static_output .= "\tSyslog entries... ";
702
			update_output_window($static_output);
703
			remove_text_from_file("/etc/syslog.conf", $pkg_config['logging']['facilityname'] . "\t\t\t\t" . $pkg_config['logging']['logfilename']);
704
			$static_output .= "done.\n";
705
			update_output_window($static_output);
706
		}
707
		/* deinstall commands */
708
		if($pkg_config['custom_php_deinstall_command'] <> "") {
709
			$static_output .= "\tDeinstall commands... ";
710
			update_output_window($static_output);
711
			eval_once($pkg_config['custom_php_deinstall_command']);
712
			$static_output .= "done.\n";
713
			update_output_window($static_output);
714
		}
715
		/* package XML file */
716
		$static_output .= "\tPackage XML... ";
717
		update_output_window($static_output);
718
		unlink_if_exists("/usr/local/pkg/" . $packages[$pkgid]['configurationfile']);
719
		$static_output .= "done.\n";
720
		update_output_window($static_output);
721
	}
722
	/* remove config.xml entries */
723
	$static_output .= "\tConfiguration... ";
724
	update_output_window($static_output);
725
	unset($config['installedpackages']['package'][$pkgid]);
726
	$static_output .= "done.\n";
727
	update_output_window($static_output);
728
	write_config("Removed {$pkg} package.");
729
	/* file cleanup */
730
	$ctag = file("/etc/crontab");
731
	foreach($ctag as $line) {
732
		if(trim($line) != "") $towrite[] = $line;
733
	}
734
	$tmptab = fopen("/tmp/crontab", "w");
735
	foreach($towrite as $line) {
736
		fwrite($tmptab, $line);
737
	}
738
	fclose($tmptab);
739
	rename("/tmp/crontab", "/etc/crontab");
740
}
741

    
742
function expand_to_bytes($size) {
743
	$conv = array(
744
			"G" =>	"3",
745
			"M" =>  "2",
746
			"K" =>  "1",
747
			"B" =>  "0"
748
		);
749
	$suffix = substr($size, -1);
750
	if(!in_array($suffix, array_keys($conv))) return $size;
751
	$size = substr($size, 0, -1);
752
	for($i = 0; $i < $conv[$suffix]; $i++) {
753
		$size *= 1024;
754
	}
755
	return $size;
756
}
757

    
758
function get_pkg_db() {
759
	global $g;
760
	return return_dir_as_array($g['vardb_path'] . '/pkg');
761
}
762

    
763
function walk_depend($depend, $pkgdb = "", $alreadyseen = "") {
764
	if(!$pkgdb) $pkgdb = get_pkg_db();
765
	if(!$alreadyseen) $alreadyseen = array();
766
	foreach($depend as $adepend) {
767
		$pkgname = reverse_strrchr($adepend['name'], '.');
768
		if(in_array($pkgname, $alreadyseen)) {
769
			continue;
770
		} elseif(!in_array($pkgname, $pkgdb)) {
771
			$size += expand_to_bytes($adepend['size']);
772
			$alreadyseen[] = $pkgname;
773
			if(is_array($adepend['depend'])) $size += walk_depend($adepend['depend'], $pkgdb, $alreadyseen);
774
		} else {
775
			continue;
776
		}
777
	}
778
	return $size;
779
}
780

    
781
function get_package_install_size($pkg = 'all', $pkg_info = "") {
782
	global $config, $g;
783
	if((!is_array($pkg)) and ($pkg != 'all')) $pkg = array($pkg);
784
	$pkgdb = get_pkg_db();
785
	if(!$pkg_info) $pkg_info = get_pkg_sizes($pkg);
786
	foreach($pkg as $apkg) {
787
		$size = 0;
788
		if(!$pkg_info[$apkg]) continue;
789
		$toreturn[$apkg] = expand_to_bytes(walk_depend(array($pkg_info[$apkg]), $pkgdb));
790
	}
791
	return $toreturn;
792
}
793

    
794
function squash_from_bytes($size, $round = "") {
795
	$conv = array(1 => "B", "K", "M", "G");
796
	foreach($conv as $div => $suffix) {
797
		$sizeorig = $size;
798
		if(($size /= 1024) < 1) {
799
			if($round) {
800
				$sizeorig = round($sizeorig, $round);
801
			}
802
			return $sizeorig . $suffix;
803
		}
804
	}
805
	return;
806
}
807
?>
(12-12/21)