Project

General

Profile

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