Project

General

Profile

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