Completed
Push — release-2.1 ( f9d087...e49a83 )
by Mert
04:30
created

PackageGet.php ➔ PackageUpload()   F

Complexity

Conditions 27
Paths 288

Size

Total Lines 89
Code Lines 50

Duplication

Lines 12
Ratio 13.48 %

Importance

Changes 0
Metric Value
cc 27
eloc 50
nc 288
nop 0
dl 12
loc 89
rs 3.5693
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * This file handles the package servers and packages download from Package Manager.
5
 *
6
 * Simple Machines Forum (SMF)
7
 *
8
 * @package SMF
9
 * @author Simple Machines http://www.simplemachines.org
10
 * @copyright 2016 Simple Machines and individual contributors
11
 * @license http://www.simplemachines.org/about/smf/license.php BSD
12
 *
13
 * @version 2.1 Beta 3
14
 */
15
16
if (!defined('SMF'))
17
	die('No direct access...');
18
19
/**
20
 * Browse the list of package servers, add servers...
21
 */
22
function PackageGet()
23
{
24
	global $txt, $context, $sourcedir;
25
26
	isAllowedTo('admin_forum');
27
	require_once($sourcedir . '/Subs-Package.php');
28
29
	// Use the Packages template... no reason to separate.
30
	loadLanguage('Packages');
31
	loadTemplate('Packages', 'admin');
32
33
	$context['page_title'] = $txt['package'];
34
35
	// Here is a list of all the potentially valid actions.
36
	$subActions = array(
37
		'servers' => 'PackageServers',
38
		'add' => 'PackageServerAdd',
39
		'browse' => 'PackageGBrowse',
40
		'download' => 'PackageDownload',
41
		'remove' => 'PackageServerRemove',
42
		'upload' => 'PackageUpload',
43
	);
44
45
	// Now let's decide where we are taking this...
46
	if (isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']]))
47
		$context['sub_action'] = $_REQUEST['sa'];
48
	// We need to support possible old javascript links...
49
	elseif (isset($_GET['pgdownload']))
50
		$context['sub_action'] = 'download';
51
	else
52
		$context['sub_action'] = 'servers';
53
54
	// We need to force the "Download" tab as selected.
55
	$context['menu_data_' . $context['admin_menu_id']]['current_subsection'] = 'packageget';
56
57
	// Now create the tabs for the template.
58
	$context[$context['admin_menu_name']]['tab_data'] = array(
59
		'title' => $txt['package_manager'],
60
		//'help' => 'registrations',
61
		'description' => $txt['package_manager_desc'],
62
		'tabs' => array(
63
			'browse' => array(
64
			),
65
			'packageget' => array(
66
				'description' => $txt['download_packages_desc'],
67
			),
68
			'perms' => array(
69
				'description' => $txt['package_file_perms_desc'],
70
			),
71
			'options' => array(
72
				'description' => $txt['package_install_options_ftp_why'],
73
			),
74
		),
75
	);
76
77
	call_integration_hook('integrate_package_get', array(&$subActions));
78
79
	call_helper($subActions[$context['sub_action']]);
80
}
81
82
/**
83
 * Load a list of package servers.
84
 */
85
function PackageServers()
86
{
87
	global $txt, $context, $sourcedir, $packagesdir, $modSettings, $smcFunc;
88
89
	// Ensure we use the correct template, and page title.
90
	$context['sub_template'] = 'servers';
91
	$context['page_title'] .= ' - ' . $txt['download_packages'];
92
93
	// Load the list of servers.
94
	$request = $smcFunc['db_query']('', '
95
		SELECT id_server, name, url
96
		FROM {db_prefix}package_servers',
97
		array(
98
		)
99
	);
100
	$context['servers'] = array();
101
	while ($row = $smcFunc['db_fetch_assoc']($request))
102
	{
103
		$context['servers'][] = array(
104
			'name' => $row['name'],
105
			'url' => $row['url'],
106
			'id' => $row['id_server'],
107
		);
108
	}
109
	$smcFunc['db_free_result']($request);
110
111
	$context['package_download_broken'] = !is_writable($packagesdir);
112
113
	if ($context['package_download_broken'])
114
	{
115
		smf_chmod($packagesdir, 0777);
116
	}
117
118
	$context['package_download_broken'] = !is_writable($packagesdir);
119
120
	if ($context['package_download_broken'])
121
	{
122 View Code Duplication
		if (isset($_POST['ftp_username']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
123
		{
124
			require_once($sourcedir . '/Class-Package.php');
125
			$ftp = new ftp_connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']);
126
127
			if ($ftp->error === false)
128
			{
129
				// I know, I know... but a lot of people want to type /home/xyz/... which is wrong, but logical.
130
				if (!$ftp->chdir($_POST['ftp_path']))
131
				{
132
					$ftp_error = $ftp->error;
133
					$ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $_POST['ftp_path']));
134
				}
135
			}
136
		}
137
138
		if (!isset($ftp) || $ftp->error !== false)
139
		{
140 View Code Duplication
			if (!isset($ftp))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
141
			{
142
				require_once($sourcedir . '/Class-Package.php');
143
				$ftp = new ftp_connection(null);
144
			}
145
			elseif ($ftp->error !== false && !isset($ftp_error))
146
				$ftp_error = $ftp->last_message === null ? '' : $ftp->last_message;
147
148
			list ($username, $detect_path, $found_path) = $ftp->detect_path($packagesdir);
149
150
			if ($found_path || !isset($_POST['ftp_path']))
151
				$_POST['ftp_path'] = $detect_path;
152
153
			if (!isset($_POST['ftp_username']))
154
				$_POST['ftp_username'] = $username;
155
156
			$context['package_ftp'] = array(
157
				'server' => isset($_POST['ftp_server']) ? $_POST['ftp_server'] : (isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost'),
158
				'port' => isset($_POST['ftp_port']) ? $_POST['ftp_port'] : (isset($modSettings['package_port']) ? $modSettings['package_port'] : '21'),
159
				'username' => isset($_POST['ftp_username']) ? $_POST['ftp_username'] : (isset($modSettings['package_username']) ? $modSettings['package_username'] : ''),
160
				'path' => $_POST['ftp_path'],
161
				'error' => empty($ftp_error) ? null : $ftp_error,
162
			);
163
		}
164
		else
165
		{
166
			$context['package_download_broken'] = false;
167
168
			$ftp->chmod('.', 0777);
169
			$ftp->close();
170
		}
171
	}
172
173
	addInlineJavaScript('
174
	$(\'.new_package_content\').hide();
175
	$(\'.download_new_package\').on(\'click\', function() {
176
		var collapseState = $(\'.new_package_content\').css(\'display\');
177
		var icon = $(\'.download_new_package\').children(\'span\');
178
		var collapsedDiv = $(\'.new_package_content\');
179
180
		if (collapseState == \'none\')
181
		{
182
			collapsedDiv.show(\'slow\');
183
			icon.removeClass(\'toggle_down\').addClass(\'toggle_up\');
184
			icon.prop(\'title\', '. JavaScriptEscape($txt['hide']) .');
185
		}
186
187
		else
188
		{
189
			collapsedDiv.hide(\'slow\');
190
			icon.removeClass(\'toggle_up\').addClass(\'toggle_down\');
191
			icon.prop(\'title\', '. JavaScriptEscape($txt['show']) .');
192
		}
193
194
	});', true);
195
}
196
197
/**
198
 * Browse a server's list of packages.
199
 */
200
function PackageGBrowse()
201
{
202
	global $txt, $context, $scripturl, $sourcedir, $forum_version, $smcFunc;
203
204
	if (isset($_GET['server']))
205
	{
206
		if ($_GET['server'] == '')
207
			redirectexit('action=admin;area=packages;get');
208
209
		$server = (int) $_GET['server'];
210
211
		// Query the server list to find the current server.
212
		$request = $smcFunc['db_query']('', '
213
			SELECT name, url
214
			FROM {db_prefix}package_servers
215
			WHERE id_server = {int:current_server}
216
			LIMIT 1',
217
			array(
218
				'current_server' => $server,
219
			)
220
		);
221
		list ($name, $url) = $smcFunc['db_fetch_row']($request);
222
		$smcFunc['db_free_result']($request);
223
224
		// If the server does not exist, dump out.
225
		if (empty($url))
226
			fatal_lang_error('couldnt_connect', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
227
228
		// If there is a relative link, append to the stored server url.
229
		if (isset($_GET['relative']))
230
			$url = $url . (substr($url, -1) == '/' ? '' : '/') . $_GET['relative'];
231
232
		// Clear any "absolute" URL.  Since "server" is present, "absolute" is garbage.
233
		unset($_GET['absolute']);
234
	}
235
	elseif (isset($_GET['absolute']) && $_GET['absolute'] != '')
236
	{
237
		// Initialize the requried variables.
238
		$server = '';
239
		$url = $_GET['absolute'];
240
		$name = '';
241
		$_GET['package'] = $url . '/packages.xml?language=' . $context['user']['language'];
242
243
		// Clear any "relative" URL.  Since "server" is not present, "relative" is garbage.
244
		unset($_GET['relative']);
245
246
		$token = checkConfirm('get_absolute_url');
247
		if ($token !== true)
248
		{
249
			$context['sub_template'] = 'package_confirm';
250
251
			$context['page_title'] = $txt['package_servers'];
252
			$context['confirm_message'] = sprintf($txt['package_confirm_view_package_content'], $smcFunc['htmlspecialchars']($_GET['absolute']));
253
			$context['proceed_href'] = $scripturl . '?action=admin;area=packages;get;sa=browse;absolute=' . urlencode($_GET['absolute']) . ';confirm=' . $token;
254
255
			return;
256
		}
257
	}
258
	// Minimum required parameter did not exist so dump out.
259
	else
260
		fatal_lang_error('couldnt_connect', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
261
262
	// Attempt to connect.  If unsuccessful... try the URL.
263
	if (!isset($_GET['package']) || file_exists($_GET['package']))
264
		$_GET['package'] = $url . '/packages.xml?language=' . $context['user']['language'];
0 ignored issues
show
Bug introduced by
The variable $url does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
265
266
	// Check to be sure the packages.xml file actually exists where it is should be... or dump out.
267
	if ((isset($_GET['absolute']) || isset($_GET['relative'])) && !url_exists($_GET['package']))
268
		fatal_lang_error('packageget_unable', false, array($url . '/index.php'));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
269
270
	// Might take some time.
271
	@set_time_limit(600);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
272
273
	// Read packages.xml and parse into xmlArray. (the true tells it to trim things ;).)
274
	require_once($sourcedir . '/Class-Package.php');
275
	$listing = new xmlArray(fetch_web_data($_GET['package']), true);
0 ignored issues
show
Security Bug introduced by
It seems like fetch_web_data($_GET['package']) targeting fetch_web_data() can also be of type false; however, xmlArray::__construct() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
276
277
	// Errm.... empty file?  Try the URL....
278
	if (!$listing->exists('package-list'))
279
		fatal_lang_error('packageget_unable', false, array($url . '/index.php'));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
280
281
	// List out the packages...
282
	$context['package_list'] = array();
283
284
	$listing = $listing->path('package-list[0]');
285
286
	// Use the package list's name if it exists.
287
	if ($listing->exists('list-title'))
288
		$name = $smcFunc['htmlspecialchars']($listing->fetch('list-title'));
289
290
	// Pick the correct template.
291
	$context['sub_template'] = 'package_list';
292
293
	$context['page_title'] = $txt['package_servers'] . ($name != '' ? ' - ' . $name : '');
0 ignored issues
show
Bug introduced by
The variable $name does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
294
	$context['package_server'] = $server;
0 ignored issues
show
Bug introduced by
The variable $server does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
295
296
	// By default we use an unordered list, unless there are no lists with more than one package.
297
	$context['list_type'] = 'ul';
298
299
	$instmods = loadInstalledPackages();
300
301
	$installed_mods = array();
302
	// Look through the list of installed mods...
303
	foreach ($instmods as $installed_mod)
304
		$installed_mods[$installed_mod['package_id']] = $installed_mod['version'];
305
306
	// Get default author and email if they exist.
307
	if ($listing->exists('default-author'))
308
	{
309
		$default_author = $smcFunc['htmlspecialchars']($listing->fetch('default-author'));
310
		if ($listing->exists('default-author/@email') && filter_var($listing->fetch('default-author/@email'), FILTER_VALIDATE_EMAIL))
311
			$default_email = $smcFunc['htmlspecialchars']($listing->fetch('default-author/@email'));
312
	}
313
314
	// Get default web site if it exists.
315 View Code Duplication
	if ($listing->exists('default-website'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
316
	{
317
		$default_website = $smcFunc['htmlspecialchars']($listing->fetch('default-website'));
318
		if ($listing->exists('default-website/@title'))
319
			$default_title = $smcFunc['htmlspecialchars']($listing->fetch('default-website/@title'));
320
	}
321
322
	$the_version = strtr($forum_version, array('SMF ' => ''));
323
	if (!empty($_SESSION['version_emulate']))
324
		$the_version = $_SESSION['version_emulate'];
325
326
	$packageNum = 0;
327
	$packageSection = 0;
328
329
	$sections = $listing->set('section');
330
	foreach ($sections as $i => $section)
331
	{
332
		$context['package_list'][$packageSection] = array(
333
			'title' => '',
334
			'text' => '',
335
			'items' => array(),
336
		);
337
338
		$packages = $section->set('title|heading|text|remote|rule|modification|language|avatar-pack|theme|smiley-set');
339
		foreach ($packages as $thisPackage)
340
		{
341
			$package = array(
342
				'type' => $thisPackage->name(),
343
			);
344
345
			if (in_array($package['type'], array('title', 'text')))
346
				$context['package_list'][$packageSection][$package['type']] = $smcFunc['htmlspecialchars']($thisPackage->fetch('.'));
347
			// It's a Title, Heading, Rule or Text.
348
			elseif (in_array($package['type'], array('heading', 'rule')))
349
				$package['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('.'));
350
			// It's a Remote link.
351
			elseif ($package['type'] == 'remote')
352
			{
353
				$remote_type = $thisPackage->exists('@type') ? $thisPackage->fetch('@type') : 'relative';
354
355
				if ($remote_type == 'relative' && substr($thisPackage->fetch('@href'), 0, 7) != 'http://' && substr($thisPackage->fetch('@href'), 0, 8) != 'https://')
356
				{
357 View Code Duplication
					if (isset($_GET['absolute']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
358
						$current_url = $_GET['absolute'] . '/';
359
					elseif (isset($_GET['relative']))
360
						$current_url = $_GET['relative'] . '/';
361
					else
362
						$current_url = '';
363
364
					$current_url .= $thisPackage->fetch('@href');
365
					if (isset($_GET['absolute']))
366
						$package['href'] = $scripturl . '?action=admin;area=packages;get;sa=browse;absolute=' . $current_url;
367
					else
368
						$package['href'] = $scripturl . '?action=admin;area=packages;get;sa=browse;server=' . $context['package_server'] . ';relative=' . $current_url;
369
				}
370
				else
371
				{
372
					$current_url = $thisPackage->fetch('@href');
373
					$package['href'] = $scripturl . '?action=admin;area=packages;get;sa=browse;absolute=' . $current_url;
374
				}
375
376
				$package['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('.'));
377
				$package['link'] = '<a href="' . $package['href'] . '">' . $package['name'] . '</a>';
378
			}
379
			// It's a package...
380
			else
381
			{
382 View Code Duplication
				if (isset($_GET['absolute']))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
383
					$current_url = $_GET['absolute'] . '/';
384
				elseif (isset($_GET['relative']))
385
					$current_url = $_GET['relative'] . '/';
386
				else
387
					$current_url = '';
388
389
				$server_att = $server != '' ? ';server=' . $server : '';
390
391
				$package += $thisPackage->to_array();
392
393
				if (isset($package['website']))
394
					unset($package['website']);
395
				$package['author'] = array();
396
397
				if ($package['description'] == '')
398
					$package['description'] = $txt['package_no_description'];
399
				else
400
					$package['description'] = parse_bbc(preg_replace('~\[[/]?html\]~i', '', $smcFunc['htmlspecialchars']($package['description'])));
401
402
				$package['is_installed'] = isset($installed_mods[$package['id']]);
403
				$package['is_current'] = $package['is_installed'] && ($installed_mods[$package['id']] == $package['version']);
404
				$package['is_newer'] = $package['is_installed'] && ($installed_mods[$package['id']] > $package['version']);
405
406
				// This package is either not installed, or installed but old.  Is it supported on this version of SMF?
407
				if (!$package['is_installed'] || (!$package['is_current'] && !$package['is_newer']))
408
				{
409
					if ($thisPackage->exists('version/@for'))
410
						$package['can_install'] = matchPackageVersion($the_version, $thisPackage->fetch('version/@for'));
411
				}
412
				// Okay, it's already installed AND up to date.
413
				else
414
					$package['can_install'] = false;
415
416
				$already_exists = getPackageInfo(basename($package['filename']));
417
				$package['download_conflict'] = is_array($already_exists) && $already_exists['id'] == $package['id'] && $already_exists['version'] != $package['version'];
418
419
				$package['href'] = $url . '/' . $package['filename'];
420
				$package['link'] = '<a href="' . $package['href'] . '">' . $package['name'] . '</a>';
421
				$package['download']['href'] = $scripturl . '?action=admin;area=packages;get;sa=download' . $server_att . ';package=' . $current_url . $package['filename'] . ($package['download_conflict'] ? ';conflict' : '') . ';' . $context['session_var'] . '=' . $context['session_id'];
422
				$package['download']['link'] = '<a href="' . $package['download']['href'] . '">' . $package['name'] . '</a>';
423
424
				if ($thisPackage->exists('author') || isset($default_author))
425
				{
426
					if ($thisPackage->exists('author/@email') && filter_var($thisPackage->fetch('author/@email'), FILTER_VALIDATE_EMAIL))
427
						$package['author']['email'] = $thisPackage->fetch('author/@email');
428
					elseif (isset($default_email))
429
						$package['author']['email'] = $default_email;
430
431
					if ($thisPackage->exists('author') && $thisPackage->fetch('author') != '')
432
						$package['author']['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('author'));
433
					else
434
						$package['author']['name'] = $default_author;
0 ignored issues
show
Bug introduced by
The variable $default_author does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
435
436
					if (!empty($package['author']['email']))
437
						$package['author']['link'] = '<a href="mailto:' . $package['author']['email'] . '">' . $package['author']['name'] . '</a>';
438
				}
439
440
				if ($thisPackage->exists('website') || isset($default_website))
441
				{
442
					if ($thisPackage->exists('website') && $thisPackage->exists('website/@title'))
443
						$package['author']['website']['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('website/@title'));
444
					elseif (isset($default_title))
445
						$package['author']['website']['name'] = $default_title;
446
					elseif ($thisPackage->exists('website'))
447
						$package['author']['website']['name'] = $smcFunc['htmlspecialchars']($thisPackage->fetch('website'));
448
					else
449
						$package['author']['website']['name'] = $default_website;
0 ignored issues
show
Bug introduced by
The variable $default_website does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
450
451 View Code Duplication
					if ($thisPackage->exists('website') && $thisPackage->fetch('website') != '')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
452
						$authorhompage = $smcFunc['htmlspecialchars']($thisPackage->fetch('website'));
453
					else
454
						$authorhompage = $default_website;
455
456
					$package['author']['website']['href'] = $authorhompage;
457
					$package['author']['website']['link'] = '<a href="' . $authorhompage . '">' . $package['author']['website']['name'] . '</a>';
458
				}
459
				else
460
				{
461
					$package['author']['website']['href'] = '';
462
					$package['author']['website']['link'] = '';
463
				}
464
			}
465
466
			$package['is_remote'] = $package['type'] == 'remote';
467
			$package['is_title'] = $package['type'] == 'title';
468
			$package['is_heading'] = $package['type'] == 'heading';
469
			$package['is_text'] = $package['type'] == 'text';
470
			$package['is_line'] = $package['type'] == 'rule';
471
472
			$packageNum = in_array($package['type'], array('title', 'heading', 'text', 'remote', 'rule')) ? 0 : $packageNum + 1;
473
			$package['count'] = $packageNum;
474
475
			if (!in_array($package['type'], array('title', 'text')))
476
				$context['package_list'][$packageSection]['items'][] = $package;
477
478
			if ($package['count'] > 1)
479
				$context['list_type'] = 'ol';
480
		}
481
482
		$packageSection++;
483
	}
484
485
	// Lets make sure we get a nice new spiffy clean $package to work with.  Otherwise we get PAIN!
486
	unset($package);
487
488
	foreach ($context['package_list'] as $ps_id => $packageSection)
489
	{
490
		foreach ($packageSection['items'] as $i => $package)
491
		{
492
			if ($package['count'] == 0 || isset($package['can_install']))
493
				continue;
494
495
			$context['package_list'][$ps_id]['items'][$i]['can_install'] = false;
496
497
			$packageInfo = getPackageInfo($url . '/' . $package['filename']);
498
			if (is_array($packageInfo) && $packageInfo['xml']->exists('install'))
499
			{
500
				$installs = $packageInfo['xml']->set('install');
501
				foreach ($installs as $install)
502
				{
503
					if (!$install->exists('@for') || matchPackageVersion($the_version, $install->fetch('@for')))
504
					{
505
						// Okay, this one is good to go.
506
						$context['package_list'][$ps_id]['items'][$i]['can_install'] = true;
507
						break;
508
					}
509
510
					// no install found for this version, lets see if one exists for another
511
					if ($context['package_list'][$ps_id]['items'][$i]['can_install'] === false && $install->exists('@for'))
512
					{
513
						$reset = true;
514
515
						// Get the highest install version that is available from the package
516
						foreach ($installs as $install)
517
						{
518
							$context['package_list'][$ps_id]['items'][$i]['can_emulate_install'] = matchHighestPackageVersion($install->fetch('@for'), $reset, $the_version);
519
							$reset = false;
520
						}
521
					}
522
				}
523
			}
524
		}
525
	}
526
}
527
528
/**
529
 * Download a package.
530
 */
531
function PackageDownload()
532
{
533
	global $txt, $scripturl, $context, $packagesdir, $smcFunc;
534
535
	// Use the downloaded sub template.
536
	$context['sub_template'] = 'downloaded';
537
538
	// Security is good...
539
	checkSession('get');
540
541
	// To download something, we need a valid server or url.
542
	if (empty($_GET['server']) && (!empty($_GET['get']) && !empty($_REQUEST['package'])))
543
		fatal_lang_error('package_get_error_is_zero', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
544
545
	if (isset($_GET['server']))
546
	{
547
		$server = (int) $_GET['server'];
548
549
		// Query the server table to find the requested server.
550
		$request = $smcFunc['db_query']('', '
551
			SELECT name, url
552
			FROM {db_prefix}package_servers
553
			WHERE id_server = {int:current_server}
554
			LIMIT 1',
555
			array(
556
				'current_server' => $server,
557
			)
558
		);
559
		list ($name, $url) = $smcFunc['db_fetch_row']($request);
0 ignored issues
show
Unused Code introduced by
The assignment to $name is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
560
		$smcFunc['db_free_result']($request);
561
562
		// If server does not exist then dump out.
563
		if (empty($url))
564
			fatal_lang_error('couldnt_connect', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
565
566
		$url = $url . '/';
567
	}
568
	else
569
	{
570
		// Initialize the requried variables.
571
		$server = '';
572
		$url = '';
573
	}
574
575
	if (isset($_REQUEST['byurl']) && !empty($_POST['filename']))
576
		$package_name = basename($_REQUEST['filename']);
577
	else
578
		$package_name = basename($_REQUEST['package']);
579
580
	if (isset($_REQUEST['conflict']) || (isset($_REQUEST['auto']) && file_exists($packagesdir . '/' . $package_name)))
581
	{
582
		// Find the extension, change abc.tar.gz to abc_1.tar.gz...
583
		if (strrpos(substr($package_name, 0, -3), '.') !== false)
584
		{
585
			$ext = substr($package_name, strrpos(substr($package_name, 0, -3), '.'));
586
			$package_name = substr($package_name, 0, strrpos(substr($package_name, 0, -3), '.')) . '_';
587
		}
588
		else
589
			$ext = '';
590
591
		// Find the first available.
592
		$i = 1;
593
		while (file_exists($packagesdir . '/' . $package_name . $i . $ext))
594
			$i++;
595
596
		$package_name = $package_name . $i . $ext;
597
	}
598
599
	// Use FTP if necessary.
600
	create_chmod_control(array($packagesdir . '/' . $package_name), array('destination_url' => $scripturl . '?action=admin;area=packages;get;sa=download' . (isset($_GET['server']) ? ';server=' . $_GET['server'] : '') . (isset($_REQUEST['auto']) ? ';auto' : '') . ';package=' . $_REQUEST['package'] . (isset($_REQUEST['conflict']) ? ';conflict' : '') . ';' . $context['session_var'] . '=' . $context['session_id'], 'crash_on_error' => true));
601
	package_put_contents($packagesdir . '/' . $package_name, fetch_web_data($url . $_REQUEST['package']));
0 ignored issues
show
Security Bug introduced by
It seems like fetch_web_data($url . $_REQUEST['package']) targeting fetch_web_data() can also be of type false; however, package_put_contents() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
602
603
	// Done!  Did we get this package automatically?
604
	if (preg_match('~^http://[\w_\-]+\.simplemachines\.org/~', $_REQUEST['package']) == 1 && strpos($_REQUEST['package'], 'dlattach') === false && isset($_REQUEST['auto']))
605
		redirectexit('action=admin;area=packages;sa=install;package=' . $package_name);
606
607
	// You just downloaded a mod from SERVER_NAME_GOES_HERE.
608
	$context['package_server'] = $server;
609
610
	$context['package'] = getPackageInfo($package_name);
611
612
	if (!is_array($context['package']))
613
		fatal_lang_error('package_cant_download', false);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
614
615 View Code Duplication
	if ($context['package']['type'] == 'modification')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
616
		$context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['install_mod'] . ' ]</a>';
617
	elseif ($context['package']['type'] == 'avatar')
618
		$context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['use_avatars'] . ' ]</a>';
619
	elseif ($context['package']['type'] == 'language')
620
		$context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['add_languages'] . ' ]</a>';
621
	else
622
		$context['package']['install']['link'] = '';
623
624
	// Does a 3rd party hook want to do some additional changes?
625
	call_integration_hook('integrate_package_download');
626
627
	$context['package']['list_files']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=list;package=' . $context['package']['filename'] . '">[ ' . $txt['list_files'] . ' ]</a>';
628
629
	// Free a little bit of memory...
630
	unset($context['package']['xml']);
631
632
	$context['page_title'] = $txt['download_success'];
633
}
634
635
/**
636
 * Upload a new package to the directory.
637
 */
638
function PackageUpload()
639
{
640
	global $txt, $scripturl, $context, $packagesdir;
641
642
	// Setup the correct template, even though I'll admit we ain't downloading ;)
643
	$context['sub_template'] = 'downloaded';
644
	$allowext = array('.zip','.tgz','.gz');
645
	// @todo Use FTP if the Packages directory is not writable.
646
647
	// Check the file was even sent!
648
	if (!isset($_FILES['package']['name']) || $_FILES['package']['name'] == '')
649
		fatal_lang_error('package_upload_error_nofile');
650 View Code Duplication
	elseif (!is_uploaded_file($_FILES['package']['tmp_name']) || (ini_get('open_basedir') == '' && !file_exists($_FILES['package']['tmp_name'])))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
651
		fatal_lang_error('package_upload_error_failed');
652
653
	// Make sure it has a sane filename.
654
	$_FILES['package']['name'] = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $_FILES['package']['name']);
655
	$extension = substr(strrchr(strtolower($_FILES['package']['name']), '.'), 0);
656
	if(!in_array($extension, $allowext))
657
	{
658
		fatal_lang_error('package_upload_error_supports', false, array('zip, tgz, tar.gz'));
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
659
	}
660
	
661
	// We only need the filename...
662
	$extension = ($extension == '.gz') ? '.tar.gz' : $extension ;
663
	$packageName = time() . $extension;
664
665
	// Setup the destination and throw an error if the file is already there!
666
	$destination = $packagesdir . '/' . $packageName;
667
	// @todo Maybe just roll it like we do for downloads?
668
	if (file_exists($destination))
669
		fatal_lang_error('package_upload_error_exists');
670
671
	// Now move the file.
672
	move_uploaded_file($_FILES['package']['tmp_name'], $destination);
673
	smf_chmod($destination, 0777);
674
675
	// If we got this far that should mean it's available.
676
	$context['package'] = getPackageInfo($packageName);
677
	$context['package_server'] = '';
678
679
	// Not really a package, you lazy bum!
680
	if (!is_array($context['package']))
681
	{
682
		@unlink($destination);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
683
		loadLanguage('Errors');
684
		$txt[$context['package']] = str_replace('{MANAGETHEMEURL}', $scripturl . '?action=admin;area=theme;sa=admin;' . $context['session_var'] . '=' . $context['session_id'] . '#theme_install', $txt[$context['package']]);
685
		fatal_lang_error('package_upload_error_broken', false, $txt[$context['package']]);
0 ignored issues
show
Documentation introduced by
false is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
686
	}
687
	// Is it already uploaded, maybe?
688
	elseif ($dir = @opendir($packagesdir))
689
	{
690
		while ($package = readdir($dir))
691
		{
692 View Code Duplication
			if ($package == '.' || $package == '..' || $package == 'temp' || $package == $packageName || (!(is_dir($packagesdir . '/' . $package) && file_exists($packagesdir . '/' . $package . '/package-info.xml')) && substr(strtolower($package), -7) != '.tar.gz' && substr(strtolower($package), -4) != '.tgz' && substr(strtolower($package), -4) != '.zip'))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
693
				continue;
694
695
			$packageInfo = getPackageInfo($package);
696
			if (!is_array($packageInfo))
697
				continue;
698
699
			if ($packageInfo['id'] == $context['package']['id'] && $packageInfo['version'] == $context['package']['version'])
700
			{
701
				@unlink($destination);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
702
				loadLanguage('Errors');
703
				fatal_lang_error('package_upload_error_exists');
704
			}
705
		}
706
		closedir($dir);
707
	}
708
709 View Code Duplication
	if ($context['package']['type'] == 'modification')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
710
		$context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['install_mod'] . ' ]</a>';
711
	elseif ($context['package']['type'] == 'avatar')
712
		$context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['use_avatars'] . ' ]</a>';
713
	elseif ($context['package']['type'] == 'language')
714
		$context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['add_languages'] . ' ]</a>';
715
	else
716
		$context['package']['install']['link'] = '';
717
718
	// Does a 3rd party hook want to do some additional changes?
719
	call_integration_hook('integrate_package_upload');
720
721
	$context['package']['list_files']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=list;package=' . $context['package']['filename'] . '">[ ' . $txt['list_files'] . ' ]</a>';
722
723
	unset($context['package']['xml']);
724
725
	$context['page_title'] = $txt['package_uploaded_success'];
726
}
727
728
/**
729
 * Add a package server to the list.
730
 */
731
function PackageServerAdd()
732
{
733
	global $smcFunc;
734
735
	// Validate the user.
736
	checkSession();
737
738
	// If they put a slash on the end, get rid of it.
739
	if (substr($_POST['serverurl'], -1) == '/')
740
		$_POST['serverurl'] = substr($_POST['serverurl'], 0, -1);
741
742
	// Are they both nice and clean?
743
	$servername = trim($smcFunc['htmlspecialchars']($_POST['servername']));
744
	$serverurl = trim($smcFunc['htmlspecialchars']($_POST['serverurl']));
745
746
	// Make sure the URL has the correct prefix.
747
	if (strpos($serverurl, 'http://') !== 0 && strpos($serverurl, 'https://') !== 0)
748
		$serverurl = 'http://' . $serverurl;
749
750
	$smcFunc['db_insert']('',
751
		'{db_prefix}package_servers',
752
		array(
753
			'name' => 'string-255', 'url' => 'string-255',
754
		),
755
		array(
756
			$servername, $serverurl,
757
		),
758
		array('id_server')
759
	);
760
761
	redirectexit('action=admin;area=packages;get');
762
}
763
764
/**
765
 * Remove a server from the list.
766
 */
767
function PackageServerRemove()
768
{
769
	global $smcFunc;
770
771
	checkSession('get');
772
773
	$smcFunc['db_query']('', '
774
		DELETE FROM {db_prefix}package_servers
775
		WHERE id_server = {int:current_server}',
776
		array(
777
			'current_server' => (int) $_GET['server'],
778
		)
779
	);
780
781
	redirectexit('action=admin;area=packages;get');
782
}
783
784
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
785