Project

General

Profile

Download (43.2 KB) Statistics
| Branch: | Tag: | Revision:
1 7597c8e8 Colin Smith
<?php
2 1262d7e7 Renato Botelho
/*
3
 * pkg-utils.inc
4 a2febf9a Stephen Beaver
 *
5 ac24dc24 Renato Botelho
 * part of pfSense (https://www.pfsense.org)
6
 * Copyright (c) 2005-2006 Colin Smith (ethethlay@gmail.com)
7 38809d47 Renato Botelho do Couto
 * Copyright (c) 2004-2013 BSD Perimeter
8
 * Copyright (c) 2013-2016 Electric Sheep Fencing
9 8f585441 Luiz Souza
 * Copyright (c) 2014-2021 Rubicon Communications, LLC (Netgate)
10 ac24dc24 Renato Botelho
 * All rights reserved.
11 a2febf9a Stephen Beaver
 *
12 b12ea3fb Renato Botelho
 * Licensed under the Apache License, Version 2.0 (the "License");
13
 * you may not use this file except in compliance with the License.
14
 * You may obtain a copy of the License at
15 a2febf9a Stephen Beaver
 *
16 b12ea3fb Renato Botelho
 * http://www.apache.org/licenses/LICENSE-2.0
17 a2febf9a Stephen Beaver
 *
18 b12ea3fb Renato Botelho
 * Unless required by applicable law or agreed to in writing, software
19
 * distributed under the License is distributed on an "AS IS" BASIS,
20
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21
 * See the License for the specific language governing permissions and
22
 * limitations under the License.
23 8c6516d1 Colin Smith
 */
24 523855b0 Scott Ullrich
25 01a6e665 Ermal
require_once("globals.inc");
26 7eea4407 Ermal
require_once("service-utils.inc");
27 1e8644ca Renato Botelho
28 49aec489 Phil Davis
if (file_exists("/cf/conf/use_xmlreader")) {
29 093bcebc Scott Ullrich
	require_once("xmlreader.inc");
30 49aec489 Phil Davis
} else {
31 093bcebc Scott Ullrich
	require_once("xmlparse.inc");
32 49aec489 Phil Davis
}
33 33b7cc0d Colin Smith
34 1e8644ca Renato Botelho
require_once("pfsense-utils.inc");
35 b47833cc Scott Ullrich
36 eab543ed Ermal
if (!function_exists("pkg_debug")) {
37
	/* set up logging if needed */
38
	function pkg_debug($msg) {
39
		global $g, $debug, $fd_log;
40
41 49aec489 Phil Davis
		if (!$debug) {
42 eab543ed Ermal
			return;
43 49aec489 Phil Davis
		}
44 eab543ed Ermal
45
		if (!$fd_log) {
46 0c9d489e Renato Botelho do Couto
			$fd_log = fopen("{$g['tmp_path']}/pkg_mgr_debug.log",
47
			    "w");
48
		}
49
50
		if (!$fd_log) {
51
			update_status(gettext("Warning, could not open log " .
52
			    "for writing.") . "\n");
53 7489746e Renato Botelho do Couto
			return;
54 eab543ed Ermal
		}
55
		@fwrite($fd_log, $msg);
56
	}
57
}
58
59 c078dd89 Renato Botelho
/* Validate if pkg name is valid */
60
function pkg_valid_name($pkgname) {
61
	global $g;
62
63
	$pattern = "/^{$g['pkg_prefix']}[a-zA-Z0-9\.\-_]+$/";
64
	return preg_match($pattern, $pkgname);
65
}
66
67 c2eb2508 Renato Botelho
/* Remove pkg_prefix from package name if it's present */
68
function pkg_remove_prefix(&$pkg_name) {
69
	global $g;
70
71 0c9d489e Renato Botelho do Couto
	if (substr($pkg_name, 0, strlen($g['pkg_prefix'])) ==
72
	    $g['pkg_prefix']) {
73 c2eb2508 Renato Botelho
		$pkg_name = substr($pkg_name, strlen($g['pkg_prefix']));
74
	}
75 e7405fbf Scott Ullrich
}
76 33b7cc0d Colin Smith
77 d3ff1e59 Renato Botelho
/* Execute pkg update when it's necessary */
78
function pkg_update($force = false) {
79
	global $g;
80
81 6cf87aec Renato Botelho
	return pkg_call("update" . ($force ? " -f" : ""));
82 d3ff1e59 Renato Botelho
}
83
84 75bb92c4 Renato Botelho
/* return an array with necessary environment vars for pkg */
85 a948633c Renato Botelho
function pkg_env($extra_env = array()) {
86 75bb92c4 Renato Botelho
	global $config, $g;
87
88 573ec19d Renato Botelho do Couto
	$user_agent = $g['product_label'] . '/' . $g['product_version'];
89 2bf67a6f Renato Botelho
	if (!isset($config['system']['do_not_send_uniqueid'])) {
90 6cc74faa Renato Botelho
		$user_agent .= ':' . system_get_uniqueid();
91 d49ad309 Renato Botelho
	}
92
93 75bb92c4 Renato Botelho
	$pkg_env_vars = array(
94 e21ac870 Renato Botelho
		"LANG" => "C",
95 75bb92c4 Renato Botelho
		"HTTP_USER_AGENT" => $user_agent,
96 a120c849 Renato Botelho
		"ASSUME_ALWAYS_YES" => "true",
97
		"FETCH_TIMEOUT" => 5,
98
		"FETCH_RETRY" => 2
99 75bb92c4 Renato Botelho
	);
100
101 a7fcbc1e jim-p
	if (!empty($config['system']['proxyurl'])) {
102
		$http_proxy = $config['system']['proxyurl'];
103
		if (!empty($config['system']['proxyport'])) {
104
			$http_proxy .= ':' . $config['system']['proxyport'];
105
		}
106
		$pkg_env_vars['HTTP_PROXY'] = $http_proxy;
107 1060378f jim-p
108 0c9d489e Renato Botelho do Couto
		if (!empty($config['system']['proxyuser']) &&
109
		    !empty($config['system']['proxypass'])) {
110
			$pkg_env_vars['HTTP_PROXY_AUTH'] = "basic:*:" .
111
			    $config['system']['proxyuser'] . ":" .
112
			    $config['system']['proxypass'];
113 1060378f jim-p
		}
114 a7fcbc1e jim-p
	}
115
116 0c9d489e Renato Botelho do Couto
	if (isset($config['system']['use_mfs_tmpvar']) &&
117
	    !file_exists("/conf/ram_disks_failed")) {
118 75bb92c4 Renato Botelho
		$pkg_env_vars['PKG_DBDIR'] = '/root/var/db/pkg';
119
		$pkg_env_vars['PKG_CACHEDIR'] = '/root/var/cache/pkg';
120
	}
121
122 a948633c Renato Botelho
	foreach ($extra_env as $key => $value) {
123
		$pkg_env_vars[$key] = $value;
124
	}
125
126 75bb92c4 Renato Botelho
	return $pkg_env_vars;
127
}
128
129 c2eb2508 Renato Botelho
/* Execute a pkg call */
130 a948633c Renato Botelho
function pkg_call($params, $mute = false, $extra_env = array()) {
131 e791dee8 Renato Botelho
	global $g, $config;
132 6fd37d04 Renato Botelho
133 c2eb2508 Renato Botelho
	if (empty($params)) {
134
		return false;
135
	}
136
137 6fd37d04 Renato Botelho
	$descriptorspec = array(
138
		1 => array("pipe", "w"), /* stdout */
139 a2febf9a Stephen Beaver
		2 => array("pipe", "w")	 /* stderr */
140 6fd37d04 Renato Botelho
	);
141
142
	pkg_debug("pkg_call(): {$params}\n");
143 58e60eb9 Renato Botelho
	$process = proc_open("/usr/local/sbin/pkg-static {$params}",
144
	    $descriptorspec, $pipes, '/', pkg_env($extra_env));
145 6fd37d04 Renato Botelho
146
	if (!is_resource($process)) {
147
		return false;
148
	}
149
150
	stream_set_blocking($pipes[1], 0);
151
	stream_set_blocking($pipes[2], 0);
152
153 f3f98e97 Phil Davis
	/* XXX: should be a tunable? */
154 9c91c7bd doktornotor
	$timeout = 60; // seconds
155 6fd37d04 Renato Botelho
	$error_log = '';
156
157
	do {
158
		$write = array();
159
		$read = array($pipes[1], $pipes[2]);
160
		$except = array();
161
162 e1a6074d Renato Botelho
		$stream = @stream_select($read, $write, $except, $timeout);
163 6fd37d04 Renato Botelho
		if ($stream !== FALSE && $stream > 0) {
164
			foreach ($read as $pipe) {
165
				$content = stream_get_contents($pipe);
166
				if ($content == '') {
167
					continue;
168
				}
169
				if ($pipe === $pipes[1]) {
170
					if (!$mute) {
171 e791dee8 Renato Botelho
						update_status($content);
172 6fd37d04 Renato Botelho
					}
173
					flush();
174
				} else if ($pipe === $pipes[2]) {
175
					$error_log .= $content;
176
				}
177
			}
178 49aec489 Phil Davis
		}
179 a2febf9a Stephen Beaver
180 6fd37d04 Renato Botelho
		$status = proc_get_status($process);
181
	} while ($status['running']);
182 a2febf9a Stephen Beaver
183 6fd37d04 Renato Botelho
	fclose($pipes[1]);
184
	fclose($pipes[2]);
185
	proc_close($process);
186
187 4b834523 Renato Botelho
188 1c981897 Renato Botelho
	$rc = $status['exitcode'];
189 6fd37d04 Renato Botelho
190
	pkg_debug("pkg_call(): rc = {$rc}\n");
191
	if ($rc == 0) {
192
		return true;
193
	}
194
195
	pkg_debug("pkg_call(): error_log\n{$error_log}\n");
196
	if (!$mute) {
197 0c9d489e Renato Botelho do Couto
		update_status("\n\n" . sprintf(gettext("ERROR!!! An error " .
198
		    "occurred on pkg execution (rc = %d) with parameters " .
199
		    "'%s':"), $rc, $params) . "\n" . $error_log . "\n");
200 49aec489 Phil Davis
	}
201 a2febf9a Stephen Beaver
202 6fd37d04 Renato Botelho
	return false;
203 31e7e1bc Scott Ullrich
}
204
205 6fd37d04 Renato Botelho
/* Execute pkg with $params, fill stdout and stderr and return pkg rc */
206 a948633c Renato Botelho
function pkg_exec($params, &$stdout, &$stderr, $extra_env = array()) {
207 96bf5038 Renato Botelho
	global $g, $config;
208 6fd37d04 Renato Botelho
209
	if (empty($params)) {
210
		return -1;
211
	}
212
213
	$descriptorspec = array(
214
		1 => array("pipe", "w"), /* stdout */
215 a2febf9a Stephen Beaver
		2 => array("pipe", "w")	 /* stderr */
216 6fd37d04 Renato Botelho
	);
217
218 4b834523 Renato Botelho
219 6fd37d04 Renato Botelho
	pkg_debug("pkg_exec(): {$params}\n");
220 58e60eb9 Renato Botelho
	$process = proc_open("/usr/local/sbin/pkg-static {$params}",
221
	    $descriptorspec, $pipes, '/', pkg_env($extra_env));
222 6fd37d04 Renato Botelho
223
	if (!is_resource($process)) {
224
		return -1;
225
	}
226
227
	$stdout = '';
228
	while (($l = fgets($pipes[1])) !== FALSE) {
229
		$stdout .= $l;
230
	}
231
	fclose($pipes[1]);
232
233
	$stderr = '';
234
	while (($l = fgets($pipes[2])) !== FALSE) {
235
		$stderr .= $l;
236
	}
237
	fclose($pipes[2]);
238 c2eb2508 Renato Botelho
239 4b834523 Renato Botelho
240 6fd37d04 Renato Botelho
	return proc_close($process);
241 c2eb2508 Renato Botelho
}
242
243 8df1877b Renato Botelho
/* Compare 2 pkg versions and return:
244
 * '=' - versions are the same
245
 * '>' - $v1 > $v2
246
 * '<' - $v1 < $v2
247
 * '?' - Error
248
 */
249
function pkg_version_compare($v1, $v2) {
250
	if (empty($v1) || empty($v2)) {
251
		return '?';
252
	}
253
254 500dfdb8 Renato Botelho
	$rc = pkg_exec("version -t '{$v1}' '{$v2}'", $stdout, $stderr);
255 8df1877b Renato Botelho
256
	if ($rc != 0) {
257
		return '?';
258
	}
259
260
	return str_replace("\n", "", $stdout);
261
}
262
263 c2eb2508 Renato Botelho
/* Check if package is installed */
264
function is_pkg_installed($pkg_name) {
265
	global $g;
266
267 f5b1c660 Renato Botelho
	if (empty($pkg_name)) {
268
		return false;
269
	}
270 c2eb2508 Renato Botelho
271 500dfdb8 Renato Botelho
	return pkg_call("info -e " . $pkg_name, true);
272 c2eb2508 Renato Botelho
}
273
274 7379d80f Renato Botelho
/* Install package, $pkg_name should not contain prefix */
275 46903fb9 Renato Botelho
function pkg_install($pkg_name, $force = false) {
276 7379d80f Renato Botelho
	global $g;
277 e7553e1b Renato Botelho
	$result = false;
278 7379d80f Renato Botelho
279 f5b1c660 Renato Botelho
	$shortname = $pkg_name;
280
	pkg_remove_prefix($shortname);
281 7379d80f Renato Botelho
282 46903fb9 Renato Botelho
	$pkg_force = "";
283
	if ($force) {
284
		$pkg_force = "-f ";
285
	}
286
287 f5b1c660 Renato Botelho
	pkg_debug("Installing package {$shortname}\n");
288 46903fb9 Renato Botelho
	if ($force || !is_pkg_installed($pkg_name)) {
289 f5b1c660 Renato Botelho
		$result = pkg_call("install -y " . $pkg_force . $pkg_name);
290 f3f98e97 Phil Davis
		/* Cleanup cache to free disk space */
291 e7553e1b Renato Botelho
		pkg_call("clean -y");
292 7379d80f Renato Botelho
	}
293
294 e7553e1b Renato Botelho
	return $result;
295 7379d80f Renato Botelho
}
296
297 c2eb2508 Renato Botelho
/* Delete package from FreeBSD, $pkg_name should not contain prefix */
298
function pkg_delete($pkg_name) {
299
	global $g;
300
301 f5b1c660 Renato Botelho
	$shortname = $pkg_name;
302
	pkg_remove_prefix($shortname);
303 c2eb2508 Renato Botelho
304 f5b1c660 Renato Botelho
	pkg_debug("Removing package {$shortname}\n");
305 c2eb2508 Renato Botelho
	if (is_pkg_installed($pkg_name)) {
306 f5b1c660 Renato Botelho
		pkg_call("delete -y " . $pkg_name);
307 f3f98e97 Phil Davis
		/* Cleanup unnecessary dependencies */
308 e1382589 Renato Botelho
		pkg_call("autoremove -y");
309 49aec489 Phil Davis
	}
310 8c6516d1 Colin Smith
}
311 43db85f8 Scott Ullrich
312 af5d93f6 Renato Botelho
/* Check if package is present in config.xml */
313
function is_package_installed($package_name) {
314
	return (get_package_id($package_name) != -1);
315 8c6516d1 Colin Smith
}
316 43db85f8 Scott Ullrich
317 af5d93f6 Renato Botelho
/* Find package array index */
318
function get_package_id($package_name) {
319 e65a287f Scott Ullrich
	global $config;
320
321 bfd3334b jim-p
	if (!isset($config['installedpackages']['package']) ||
322
	    !is_array($config['installedpackages']['package'])) {
323 af5d93f6 Renato Botelho
		return -1;
324
	}
325
326
	foreach ($config['installedpackages']['package'] as $idx => $pkg) {
327 a50534b6 Renato Botelho
		if ($pkg['name'] == $package_name ||
328 4e322e2c Phil Davis
		    get_package_internal_name($pkg) == $package_name) {
329 af5d93f6 Renato Botelho
			return $idx;
330 e65a287f Scott Ullrich
		}
331
	}
332 af5d93f6 Renato Botelho
333 e65a287f Scott Ullrich
	return -1;
334 8c6516d1 Colin Smith
}
335
336 af5d93f6 Renato Botelho
/* Return internal_name when it's defined, otherwise, returns name */
337
function get_package_internal_name($package_data) {
338 0c9d489e Renato Botelho do Couto
	if (isset($package_data['internal_name']) &&
339
	    ($package_data['internal_name'] != "")) {
340 75a01a7c Phil Davis
		/* e.g. name is Ipguard-dev, internal name is ipguard */
341 af5d93f6 Renato Botelho
		return $package_data['internal_name'];
342 75a01a7c Phil Davis
	} else {
343 af5d93f6 Renato Botelho
		return $package_data['name'];
344 75a01a7c Phil Davis
	}
345
}
346
347 a2febf9a Stephen Beaver
// Get information about packages.
348 4333564a Renato Botelho
function get_pkg_info($pkgs = 'all', $remote_repo_usage_disabled = false,
349
    $installed_pkgs_only = false) {
350 e791dee8 Renato Botelho
	global $g, $input_errors;
351 b2a66231 Ermal
352 04daf8b1 stilez
	$out = $err = $extra_param = '';
353 587988f6 stilez
	$rc = 0;
354 e65a287f Scott Ullrich
355 d65fc2ff Renato Botelho
	unset($pkg_filter);
356 04daf8b1 stilez
357 d65fc2ff Renato Botelho
	if (is_array($pkgs)) {
358
		$pkg_filter = $pkgs;
359 e87ea36d Renato Botelho
		$pkgs = $g['pkg_prefix'] . '*';
360
	} elseif ($pkgs == 'all') {
361
		$pkgs = $g['pkg_prefix'] . '*';
362 65c94077 Renato Botelho
	}
363 e87ea36d Renato Botelho
364 283e8d24 Renato Botelho
	$base_packages = (substr($pkgs, 0, strlen($g['pkg_prefix'])) !=
365
	    $g['pkg_prefix']);
366 07152ca7 Steve Beaver
367 dd6ecfa2 Phil Davis
	if ($installed_pkgs_only && !is_pkg_installed($pkgs)) {
368 a835cdee Renato Botelho
		/*
369
		 * Return early if the caller wants just installed packages
370
		 * and there are none.  Saves doing any calls that might
371
		 * access a remote package repo.
372
		 */
373 dd6ecfa2 Phil Davis
		return array();
374
	}
375
376 9b7cfb3f Renato Botelho
	if (!function_exists('is_subsystem_dirty')) {
377
		require_once("util.inc");
378
	}
379
380
	/* Do not run remote operations if pkg has a lock */
381
	if (is_subsystem_dirty('pkg')) {
382 04daf8b1 stilez
		$remote_repo_usage_disabled = true;
383 9b7cfb3f Renato Botelho
		$lock = false;
384
	} else {
385
		$lock = true;
386
	}
387
388
	if ($lock) {
389
		mark_subsystem_dirty('pkg');
390
	}
391 587988f6 stilez
392 04daf8b1 stilez
	if ($remote_repo_usage_disabled) {
393
		$extra_param = "-U ";
394
	}
395
396 eaed7e74 Renato Botelho
	$did_search = false;
397 a9b0a7a3 Renato Botelho
	$search_rc = 0;
398
	$info_rc = 0;
399
	$search_items = array();
400
	$info_items = array();
401
402 283e8d24 Renato Botelho
	if ($base_packages) {
403
		$repo_param = "";
404
	} else {
405
		$repo_param = "-r {$g['product_name']}";
406
	}
407
408 a9b0a7a3 Renato Botelho
	/*
409
	 * If we want more than just the currently installed packages or
410
	 * we want up-to-date remote repo info then do a full pkg search
411
	 */
412 dd6ecfa2 Phil Davis
	if (!$installed_pkgs_only || !$remote_repo_usage_disabled) {
413 eaed7e74 Renato Botelho
		$did_search = true;
414 283e8d24 Renato Botelho
		$search_rc = pkg_exec("search {$repo_param} " .
415 05318264 Renato Botelho
		    "{$extra_param}-R --raw-format json-compact " .
416 a9b0a7a3 Renato Botelho
		    $pkgs, $search_out, $search_err);
417
		if ($search_rc == 0) {
418 c253e352 Renato Botelho
			$search_items = explode("\n", chop($search_out));
419 a9b0a7a3 Renato Botelho
			array_walk($search_items, function(&$v, &$k) {
420
				$v = json_decode($v, true);
421
			});
422
		}
423 4333564a Renato Botelho
	}
424 dd6ecfa2 Phil Davis
425 a9b0a7a3 Renato Botelho
	/*
426
	 * We always should look for local items to detect packages that
427
	 * were removed from remote repo but are already installed locally
428
	 *
429
	 * Take pkg search return code into consideration to fallback to local
430
	 * information when remote repo is not accessible
431
	 */
432
	if (is_pkg_installed($pkgs) || $search_rc != 0) {
433
		$info_rc = pkg_exec("info -R --raw-format json-compact " .
434
		    $pkgs, $info_out, $info_err);
435
		if ($info_rc == 0) {
436 c253e352 Renato Botelho
			$info_items = explode("\n", chop($info_out));
437 a9b0a7a3 Renato Botelho
			array_walk($info_items, function(&$v, &$k) {
438
				$v = json_decode($v, true);
439
			});
440
		}
441 587988f6 stilez
	}
442 04daf8b1 stilez
443 9b7cfb3f Renato Botelho
	if ($lock) {
444
		clear_subsystem_dirty('pkg');
445
	}
446 b2a66231 Ermal
447 a9b0a7a3 Renato Botelho
	if ($search_rc != 0 && $info_rc != 0) {
448 e791dee8 Renato Botelho
		update_status("\n" . gettext(
449
		    "ERROR: Error trying to get packages list. Aborting...")
450
		    . "\n");
451 a9b0a7a3 Renato Botelho
		update_status($search_err . "\n" . $info_err);
452 4333564a Renato Botelho
		$input_errors[] = gettext(
453
		    "ERROR: Error trying to get packages list. Aborting...") .
454
		    "\n";
455 a9b0a7a3 Renato Botelho
		$input_errors[] = $search_err . "\n" . $info_err;
456 65c94077 Renato Botelho
		return array();
457
	}
458
459 a9b0a7a3 Renato Botelho
	/* It was not possible to search, use local information only */
460 eaed7e74 Renato Botelho
	if ($search_rc != 0 || !$did_search) {
461 a9b0a7a3 Renato Botelho
		$search_items = $info_items;
462
	} else {
463
		foreach ($info_items as $pkg_info) {
464
			if (empty($pkg_info['name'])) {
465
				continue;
466
			}
467
468 bc60e070 Renato Botelho
			if (array_search($pkg_info['name'], array_column(
469
			    $search_items, 'name')) === FALSE) {
470 a9b0a7a3 Renato Botelho
				$pkg_info['obsolete'] = true;
471
				$search_items[] = $pkg_info;
472
			}
473
		}
474
	}
475
476 65c94077 Renato Botelho
	$result = array();
477 a9b0a7a3 Renato Botelho
	foreach ($search_items as $pkg_info) {
478
		if (empty($pkg_info['name'])) {
479 65c94077 Renato Botelho
			continue;
480
		}
481
482 4333564a Renato Botelho
		if (isset($pkg_filter) && !in_array($pkg_info['name'],
483
		    $pkg_filter)) {
484 d65fc2ff Renato Botelho
			continue;
485
		}
486
487 b9e2048a Renato Botelho
		$pkg_info['shortname'] = $pkg_info['name'];
488
		pkg_remove_prefix($pkg_info['shortname']);
489
490
		/* XXX: Add it to globals.inc? */
491
		$pkg_info['changeloglink'] =
492
		    "https://github.com/pfsense/FreeBSD-ports/commits/devel/" .
493
		    $pkg_info['categories'][0] . '/' . $pkg_info['name'];
494
495 dd6ecfa2 Phil Davis
		$pkg_is_installed = false;
496
497 77340246 Renato Botelho
		if (is_pkg_installed($pkg_info['name'])) {
498 05318264 Renato Botelho
			$rc = pkg_exec("query %R {$pkg_info['name']}", $out,
499
			    $err);
500 283e8d24 Renato Botelho
			if (!$base_packages &&
501
			    rtrim($out) != $g['product_name']) {
502 05318264 Renato Botelho
				continue;
503
			}
504
505 77340246 Renato Botelho
			$pkg_info['installed'] = true;
506 dd6ecfa2 Phil Davis
			$pkg_is_installed = true;
507 54f236f7 Renato Botelho
508 4333564a Renato Botelho
			$rc = pkg_exec("query %v {$pkg_info['name']}", $out,
509
			    $err);
510 54f236f7 Renato Botelho
511
			if ($rc != 0) {
512 a835cdee Renato Botelho
				update_status("\n" . gettext("ERROR: Error " .
513
				    "trying to get package version. " .
514
				    "Aborting...") . "\n");
515 e791dee8 Renato Botelho
				update_status($err);
516 a835cdee Renato Botelho
				$input_errors[] = gettext("ERROR: Error " .
517
				    "trying to get package version. " .
518
				    "Aborting...") . "\n";
519 4333564a Renato Botelho
				$input_errors[] = $err;
520 54f236f7 Renato Botelho
				return array();
521
			}
522
523 a835cdee Renato Botelho
			$pkg_info['installed_version'] = str_replace("\n", "",
524
			    $out);
525 07152ca7 Steve Beaver
526
			/*
527 a835cdee Renato Botelho
			 * We used pkg info to collect pkg data so remote
528
			 * version is not available. Lets try to collect it
529
			 * using rquery if possible
530
			 */
531 eaed7e74 Renato Botelho
			if ($search_rc != 0 || !$did_search) {
532 a835cdee Renato Botelho
				$rc = pkg_exec(
533
				    "rquery -U %v {$pkg_info['name']}", $out,
534
				    $err);
535 07152ca7 Steve Beaver
536
				if ($rc == 0) {
537 a835cdee Renato Botelho
					$pkg_info['version'] =
538
					    str_replace("\n", "", $out);
539 07152ca7 Steve Beaver
				}
540
			}
541
542 82692fe1 Renato Botelho
		} else if (is_package_installed($pkg_info['shortname'])) {
543
			$pkg_info['broken'] = true;
544 dd6ecfa2 Phil Davis
			$pkg_is_installed = true;
545 77340246 Renato Botelho
		}
546
547 4333564a Renato Botelho
		$pkg_info['desc'] = preg_replace('/\n+WWW:.*$/', '',
548
		    $pkg_info['desc']);
549 c8cae8e5 Renato Botelho
550 dd6ecfa2 Phil Davis
		if (!$installed_pkgs_only || $pkg_is_installed) {
551
			$result[] = $pkg_info;
552
		}
553 65c94077 Renato Botelho
		unset($pkg_info);
554 34da63c3 Colin Smith
	}
555 b2a66231 Ermal
556 c5ecf722 Renato Botelho
	/* Sort result alphabetically */
557
	usort($result, function($a, $b) {
558
		return(strcasecmp ($a['name'], $b['name']));
559
	});
560
561 65c94077 Renato Botelho
	return $result;
562 8c6516d1 Colin Smith
}
563
564 bed6c19b Renato Botelho
/*
565
 * If binary pkg is installed but post-install tasks were not
566 0d0f419e Phil Davis
 * executed yet, do it now.
567 bed6c19b Renato Botelho
 * This scenario can happen when a pkg is pre-installed during
568
 * build phase, and at this point, cannot find a running system
569
 * to register itself in config.xml and also execute custom
570
 * install functions
571
 */
572
function register_all_installed_packages() {
573
	global $g, $config, $pkg_interface;
574
575 587988f6 stilez
	$pkg_info = get_pkg_info('all', true, true);
576
577 bed6c19b Renato Botelho
	foreach ($pkg_info as $pkg) {
578
		pkg_remove_prefix($pkg['name']);
579
580
		if (is_package_installed($pkg['name'])) {
581
			continue;
582
		}
583
584
		update_status(sprintf(gettext(
585
		    "Running last steps of %s installation.") . "\n",
586
		    $pkg['name']));
587
		install_package_xml($pkg['name']);
588
	}
589
}
590
591 8c6516d1 Colin Smith
/*
592 0c9d489e Renato Botelho do Couto
 * resync_all_package_configs() Force packages to setup their configuration
593
 * and rc.d files.  This function may also print output to the terminal
594
 * indicating progress.
595 8c6516d1 Colin Smith
 */
596
function resync_all_package_configs($show_message = false) {
597 b1224cdc jim-p
	global $config, $pkg_interface, $g;
598 b2a66231 Ermal
599 6acdf659 Carlos Eduardo Ramos
	log_error(gettext("Resyncing configuration for all packages."));
600 06e57df8 Scott Ullrich
601 bfd3334b jim-p
	if (!isset($config['installedpackages']['package']) ||
602
	    !is_array($config['installedpackages']['package'])) {
603 3a9eb3c9 Ermal
		return;
604 49aec489 Phil Davis
	}
605 06e57df8 Scott Ullrich
606 49aec489 Phil Davis
	if ($show_message == true) {
607 3a9eb3c9 Ermal
		echo "Syncing packages:";
608 49aec489 Phil Davis
	}
609 b2a66231 Ermal
610 06e57df8 Scott Ullrich
611 49aec489 Phil Davis
	foreach ($config['installedpackages']['package'] as $idx => $package) {
612
		if (empty($package['name'])) {
613 2addd5b2 Ermal
			continue;
614 49aec489 Phil Davis
		}
615
		if ($show_message == true) {
616 2addd5b2 Ermal
			echo " " . $package['name'];
617 49aec489 Phil Davis
		}
618
		if (platform_booting() != true) {
619 af5d93f6 Renato Botelho
			stop_service(get_package_internal_name($package));
620 49aec489 Phil Davis
		}
621 a0d4336f Renato Botelho
		sync_package($package['name']);
622 e791dee8 Renato Botelho
		update_status(gettext("Syncing packages...") . "\n");
623 e65a287f Scott Ullrich
	}
624 06e57df8 Scott Ullrich
625 49aec489 Phil Davis
	if ($show_message == true) {
626 08452bff Warren Baker
		echo " done.\n";
627 49aec489 Phil Davis
	}
628 8c6516d1 Colin Smith
}
629
630 d1a8f050 Renato Botelho
function uninstall_package($package_name) {
631 e791dee8 Renato Botelho
	global $config;
632 b2a66231 Ermal
633 0d579b59 Renato Botelho
	$internal_name = $package_name;
634 d1a8f050 Renato Botelho
	$id = get_package_id($package_name);
635 df5da531 Ermal
	if ($id >= 0) {
636 0c9d489e Renato Botelho do Couto
		$internal_name = get_package_internal_name(
637
		    $config['installedpackages']['package'][$id]);
638 d1a8f050 Renato Botelho
		stop_service($internal_name);
639 0d579b59 Renato Botelho
	}
640 f5b1c660 Renato Botelho
	$pkg_name = $g['pkg_prefix'] . $internal_name;
641 0d579b59 Renato Botelho
642 f5b1c660 Renato Botelho
	if (is_pkg_installed($pkg_name)) {
643 e791dee8 Renato Botelho
		update_status(gettext("Removing package...") . "\n");
644 f5b1c660 Renato Botelho
		pkg_delete($pkg_name);
645 0d579b59 Renato Botelho
	} else {
646
		delete_package_xml($package_name);
647 1570d27a Ermal Lu?i
	}
648 4c6a49d7 Scott Ullrich
649 e791dee8 Renato Botelho
	update_status(gettext("done.") . "\n");
650 f898cf33 Scott Ullrich
}
651
652 e5960712 PiBa-NL
function reinstall_package($package_name) {
653
	global $config, $g;
654
655
	$internal_name = $package_name;
656
	$id = get_package_id($package_name);
657
	if ($id >= 0) {
658 0c9d489e Renato Botelho do Couto
		$internal_name = get_package_internal_name(
659
		    $config['installedpackages']['package'][$id]);
660 e5960712 PiBa-NL
	}
661
	$pkg_name = $g['pkg_prefix'] . $internal_name;
662
	pkg_install($pkg_name);
663
}
664
665 a0d4336f Renato Botelho
/* Run <custom_php_resync_config_command> */
666
function sync_package($package_name) {
667
	global $config, $builder_package_install;
668 2d26ee5e Sjon Hortensius
669
	// If this code is being called by pfspkg_installer
670 09e11b69 Scott Ullrich
	// which the builder system uses then return (ignore).
671 49aec489 Phil Davis
	if ($builder_package_install) {
672 f0695975 Scott Ullrich
		return;
673 49aec489 Phil Davis
	}
674 2d26ee5e Sjon Hortensius
675 49aec489 Phil Davis
	if (empty($config['installedpackages']['package'])) {
676 b2a66231 Ermal
		return;
677 49aec489 Phil Davis
	}
678 a0d4336f Renato Botelho
679
	if (($pkg_id = get_package_id($package_name)) == -1) {
680 0c9d489e Renato Botelho do Couto
		// This package doesn't really exist - exit the function.
681
		return;
682 49aec489 Phil Davis
	}
683 3e643dba Ermal LUÇI
684 49aec489 Phil Davis
	if (!is_array($config['installedpackages']['package'][$pkg_id])) {
685 0c9d489e Renato Botelho do Couto
		// No package belongs to the pkg_id passed to this function.
686
		return;
687 49aec489 Phil Davis
	}
688 3e643dba Ermal LUÇI
689 c6c398c6 jim-p
	$package = &$config['installedpackages']['package'][$pkg_id];
690 49aec489 Phil Davis
	if (!file_exists("/usr/local/pkg/" . $package['configurationfile'])) {
691 0c9d489e Renato Botelho do Couto
		log_error(sprintf(gettext("The %s package is missing its " .
692
		    "configuration file and must be reinstalled."),
693
		    $package['name']));
694 106574d1 Renato Botelho
		delete_package_xml($package['name']);
695 a0d4336f Renato Botelho
		return;
696 2c794549 Ermal
	}
697 a0d4336f Renato Botelho
698 0c9d489e Renato Botelho do Couto
	$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" .
699
	    $package['configurationfile'], "packagegui");
700 49aec489 Phil Davis
	if (isset($pkg_config['nosync'])) {
701 2addd5b2 Ermal
		return;
702 49aec489 Phil Davis
	}
703 a0d4336f Renato Botelho
704 2c794549 Ermal
	/* Bring in package include files */
705
	if (!empty($pkg_config['include_file'])) {
706
		$include_file = $pkg_config['include_file'];
707 49aec489 Phil Davis
		if (file_exists($include_file)) {
708 2c794549 Ermal
			require_once($include_file);
709 49aec489 Phil Davis
		} else {
710 0c9d489e Renato Botelho do Couto
			log_error(sprintf(gettext('Reinstalling package %1$s " .
711
			    "because its include file(%2$s) is missing!'),
712
			    $package['name'], $include_file));
713 2c794549 Ermal
			uninstall_package($package['name']);
714 e5960712 PiBa-NL
			if (reinstall_package($package['name']) != 0) {
715 0c9d489e Renato Botelho do Couto
				log_error(sprintf(gettext("Reinstalling " .
716
				    "package %s failed. Take appropriate " .
717
				    "measures!!!"), $package['name']));
718 a0d4336f Renato Botelho
				return;
719
			}
720
			if (file_exists($include_file)) {
721
				require_once($include_file);
722
			} else {
723
				return;
724 83cfae8d Ermal Lu?i
			}
725 30e4c34a Scott Ullrich
		}
726 2c794549 Ermal
	}
727 30e4c34a Scott Ullrich
728 49aec489 Phil Davis
	if (!empty($pkg_config['custom_php_global_functions'])) {
729 2c794549 Ermal
		eval($pkg_config['custom_php_global_functions']);
730 49aec489 Phil Davis
	}
731
	if (!empty($pkg_config['custom_php_resync_config_command'])) {
732 2c794549 Ermal
		eval($pkg_config['custom_php_resync_config_command']);
733 49aec489 Phil Davis
	}
734 8c6516d1 Colin Smith
}
735
736 801fcf24 Renato Botelho
/* Read info.xml installed by package and return an array */
737
function read_package_config($package_name) {
738
	global $g;
739 e5b5e29c Renato Botelho
740 0c9d489e Renato Botelho do Couto
	$pkg_info_xml = '/usr/local/share/' . $g['pkg_prefix'] . $package_name .
741
	    '/info.xml';
742 7860191a Renato Botelho
743 801fcf24 Renato Botelho
	if (!file_exists($pkg_info_xml)) {
744
		return false;
745
	}
746 7860191a Renato Botelho
747 801fcf24 Renato Botelho
	$pkg_info = parse_xml_config_pkg($pkg_info_xml, 'pfsensepkgs');
748 7860191a Renato Botelho
749 801fcf24 Renato Botelho
	if (empty($pkg_info)) {
750
		return false;
751 43dad535 Vinicius Coque
	}
752 801fcf24 Renato Botelho
753
	/* it always returns an array with 1 item */
754
	return $pkg_info['package'][0];
755 8c6516d1 Colin Smith
}
756
757 a2b0d909 Renato Botelho
/* Read package configurationfile and return an array */
758
function read_package_configurationfile($package_name) {
759
	global $config, $g;
760
761
	$pkg_config = array();
762
	$id = get_package_id($package_name);
763
764 71e7de02 Renato Botelho do Couto
	if ($id < 0 || !isset($config['installedpackages']['package'][$id])) {
765 a2b0d909 Renato Botelho
		return $pkg_config;
766
	}
767
768 71e7de02 Renato Botelho do Couto
	$pkg_data = $config['installedpackages']['package'][$id];
769 a2b0d909 Renato Botelho
770 71e7de02 Renato Botelho do Couto
	if (empty($pkg_data['configurationfile'])) {
771
		return $pkg_config;
772
	}
773
774
	if (!file_exists('/usr/local/pkg/' . $pkg_data['configurationfile'])) {
775 a2b0d909 Renato Botelho
		return $pkg_config;
776
	}
777
778 0c9d489e Renato Botelho do Couto
	$pkg_config = parse_xml_config_pkg('/usr/local/pkg/' .
779 71e7de02 Renato Botelho do Couto
	    $pkg_data['configurationfile'], "packagegui");
780 a2b0d909 Renato Botelho
781
	return $pkg_config;
782
}
783
784 801fcf24 Renato Botelho
function get_after_install_info($package_name) {
785 666c49ce Renato Botelho
	$pkg_config = read_package_config($package_name);
786 384e2647 Renato Botelho
787 801fcf24 Renato Botelho
	if (isset($pkg_config['after_install_info'])) {
788
		return $pkg_config['after_install_info'];
789 49aec489 Phil Davis
	}
790 384e2647 Renato Botelho
791 801fcf24 Renato Botelho
	return '';
792
}
793 384e2647 Renato Botelho
794 801fcf24 Renato Botelho
function eval_once($toeval) {
795
	global $evaled;
796
	if (!$evaled) {
797
		$evaled = array();
798 49aec489 Phil Davis
	}
799 801fcf24 Renato Botelho
	$evalmd5 = md5($toeval);
800
	if (!in_array($evalmd5, $evaled)) {
801
		@eval($toeval);
802
		$evaled[] = $evalmd5;
803 384e2647 Renato Botelho
	}
804 801fcf24 Renato Botelho
	return;
805 384e2647 Renato Botelho
}
806
807 801fcf24 Renato Botelho
function install_package_xml($package_name) {
808 e791dee8 Renato Botelho
	global $g, $config, $pkg_interface;
809 bfe9c9e7 jim-p
810 801fcf24 Renato Botelho
	if (($pkg_info = read_package_config($package_name)) == false) {
811
		return false;
812 49aec489 Phil Davis
	}
813 cfde64b8 Scott Ullrich
814 c92ccac7 Vinicius Coque
	pkg_debug(gettext("Beginning package installation.") . "\n");
815 0c9d489e Renato Botelho do Couto
	log_error(sprintf(gettext('Beginning package installation for %s .'),
816
	    $pkg_info['name']));
817 2a0e6517 Colin Smith
818 7597c8e8 Colin Smith
	/* add package information to config.xml */
819 af5d93f6 Renato Botelho
	$pkgid = get_package_id($pkg_info['name']);
820 e791dee8 Renato Botelho
	update_status(gettext("Saving updated package information...") . "\n");
821 49aec489 Phil Davis
	if ($pkgid == -1) {
822 bfd3334b jim-p
		init_config_arr(array('installedpackages', 'package'));
823 7597c8e8 Colin Smith
		$config['installedpackages']['package'][] = $pkg_info;
824 0c9d489e Renato Botelho do Couto
		$changedesc = sprintf(gettext("Installed %s package."),
825
		    $pkg_info['name']);
826 6acdf659 Carlos Eduardo Ramos
		$to_output = gettext("done.") . "\n";
827 7597c8e8 Colin Smith
	} else {
828 bfd3334b jim-p
		init_config_arr(array('installedpackages', 'package', $pkgid));
829 7597c8e8 Colin Smith
		$config['installedpackages']['package'][$pkgid] = $pkg_info;
830 0c9d489e Renato Botelho do Couto
		$changedesc = sprintf(gettext("Overwrote previous " .
831
		    "installation of %s."), $pkg_info['name']);
832 6acdf659 Carlos Eduardo Ramos
		$to_output = gettext("overwrite!") . "\n";
833 7597c8e8 Colin Smith
	}
834 0c9d489e Renato Botelho do Couto
	write_config(sprintf(gettext("Intermediate config write during " .
835
	    "package install for %s."), $pkg_info['name']));
836 e791dee8 Renato Botelho
	update_status($to_output);
837 b2a66231 Ermal
838 801fcf24 Renato Botelho
	if (($pkgid = get_package_id($package_name)) == -1) {
839 0c9d489e Renato Botelho do Couto
		update_status(sprintf(gettext('The %1$s package is not " .
840
		    "installed.%2$sInstallation aborted.'), $package_name,
841
		    "\n\n"));
842 b2a66231 Ermal
843 801fcf24 Renato Botelho
		uninstall_package($package_name);
844
		write_config($changedesc);
845 0c9d489e Renato Botelho do Couto
		log_error(sprintf(gettext("Failed to install package: %s."),
846
		    $pkg_info['name']));
847 e791dee8 Renato Botelho
		update_status(gettext("Failed to install package.") . "\n");
848 2c794549 Ermal
		return false;
849 e65a287f Scott Ullrich
	}
850 bfe9c9e7 jim-p
851 dfc51883 Renato Botelho do Couto
	if (!file_exists("/usr/local/pkg/" . $pkg_info['configurationfile'])) {
852
		pkg_debug("Unable to find config file\n");
853
		update_status(gettext("Loading package configuration... " .
854
		    "failed!") .  "\n\n" . gettext("Installation aborted."));
855
		pkg_debug(gettext("Unable to load package configuration. " .
856
		    "Installation aborted.") ."\n");
857 b2a66231 Ermal
858 dfc51883 Renato Botelho do Couto
		uninstall_package($package_name);
859
		write_config($changedesc);
860
		log_error(sprintf(gettext("Failed to install package: %s."),
861
		    $pkg_info['name']));
862
		update_status(gettext("Failed to install package.") . "\n");
863
		return false;
864
	}
865
866 2b6de647 Renato Botelho do Couto
	$pkg_data = &$config['installedpackages']['package'][$pkgid];
867
868 dfc51883 Renato Botelho do Couto
	update_status(gettext("Loading package configuration... "));
869
	$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" .
870
	    $pkg_info['configurationfile'], "packagegui");
871
	update_status(gettext("done.") . "\n");
872
	update_status(gettext("Configuring package components...") .
873
	    "\n");
874
	if (!empty($pkg_config['filter_rules_needed'])) {
875 2b6de647 Renato Botelho do Couto
		$pkg_data['filter_rule_function'] =
876 dfc51883 Renato Botelho do Couto
		    $pkg_config['filter_rules_needed'];
877
	}
878
	/* modify system files */
879
880
	/* if a require exists, include it.  this will
881
	 * show us where an error exists in a package
882
	 * instead of making us blindly guess
883
	 */
884
	$missing_include = false;
885
	if ($pkg_config['include_file'] <> "") {
886 6279f1b8 Renato Botelho do Couto
		update_status(gettext("Loading package instructions...") .
887
		    "\n");
888 dfc51883 Renato Botelho do Couto
		if (file_exists($pkg_config['include_file'])) {
889 6279f1b8 Renato Botelho do Couto
			pkg_debug("require_once('" .
890
			    $pkg_config['include_file'] . "')\n");
891 dfc51883 Renato Botelho do Couto
			require_once($pkg_config['include_file']);
892
		} else {
893 6279f1b8 Renato Botelho do Couto
			pkg_debug("Missing include " .
894
			    "{$pkg_config['include_file']}\n");
895 dfc51883 Renato Botelho do Couto
			$missing_include = true;
896
			update_status(sprintf(gettext("Include %s is missing!"),
897
			    basename($pkg_config['include_file'])) . "\n");
898
899
			uninstall_package($package_name);
900
			write_config($changedesc);
901 6279f1b8 Renato Botelho do Couto
			log_error(sprintf(gettext(
902
			    "Failed to install package: %s."),
903
			    $pkg_info['name']));
904
			update_status(gettext("Failed to install package.") .
905
			    "\n");
906 dfc51883 Renato Botelho do Couto
			return false;
907 43db85f8 Scott Ullrich
		}
908 dfc51883 Renato Botelho do Couto
	}
909 57811192 Ermal
910 dfc51883 Renato Botelho do Couto
	/* custom commands */
911
	update_status(gettext("Custom commands...") . "\n");
912
	if ($missing_include == false) {
913
		if ($pkg_config['custom_php_global_functions'] <> "") {
914 6279f1b8 Renato Botelho do Couto
			update_status(gettext(
915
			    "Executing custom_php_global_functions()..."));
916 dfc51883 Renato Botelho do Couto
			eval_once($pkg_config['custom_php_global_functions']);
917
			update_status(gettext("done.") . "\n");
918 57811192 Ermal
		}
919 dfc51883 Renato Botelho do Couto
		if ($pkg_config['custom_php_install_command']) {
920 6279f1b8 Renato Botelho do Couto
			update_status(gettext(
921
			    "Executing custom_php_install_command()..."));
922 dfc51883 Renato Botelho do Couto
			eval_once($pkg_config['custom_php_install_command']);
923
			update_status(gettext("done.") . "\n");
924
		}
925
		if ($pkg_config['custom_php_resync_config_command'] <> "") {
926 6279f1b8 Renato Botelho do Couto
			update_status(gettext(
927
			    "Executing custom_php_resync_config_command()..."));
928
			eval_once(
929
			    $pkg_config['custom_php_resync_config_command']);
930 dfc51883 Renato Botelho do Couto
			update_status(gettext("done.") . "\n");
931
		}
932
	}
933
	/* sidebar items */
934 80f1c44b Renato Botelho do Couto
	init_config_arr(array('installedpackages', 'menu'));
935 dfc51883 Renato Botelho do Couto
	if (is_array($pkg_config['menu'])) {
936
		update_status(gettext("Menu items... "));
937
		foreach ($pkg_config['menu'] as $menu) {
938 80f1c44b Renato Botelho do Couto
			foreach ($config['installedpackages']['menu'] as
939
			    $amenu) {
940
				if ($amenu['name'] == $menu['name']) {
941
					continue 2;
942 49aec489 Phil Davis
				}
943 7597c8e8 Colin Smith
			}
944 dfc51883 Renato Botelho do Couto
			$config['installedpackages']['menu'][] = $menu;
945 7597c8e8 Colin Smith
		}
946 dfc51883 Renato Botelho do Couto
		update_status(gettext("done.") . "\n");
947
	}
948
	/* services */
949 80f1c44b Renato Botelho do Couto
	init_config_arr(array('installedpackages', 'service'));
950 dfc51883 Renato Botelho do Couto
	if (is_array($pkg_config['service'])) {
951
		update_status(gettext("Services... "));
952
		foreach ($pkg_config['service'] as $service) {
953 80f1c44b Renato Botelho do Couto
			foreach ($config['installedpackages']['service'] as
954
			    $aservice) {
955
				if ($aservice['name'] == $service['name']) {
956
					continue 2;
957 49aec489 Phil Davis
				}
958 2dc264a4 Colin Smith
			}
959 dfc51883 Renato Botelho do Couto
			$config['installedpackages']['service'][] = $service;
960 2dc264a4 Colin Smith
		}
961 dfc51883 Renato Botelho do Couto
		update_status(gettext("done.") . "\n");
962
	}
963
	if (is_array($pkg_config['tabs'])) {
964 2b6de647 Renato Botelho do Couto
		$pkg_data['tabs'] = $pkg_config['tabs'];
965 dfc51883 Renato Botelho do Couto
	}
966
	/* plugins */
967
	if (isset($pkg_config['include_file'])) {
968 2b6de647 Renato Botelho do Couto
		$pkg_data['include_file'] = $pkg_config['include_file'];
969 dfc51883 Renato Botelho do Couto
	}
970
	if (is_array($pkg_config['plugins']['item'])) {
971 2b6de647 Renato Botelho do Couto
		$pkg_data['plugins']['item'] = $pkg_config['plugins']['item'];
972 7597c8e8 Colin Smith
	}
973 2c794549 Ermal
974 e791dee8 Renato Botelho
	update_status(gettext("Writing configuration... "));
975 801fcf24 Renato Botelho
	write_config($changedesc);
976 0c9d489e Renato Botelho do Couto
	log_error(sprintf(gettext("Successfully installed package: %s."),
977
	    $pkg_info['name']));
978 e791dee8 Renato Botelho
	update_status(gettext("done.") . "\n");
979 801fcf24 Renato Botelho
	if ($pkg_info['after_install_info']) {
980 e791dee8 Renato Botelho
		update_status($pkg_info['after_install_info']);
981 2d26ee5e Sjon Hortensius
	}
982 801fcf24 Renato Botelho
983 3a0df77e jim-p
	/* set up package logging streams */
984
	if ($pkg_info['logging']) {
985
		system_syslogd_start(true);
986
	}
987
988 2c794549 Ermal
	return true;
989 64974db7 Scott Ullrich
}
990
991 3bb7e3e8 Renato Botelho
function delete_package_xml($package_name, $when = "post-deinstall") {
992 e791dee8 Renato Botelho
	global $g, $config, $pkg_interface;
993 b2a66231 Ermal
994 6955830f Ermal Lu?i
995 3bb7e3e8 Renato Botelho
	$pkgid = get_package_id($package_name);
996 b2a66231 Ermal
	if ($pkgid == -1) {
997 0c9d489e Renato Botelho do Couto
		update_status(sprintf(gettext('The %1$s package is not " .
998
		    "installed.%2$sDeletion aborted.'), $package_name, "\n\n"));
999 e65a287f Scott Ullrich
		ob_flush();
1000
		sleep(1);
1001
		return;
1002
	}
1003 086cf944 Phil Davis
	pkg_debug(sprintf(gettext("Removing %s package... "), $package_name));
1004 0c9d489e Renato Botelho do Couto
	update_status(sprintf(gettext("Removing %s components..."),
1005
	    $package_name) . "\n");
1006 407bf67a Colin Smith
	/* parse package configuration */
1007 c6c398c6 jim-p
	init_config_arr(array('installedpackages', 'package', $pkgid));
1008 b2a98518 Renato Botelho do Couto
	$pkg_info = $config['installedpackages']['package'][$pkgid];
1009 bfd3334b jim-p
	init_config_arr(array('installedpackages', 'menu'));
1010
	$menus = &$config['installedpackages']['menu'];
1011
	init_config_arr(array('installedpackages', 'service'));
1012 3c41c4ab Colin Smith
	$services = &$config['installedpackages']['service'];
1013 49aec489 Phil Davis
	if (file_exists("/usr/local/pkg/" . $pkg_info['configurationfile'])) {
1014 0c9d489e Renato Botelho do Couto
		$pkg_config = parse_xml_config_pkg("/usr/local/pkg/" .
1015 b2a98518 Renato Botelho do Couto
		    $pkg_info['configurationfile'], "packagegui");
1016 3f01fe47 Colin Smith
		/* remove menu items */
1017 58e0bfbc Renato Botelho do Couto
		if (is_array($pkg_config['menu']) && is_array($menus)) {
1018 e791dee8 Renato Botelho
			update_status(gettext("Menu items... "));
1019 58e0bfbc Renato Botelho do Couto
			foreach ($pkg_config['menu'] as $menu) {
1020
				foreach ($menus as $key => $instmenu) {
1021
					if ($instmenu['name'] ==
1022
					    $menu['name']) {
1023
						unset($menus[$key]);
1024
						break;
1025 b2a66231 Ermal
					}
1026 8604523b Ermal Lu?i
				}
1027
			}
1028 e791dee8 Renato Botelho
			update_status(gettext("done.") . "\n");
1029 407bf67a Colin Smith
		}
1030 3c41c4ab Colin Smith
		/* remove services */
1031 413e939f Renato Botelho do Couto
		if (is_array($pkg_config['service']) && is_array($services)) {
1032 e791dee8 Renato Botelho
			update_status(gettext("Services... "));
1033 413e939f Renato Botelho do Couto
			foreach ($pkg_config['service'] as $service) {
1034
				foreach ($services as $key => $instservice) {
1035
					if ($instservice['name'] !=
1036
					    $service['name']) {
1037
						continue;
1038
					}
1039
					if (platform_booting() != true) {
1040
						stop_service($service['name']);
1041
					}
1042
					if ($service['rcfile']) {
1043
						if (empty($service['prefix'])) {
1044
							$prefix = RCFILEPREFIX;
1045
						} else {
1046
							$prefix =
1047
							    $service['prefix'];
1048 8604523b Ermal Lu?i
						}
1049 413e939f Renato Botelho do Couto
						unlink_if_exists($prefix .
1050
						    $service['rcfile']);
1051 0cab7cad Colin Smith
					}
1052 413e939f Renato Botelho do Couto
					unset($services[$key]);
1053 3c41c4ab Colin Smith
				}
1054
			}
1055 e791dee8 Renato Botelho
			update_status(gettext("done.") . "\n");
1056 3c41c4ab Colin Smith
		}
1057 b2a66231 Ermal
		/*
1058 0c9d489e Renato Botelho do Couto
		 * XXX: Otherwise inclusion of config.inc again invalidates
1059
		 *      actions taken.
1060 a2febf9a Stephen Beaver
		 *	Same is done during installation.
1061 b2a66231 Ermal
		 */
1062 0c9d489e Renato Botelho do Couto
		write_config(sprintf(gettext("Intermediate config write " .
1063
		    "during package removal for %s."), $package_name));
1064 b2a66231 Ermal
1065
		/*
1066 0c9d489e Renato Botelho do Couto
		 * If a require exists, include it. this will
1067 b2a66231 Ermal
		 * show us where an error exists in a package
1068
		 * instead of making us blindly guess
1069 892aef15 Scott Ullrich
		 */
1070 fcf92dae Ermal
		$missing_include = false;
1071 49aec489 Phil Davis
		if ($pkg_config['include_file'] <> "") {
1072 2b6de647 Renato Botelho do Couto
			update_status(gettext("Loading package instructions...")
1073
			    . "\n");
1074 49aec489 Phil Davis
			if (file_exists($pkg_config['include_file'])) {
1075 2b6de647 Renato Botelho do Couto
				pkg_debug("require_once(\"" .
1076
				    "{$pkg_config['include_file']}\")\n");
1077 1570d27a Ermal Lu?i
				require_once($pkg_config['include_file']);
1078 49aec489 Phil Davis
			} else {
1079 2b6de647 Renato Botelho do Couto
				pkg_debug("Missing include " .
1080
				    $pkg_config['include_file'] . "\n");
1081 fcf92dae Ermal
				$missing_include = true;
1082 0c9d489e Renato Botelho do Couto
				update_status(sprintf(gettext("Include file " .
1083
				    "%s could not be found for inclusion."),
1084
				    basename($pkg_config['include_file'])) .
1085
				    "\n");
1086 fcf92dae Ermal
			}
1087
		}
1088 0c9d489e Renato Botelho do Couto
		/*
1089 fcf92dae Ermal
		 * NOTE: It is not possible to handle parse errors on eval.
1090 0c9d489e Renato Botelho do Couto
		 * So we prevent it from being run at all to not interrupt all
1091
		 * the other code.
1092 fcf92dae Ermal
		 */
1093 3bb7e3e8 Renato Botelho
		if ($when == "deinstall" && $missing_include == false) {
1094 0c9d489e Renato Botelho do Couto
			/*
1095
			 * evaluate this package's global functions and pre
1096
			 * deinstall commands
1097
			 */
1098 49aec489 Phil Davis
			if ($pkg_config['custom_php_global_functions'] <> "") {
1099 fcf92dae Ermal
				eval_once($pkg_config['custom_php_global_functions']);
1100 49aec489 Phil Davis
			}
1101
			if ($pkg_config['custom_php_pre_deinstall_command'] <> "") {
1102 fcf92dae Ermal
				eval_once($pkg_config['custom_php_pre_deinstall_command']);
1103 49aec489 Phil Davis
			}
1104 43db85f8 Scott Ullrich
		}
1105 644d2d59 Colin Smith
		/* deinstall commands */
1106 2b6de647 Renato Botelho do Couto
		if ($when == "deinstall" &&
1107
		    $pkg_config['custom_php_deinstall_command'] <> "") {
1108 e791dee8 Renato Botelho
			update_status(gettext("Deinstall commands... "));
1109 fcf92dae Ermal
			if ($missing_include == false) {
1110
				eval_once($pkg_config['custom_php_deinstall_command']);
1111 e791dee8 Renato Botelho
				update_status(gettext("done.") . "\n");
1112 49aec489 Phil Davis
			} else {
1113 0c9d489e Renato Botelho do Couto
				update_status("\n". gettext("Not executing " .
1114
				    "custom deinstall hook because an " .
1115
				    "include is missing.") . "\n");
1116 49aec489 Phil Davis
			}
1117 644d2d59 Colin Smith
		}
1118 407bf67a Colin Smith
	}
1119 2addd5b2 Ermal
	/* syslog */
1120 ce7edfff doktornotor
	$need_syslog_restart = false;
1121 0c9d489e Renato Botelho do Couto
	if (is_array($pkg_info['logging']) &&
1122
	    $pkg_info['logging']['logfilename'] <> "") {
1123 e8c516a0 Phil Davis
		update_status(gettext("Syslog entries... "));
1124 0c9d489e Renato Botelho do Couto
		@unlink_if_exists($g['varlog_path'] . "/" .
1125
		    $pkg_info['logging']['logfilename']);
1126 e791dee8 Renato Botelho
		update_status("done.\n");
1127 ce7edfff doktornotor
		$need_syslog_restart = true;
1128 2addd5b2 Ermal
	}
1129 2d26ee5e Sjon Hortensius
1130 6b861ecd Renato Botelho
	if ($when == "post-deinstall") {
1131
		/* remove config.xml entries */
1132
		update_status(gettext("Configuration... "));
1133
		unset($config['installedpackages']['package'][$pkgid]);
1134
		update_status(gettext("done.") . "\n");
1135 0c9d489e Renato Botelho do Couto
		write_config(sprintf(gettext("Removed %s package."),
1136
		    $package_name));
1137
		/*
1138
		 * remove package entry from /etc/syslog.conf if needed
1139
		 * this must be done after removing the entries from config.xml
1140
		 */
1141 8724b1ad jim-p
		if ($need_syslog_restart) {
1142 3a0df77e jim-p
			system_syslogd_start(true);
1143 8724b1ad jim-p
		}
1144 6b861ecd Renato Botelho
	}
1145 f0a550fd Colin Smith
}
1146 5025a56c Scott Ullrich
1147 46903fb9 Renato Botelho
/*
1148 f3f98e97 Phil Davis
 * Used during upgrade process or restore backup process, verify all
1149 46903fb9 Renato Botelho
 * packages installed in config.xml and install pkg accordingly
1150
 */
1151
function package_reinstall_all() {
1152 e791dee8 Renato Botelho
	global $g, $config, $pkg_interface;
1153 c53eb903 Ermal
1154 10511c3b Renato Botelho
	if (!isset($config['installedpackages']['package']) ||
1155
	    !is_array($config['installedpackages']['package'])) {
1156 46903fb9 Renato Botelho
		return true;
1157
	}
1158
1159 10511c3b Renato Botelho
	/*
1160
	 * Configure default pkg repo for current version instead of
1161
	 * using it from backup, that could be older
1162
	 */
1163
	$default_repo = pkg_get_default_repo();
1164
	$current_repo_path = "";
1165
	if (!empty($config['system']['pkg_repo_conf_path'])) {
1166
		$current_repo_path = $config['system']['pkg_repo_conf_path'];
1167 8552be10 Renato Botelho
	}
1168
1169 10511c3b Renato Botelho
	if ($current_repo_path != $default_repo['path']) {
1170
		$config['system']['pkg_repo_conf_path'] = $default_repo['path'];
1171
		write_config( "Configured default pkg repo after restore");
1172
		pkg_switch_repo($default_repo['path']);
1173
	}
1174 3610a08e Renato Botelho
1175 10511c3b Renato Botelho
	/* wait for internet connection */
1176
	log_error(gettext("Waiting for Internet connection to update pkg " .
1177
	    "metadata and finish package reinstallation"));
1178
	$ntries = 3;
1179
	while ($ntries > 0) {
1180
		if (pkg_update(true)) {
1181
			break;
1182 3610a08e Renato Botelho
		}
1183 10511c3b Renato Botelho
		sleep(1);
1184
		$ntries--;
1185 46903fb9 Renato Botelho
	}
1186
1187 10511c3b Renato Botelho
	if ($ntries == 0) {
1188
		return false;
1189 4221eba1 Renato Botelho
	}
1190
1191
	$package_list = array();
1192
	foreach ($config['installedpackages']['package'] as $package) {
1193
		$package_list[] = get_package_internal_name($package);
1194 c0cb3c73 Renato Botelho
	}
1195
1196 1bedcacc Renato Botelho
	if (!empty($package_list)) {
1197
		$pkg_info = get_pkg_info();
1198
	}
1199 10511c3b Renato Botelho
1200 c0cb3c73 Renato Botelho
	foreach ($package_list as $package) {
1201 46903fb9 Renato Botelho
		$found = false;
1202
		foreach ($pkg_info as $pkg) {
1203
			pkg_remove_prefix($pkg['name']);
1204 c0cb3c73 Renato Botelho
			if ($pkg['name'] == $package) {
1205
				pkg_install($g['pkg_prefix'] . $package, true);
1206 46903fb9 Renato Botelho
				$found = true;
1207
				break;
1208
			}
1209
		}
1210
1211
		if (!$found) {
1212
			if (!function_exists("file_notice")) {
1213
				require_once("notices.inc");
1214
			}
1215
1216
			file_notice(gettext("Package reinstall"),
1217 10511c3b Renato Botelho
			    sprintf(gettext("Package %s does not exist in " .
1218
			    "current %s version and it has been removed."),
1219 573ec19d Renato Botelho do Couto
			    $package, $g['product_label']));
1220 c0cb3c73 Renato Botelho
			uninstall_package($package);
1221 46903fb9 Renato Botelho
		}
1222
	}
1223
1224 a55718c8 Renato Botelho
	/*
1225
	 * Verify remaining binary packages not present in current config
1226
	 * during backup restore and remove them
1227
	 */
1228 10511c3b Renato Botelho
	$installed_packages = get_pkg_info('all', true, true);
1229
	foreach ($installed_packages as $package) {
1230
		$shortname = $package['name'];
1231
		pkg_remove_prefix($shortname);
1232
		if (get_package_id($shortname) != -1) {
1233
			continue;
1234 a55718c8 Renato Botelho
		}
1235 10511c3b Renato Botelho
		pkg_delete($package['name']);
1236 a55718c8 Renato Botelho
	}
1237
1238 46903fb9 Renato Botelho
	return true;
1239 9b193619 Scott Ullrich
}
1240
1241 60dd7649 jim-p
function stop_packages() {
1242
	require_once("config.inc");
1243
	require_once("functions.inc");
1244
	require_once("filter.inc");
1245
	require_once("shaper.inc");
1246
	require_once("captiveportal.inc");
1247
	require_once("pkg-utils.inc");
1248
	require_once("pfsense-utils.inc");
1249
	require_once("service-utils.inc");
1250
1251 c5966711 phildd
	global $config, $g;
1252 60dd7649 jim-p
1253 e8c516a0 Phil Davis
	log_error(gettext("Stopping all packages."));
1254 60dd7649 jim-p
1255 c5966711 phildd
	$rcfiles = glob(RCFILEPREFIX . "*.sh");
1256 49aec489 Phil Davis
	if (!$rcfiles) {
1257 60dd7649 jim-p
		$rcfiles = array();
1258 49aec489 Phil Davis
	} else {
1259 60dd7649 jim-p
		$rcfiles = array_flip($rcfiles);
1260 49aec489 Phil Davis
		if (!$rcfiles) {
1261 60dd7649 jim-p
			$rcfiles = array();
1262 49aec489 Phil Davis
		}
1263 60dd7649 jim-p
	}
1264
1265 bfd3334b jim-p
	if (isset($config['installedpackages']['package']) &&
1266
	    is_array($config['installedpackages']['package'])) {
1267 49aec489 Phil Davis
		foreach ($config['installedpackages']['package'] as $package) {
1268 60dd7649 jim-p
			echo " Stopping package {$package['name']}...";
1269 af5d93f6 Renato Botelho
			$internal_name = get_package_internal_name($package);
1270 75a01a7c Phil Davis
			stop_service($internal_name);
1271 0c9d489e Renato Botelho do Couto
			unset($rcfiles[RCFILEPREFIX .
1272
			    strtolower($internal_name) . ".sh"]);
1273 60dd7649 jim-p
			echo "done.\n";
1274
		}
1275
	}
1276
1277 6186cdc4 jim-p
	foreach ($rcfiles as $rcfile => $number) {
1278
		$shell = @popen("/bin/sh", "w");
1279
		if ($shell) {
1280 60dd7649 jim-p
			echo " Stopping {$rcfile}...";
1281 0c9d489e Renato Botelho do Couto
			if (!@fwrite($shell,
1282
			    "{$rcfile} stop >>/tmp/bootup_messages 2>&1")) {
1283 49aec489 Phil Davis
				if ($shell) {
1284 61ef1385 Ermal
					pclose($shell);
1285 49aec489 Phil Davis
				}
1286 61ef1385 Ermal
				$shell = @popen("/bin/sh", "w");
1287
			}
1288 60dd7649 jim-p
			echo "done.\n";
1289 6186cdc4 jim-p
			pclose($shell);
1290 60dd7649 jim-p
		}
1291
	}
1292
}
1293
1294 d5f0597b Renato Botelho
/* Identify which meta package is installed */
1295
function get_meta_pkg_name() {
1296
	global $g;
1297
1298
	/* XXX: Use pkg annotation */
1299
	if (is_pkg_installed($g['product_name'])) {
1300
		return $g['product_name'];
1301 b395c4f2 Renato Botelho
	}
1302
	foreach ($g['alternativemetaports'] as $suffix) {
1303
		if (is_pkg_installed($g['product_name'] . '-' . $suffix)) {
1304
			return $g['product_name'] . '-' . $suffix;
1305
		}
1306 d5f0597b Renato Botelho
	}
1307
	return false;
1308
}
1309
1310
/* Identify which base package is installed */
1311
function get_base_pkg_name() {
1312
	global $g;
1313
1314
	/* XXX: Use pkg annotation */
1315 cda2ef35 Renato Botelho do Couto
	if (is_pkg_installed($g['product_name'] . '-base-' . $g['product_name'])) {
1316
		return $g['product_name'] . '-base-' . $g['product_name'];
1317 d5f0597b Renato Botelho
	} else if (is_pkg_installed($g['product_name'] . '-base')) {
1318
		return $g['product_name'] . '-base';
1319
	}
1320
	return false;
1321
}
1322
1323
/* Verify if system needs upgrade (meta package or base) */
1324 e8f8aeb6 Renato Botelho
function get_system_pkg_version($baseonly = false, $use_cache = true) {
1325 d5f0597b Renato Botelho
	global $g;
1326
1327 e8f8aeb6 Renato Botelho
	$cache_file = $g['version_cache_file'];
1328
	$rc_file = $cache_file . '.rc';
1329
1330
	$rc = "";
1331
	if ($use_cache && file_exists($rc_file) &&
1332
	    (time()-filemtime($rc_file) < $g['version_cache_refresh'])) {
1333
		$rc = chop(@file_get_contents($rc_file));
1334
	}
1335
1336
	if ($rc == "2") {
1337
		$output = @file_get_contents($cache_file);
1338
	} else if ($rc != "0") {
1339
		$output = exec(
1340
		    "/usr/local/sbin/{$g['product_name']}-upgrade -c", $_gc,
1341
		    $rc);
1342 429091c8 Renato Botelho
1343
		/* Update cache if it succeeded */
1344
		if ($rc == 0 || $rc == 2) {
1345
			@file_put_contents($cache_file, $output);
1346
			@file_put_contents($rc_file, $rc);
1347 6701a859 Renato Botelho do Couto
		} else {
1348
			return false;
1349 429091c8 Renato Botelho
		}
1350 e8f8aeb6 Renato Botelho
	}
1351 ee836314 Renato Botelho
1352
	/* pfSense-upgrade returns 2 when there is a new version */
1353 e8f8aeb6 Renato Botelho
	if ($rc == "2") {
1354 ee836314 Renato Botelho
		$new_version = explode(' ', $output)[0];
1355
	}
1356
1357 d5f0597b Renato Botelho
	$base_pkg = get_base_pkg_name();
1358
	$meta_pkg = get_meta_pkg_name();
1359
1360
	if (!$base_pkg || !$meta_pkg) {
1361
		return false;
1362
	}
1363
1364 d4fbf5b7 Renato Botelho
	$info = get_pkg_info($base_pkg, true, true);
1365 d5f0597b Renato Botelho
1366
	$pkg_info = array();
1367
	foreach ($info as $item) {
1368
		if ($item['name'] == $base_pkg) {
1369
			$pkg_info = $item;
1370 ee836314 Renato Botelho
			break;
1371 d5f0597b Renato Botelho
		}
1372
	}
1373
1374 ee836314 Renato Botelho
	if (empty($pkg_info) || (!$baseonly && ($pkg_info['version'] ==
1375
	    $pkg_info['installed_version']))) {
1376 d4fbf5b7 Renato Botelho
		$info = get_pkg_info($meta_pkg, true, true);
1377 d5f0597b Renato Botelho
1378
		foreach ($info as $item) {
1379 59d256a1 Renato Botelho
			if ($item['name'] == $meta_pkg) {
1380 d5f0597b Renato Botelho
				$pkg_info = $item;
1381 ee836314 Renato Botelho
				break;
1382 d5f0597b Renato Botelho
			}
1383
		}
1384
	}
1385
1386
	if (empty($pkg_info)) {
1387
		return false;
1388
	}
1389
1390 8d5ff32b Renato Botelho
	$result = array(
1391 ee836314 Renato Botelho
	    'version'           => $new_version ?: $pkg_info['version'],
1392 d5f0597b Renato Botelho
	    'installed_version' => $pkg_info['installed_version']
1393
	);
1394 8d5ff32b Renato Botelho
1395
	$result['pkg_version_compare'] = pkg_version_compare(
1396
	    $result['installed_version'], $result['version']);
1397
1398
	return $result;
1399 d5f0597b Renato Botelho
}
1400
1401 db8621d8 Renato Botelho
/* List available repos */
1402
function pkg_list_repos() {
1403 ad3c9763 Renato Botelho
	global $g;
1404
1405 db8621d8 Renato Botelho
	$path = "/usr/local/share/{$g['product_name']}/pkg/repos";
1406 ad3c9763 Renato Botelho
1407 0c9d489e Renato Botelho do Couto
	$default_descr = @file_get_contents($path .
1408
	    "/{$g['product_name']}-repo.descr");
1409 ad3c9763 Renato Botelho
1410 db8621d8 Renato Botelho
	$default = array(
1411
	    'name' => 'Default',
1412
	    'path' => $path . "/{$g['product_name']}-repo.conf",
1413
	    'descr' => $default_descr
1414
	);
1415
1416
	$result = array($default);
1417
1418
	$conf_files = glob("{$path}/{$g['product_name']}-repo-*.conf");
1419
	foreach ($conf_files as $conf_file) {
1420
		$descr_file = preg_replace('/.conf$/', '.descr', $conf_file);
1421
		if (file_exists($descr_file)) {
1422
			$descr_content = file($descr_file);
1423
			$descr = chop($descr_content[0]);
1424
		} else {
1425
			$descr = 'Unknown';
1426
		}
1427
		if (!preg_match('/-repo-(.*).conf/', $conf_file, $matches)) {
1428
			continue;
1429
		}
1430
		$entry = array(
1431
		    'name' => ucfirst(strtolower($matches[1])),
1432
		    'path' => $conf_file,
1433
		    'descr' => $descr
1434
		);
1435 fa5e9db2 Renato Botelho
		if (file_exists($conf_file . ".default")) {
1436
			$entry['default'] = true;
1437
		}
1438 db8621d8 Renato Botelho
		$result[] = $entry;
1439 ad3c9763 Renato Botelho
	}
1440
1441 db8621d8 Renato Botelho
	return $result;
1442
}
1443
1444 8552be10 Renato Botelho
function pkg_get_default_repo() {
1445
	$repos = pkg_list_repos();
1446
1447
	foreach ($repos as $repo) {
1448
		if (isset($repo['default'])) {
1449
			return $repo;
1450
		}
1451
	}
1452
1453
	/* No default found, return the first one */
1454
	return ($repos[0]);
1455
}
1456
1457 b870f03d Renato Botelho
/* List available repos on a format to be used by selectors */
1458
function pkg_build_repo_list() {
1459
	$repos = pkg_list_repos();
1460
	$list = array();
1461
1462
	foreach ($repos as $repo) {
1463
		$list[$repo['name']] = $repo['descr'];
1464
	}
1465
1466
	return($list);
1467
}
1468
1469
/* Find repo by path */
1470
function pkg_get_repo_name($path) {
1471
	$repos = pkg_list_repos();
1472
1473 fa5e9db2 Renato Botelho
	$default = $repos[0]['name'];
1474 b870f03d Renato Botelho
	foreach ($repos as $repo) {
1475
		if ($repo['path'] == $path) {
1476
			return $repo['name'];
1477
		}
1478 fa5e9db2 Renato Botelho
		if (isset($repo['default'])) {
1479
			$default = $repo['name'];
1480
		}
1481 b870f03d Renato Botelho
	}
1482
1483
	/* Default */
1484 fa5e9db2 Renato Botelho
	return $default;
1485 b870f03d Renato Botelho
}
1486
1487 7fe4d351 Renato Botelho
/* Setup pkg.conf according current repo */
1488
function pkg_conf_setup() {
1489 71b4b23b Renato Botelho
	global $g;
1490
1491 7fe4d351 Renato Botelho
	$pkg_conf_path = "/usr/local/etc/pkg.conf";
1492
	$conf = "/usr/local/etc/pkg/repos/{$g['product_name']}.conf";
1493
	if (!file_exists($conf)) {
1494
		return;
1495
	}
1496 db8621d8 Renato Botelho
1497 7fe4d351 Renato Botelho
	$real_conf = readlink($conf);
1498
1499
	if (!$real_conf) {
1500
		return;
1501
	}
1502 db8621d8 Renato Botelho
1503 7fe4d351 Renato Botelho
	$abi_file = str_replace('.conf', '.abi', $real_conf);
1504
	$altabi_file = str_replace('.conf', '.altabi', $real_conf);
1505 ce6e6519 Renato Botelho
1506 7fe4d351 Renato Botelho
	$pkg_conf = array();
1507 ce6e6519 Renato Botelho
	if (file_exists($abi_file) && file_exists($altabi_file)) {
1508
		$abi = file_get_contents($abi_file);
1509
		$altabi = file_get_contents($altabi_file);
1510
1511
		$pkg_conf = array(
1512
			"ABI={$abi}",
1513
			"ALTABI={$altabi}"
1514
		);
1515
	}
1516
1517 7fe4d351 Renato Botelho
	file_put_contents($pkg_conf_path, $pkg_conf);
1518
}
1519
1520
/* Switch between stable and devel repos */
1521
function pkg_switch_repo($path) {
1522
	global $g;
1523
1524
	safe_mkdir("/usr/local/etc/pkg/repos");
1525
	@unlink("/usr/local/etc/pkg/repos/{$g['product_name']}.conf");
1526
	@symlink($path, "/usr/local/etc/pkg/repos/{$g['product_name']}.conf");
1527
1528
	pkg_conf_setup();
1529
1530 b58c1588 Renato Botelho
	/* Update pfSense_version cache */
1531
	mwexec_bg("/etc/rc.update_pkg_metadata now");
1532
	return;
1533 ad3c9763 Renato Botelho
}
1534
1535 00d0c66e Steve Beaver
$FQDN = "https://ews.netgate.com/pfupdate";
1536
$refreshinterval = (24 * 3600);	// 24 hours
1537
$idfile = "/var/db/uniqueid";
1538
$repopath = "/usr/local/share/{$g['product_name']}/pkg/repos";
1539
$configflename = "{$repopath}/{$g['product_name']}-repo-custom.conf";
1540
1541 a001cffd Renato Botelho do Couto
/*
1542
 * Update the list of available repositories from the server. This will allow
1543
 * migration to another update repository should the existing one becomes
1544
 * unavailable
1545
 */
1546 00d0c66e Steve Beaver
function update_repos() {
1547
	global $g, $config, $idfile, $FQDN, $repopath;
1548
1549 a001cffd Renato Botelho do Couto
	if (!file_exists($idfile) || !function_exists('curl_version')) {
1550
		return;
1551
	}
1552
	/*
1553
	 * If the custom repository definition does not exist, or is more
1554
	 * than 24 hours old fetch a copy from the server
1555
	 */
1556
	if (!file_exists($configflename) ||
1557
	    (time()-filemtime($configflename) > $refreshinterval)) {
1558
		/*
1559
		 * Gather some information about the system so the proper
1560
		 * repo can be returned
1561
		 */
1562
		$nid = file_get_contents($idfile);
1563
		$serial = system_get_serial();
1564 8062e6a4 Steve Beaver
1565 a001cffd Renato Botelho do Couto
		// Compose a version string in JSON format
1566
		$os = php_uname('s');
1567
		$osver = php_uname('r');
1568
		$v = strtolower(php_uname('v'));
1569
		$ed =  (strpos($v, 'factory') !== false)
1570
		    ? "Factory" : "Community";
1571
		$pkglist = get_pkg_info("all", false, true);
1572
		$platform = system_identify_specific_platform();
1573
		$platformname = gettext('Unknown system');
1574
1575
		if (isset($platform['descr'])) {
1576
			$platformname = $platform['descr'];
1577
		}
1578 f9981994 Steve Beaver
1579 e1fb434d Renato Botelho do Couto
		/* XXX: Use json_encode instead of hardcode it */
1580 a001cffd Renato Botelho do Couto
		$version =
1581
		    "{\"platform\":\"" . $platformname .
1582
		    "\",\"os\":\"" . $os .
1583
		    "\",\"osver\":\"" . $osver .
1584 573ec19d Renato Botelho do Couto
		    "\",\"prod\":\"" . $g['product_label'] .
1585 36c5c493 Renato Botelho do Couto
		    "\",\"ver\":\"" . $g['product_version'] .
1586 a001cffd Renato Botelho do Couto
		    "\",\"ed\":\"" . $ed .
1587
		    "\",\"pkgs\":[";
1588 725c8134 Steve Beaver
1589 a001cffd Renato Botelho do Couto
		$first = true;
1590 725c8134 Steve Beaver
1591 a001cffd Renato Botelho do Couto
		foreach($pkglist as $pkg) {
1592
			if (!$first) {
1593
				$version .= ",";
1594
			}
1595 725c8134 Steve Beaver
1596 a001cffd Renato Botelho do Couto
			$version .= "{\"name\":\"" . $pkg['shortname'] .
1597
			    "\",\"ver\":\"" . $pkg['version'] . "\"}";
1598
			$first = false;
1599
		}
1600 725c8134 Steve Beaver
1601 a001cffd Renato Botelho do Couto
		$version .= "]}";
1602
1603
		$arch =  php_uname('m');
1604
		$locale = $config['system']['language'];
1605
1606
		$post = [
1607
		    'uid' => $nid,
1608
		    'language' => $locale,
1609
		    'serial' => $serial,
1610
		    'version' => $version,
1611
		    'arch' => $arch
1612
		];
1613
1614
		$ch = curl_init();
1615
		curl_setopt($ch, CURLOPT_HEADER, 0);
1616
		curl_setopt($ch, CURLOPT_VERBOSE, 0);
1617
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
1618 573ec19d Renato Botelho do Couto
		curl_setopt($ch, CURLOPT_USERAGENT, $g['product_label'] . '/' .
1619 a001cffd Renato Botelho do Couto
		    $g['product_version']);
1620
		curl_setopt($ch, CURLOPT_URL, $FQDN);
1621
		curl_setopt($ch, CURLOPT_POST, true);
1622
		curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
1623
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT ,4);
1624
		$response = curl_exec($ch);
1625
		$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
1626
		curl_close($ch);
1627
1628
		if ($status == 200) {
1629
			save_repo($response);
1630 00d0c66e Steve Beaver
		}
1631
	}
1632
}
1633
1634
// Parse the received JSON data and save the custom repository information
1635
function save_repo($json) {
1636
	global $repopath, $g;
1637 f06b389e Renato Botelho do Couto
1638 00d0c66e Steve Beaver
	$repo = json_decode($json, true);
1639
1640 f06b389e Renato Botelho do Couto
	if (($repo != NULL) && isset($repo['abi']) && isset($repo['altabi']) &&
1641
	    isset($repo['conf']) && isset($repo['descr']) &&
1642
	    isset($repo['name']) && (strlen($repo['conf']) > 10)) {
1643 00d0c66e Steve Beaver
		$basename = "{$repopath}/{$g['product_name']}-repo-custom.";
1644
1645 f06b389e Renato Botelho do Couto
		file_put_contents($basename . "conf", base64_decode(
1646
		    $repo['conf']));
1647 00d0c66e Steve Beaver
		file_put_contents($basename . "descr", $repo['descr']);
1648
		file_put_contents($basename . "abi", $repo['abi']);
1649
		file_put_contents($basename . "altabi", $repo['altabi']);
1650
		file_put_contents($basename . "name", $repo['name']);
1651
		file_put_contents($basename . "help", $repo['help']);
1652 21654184 Steve Beaver
1653
		// Save fingerprint file
1654
		if (!empty($repo['fingerprint'])) {
1655
			if (!empty($repo['fpname'])) {
1656
				$fppath = "/usr/local/share/pfSense/keys/pkg/trusted/" . $repo['fpname'];
1657
			} else {
1658
				$fppath = "/usr/local/share/pfSense/keys/pkg/trusted/custom.pfsense.org";
1659
			}
1660
1661
			file_put_contents($fppath, $repo['fingerprint']);
1662
		}
1663 00d0c66e Steve Beaver
	} else {
1664 f06b389e Renato Botelho do Couto
		/*
1665
		 * If there was anything wrong with the custom repository
1666
		 * definition, remove the help text to avoid possible confusion
1667
		 */
1668 00d0c66e Steve Beaver
		if (file_exists($basename . "help")) {
1669
			unlink($basename . "help");
1670
		}
1671
	}
1672
}
1673 b870f03d Renato Botelho
1674 61ef1385 Ermal
?>