Yoshi2889 /
SMF2.1
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 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 2017 Simple Machines and individual contributors |
||
| 11 | * @license http://www.simplemachines.org/about/smf/license.php BSD |
||
| 12 | * |
||
| 13 | * @version 2.1 Beta 4 |
||
| 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'])) |
|
| 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)) |
|
| 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); |
||
| 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); |
||
| 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
|
|||
| 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')); |
||
| 269 | |||
| 270 | // Might take some time. |
||
| 271 | @set_time_limit(600); |
||
|
0 ignored issues
–
show
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
|
|||
| 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')); |
||
| 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
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
Loading history...
|
|||
| 294 | $context['package_server'] = $server; |
||
|
0 ignored issues
–
show
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
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')) |
|
| 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'])) |
|
| 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'])) |
|
| 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
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
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
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
Loading history...
|
|||
| 450 | |||
| 451 | View Code Duplication | if ($thisPackage->exists('website') && $thisPackage->fetch('website') != '') |
|
| 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); |
||
| 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); |
||
| 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); |
||
| 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
|
|||
| 602 | |||
| 603 | // Done! Did we get this package automatically? |
||
| 604 | // @ TODO: These are usually update packages. Allowing both for now until more testing has been done. |
||
| 605 | if (preg_match('~^https?://[\w_\-]+\.simplemachines\.org/~', $_REQUEST['package']) == 1 && strpos($_REQUEST['package'], 'dlattach') === false && isset($_REQUEST['auto'])) |
||
| 606 | redirectexit('action=admin;area=packages;sa=install;package=' . $package_name); |
||
| 607 | |||
| 608 | // You just downloaded a mod from SERVER_NAME_GOES_HERE. |
||
| 609 | $context['package_server'] = $server; |
||
| 610 | |||
| 611 | $context['package'] = getPackageInfo($package_name); |
||
| 612 | |||
| 613 | if (!is_array($context['package'])) |
||
| 614 | fatal_lang_error('package_cant_download', false); |
||
| 615 | |||
| 616 | View Code Duplication | if ($context['package']['type'] == 'modification') |
|
| 617 | $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['install_mod'] . ' ]</a>'; |
||
| 618 | elseif ($context['package']['type'] == 'avatar') |
||
| 619 | $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['use_avatars'] . ' ]</a>'; |
||
| 620 | elseif ($context['package']['type'] == 'language') |
||
| 621 | $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['add_languages'] . ' ]</a>'; |
||
| 622 | else |
||
| 623 | $context['package']['install']['link'] = ''; |
||
| 624 | |||
| 625 | // Does a 3rd party hook want to do some additional changes? |
||
| 626 | call_integration_hook('integrate_package_download'); |
||
| 627 | |||
| 628 | $context['package']['list_files']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=list;package=' . $context['package']['filename'] . '">[ ' . $txt['list_files'] . ' ]</a>'; |
||
| 629 | |||
| 630 | // Free a little bit of memory... |
||
| 631 | unset($context['package']['xml']); |
||
| 632 | |||
| 633 | $context['page_title'] = $txt['download_success']; |
||
| 634 | } |
||
| 635 | |||
| 636 | /** |
||
| 637 | * Upload a new package to the directory. |
||
| 638 | */ |
||
| 639 | function PackageUpload() |
||
| 640 | { |
||
| 641 | global $txt, $scripturl, $context, $packagesdir; |
||
| 642 | |||
| 643 | // Setup the correct template, even though I'll admit we ain't downloading ;) |
||
| 644 | $context['sub_template'] = 'downloaded'; |
||
| 645 | $allowext = array('.zip','.tgz','.gz'); |
||
| 646 | // @todo Use FTP if the Packages directory is not writable. |
||
| 647 | |||
| 648 | // Check the file was even sent! |
||
| 649 | if (!isset($_FILES['package']['name']) || $_FILES['package']['name'] == '') |
||
| 650 | fatal_lang_error('package_upload_error_nofile'); |
||
| 651 | View Code Duplication | elseif (!is_uploaded_file($_FILES['package']['tmp_name']) || (ini_get('open_basedir') == '' && !file_exists($_FILES['package']['tmp_name']))) |
|
| 652 | fatal_lang_error('package_upload_error_failed'); |
||
| 653 | |||
| 654 | // Make sure it has a sane filename. |
||
| 655 | $_FILES['package']['name'] = preg_replace(array('/\s/', '/\.[\.]+/', '/[^\w_\.\-]/'), array('_', '.', ''), $_FILES['package']['name']); |
||
| 656 | $extension = substr(strrchr(strtolower($_FILES['package']['name']), '.'), 0); |
||
| 657 | if(!in_array($extension, $allowext)) |
||
| 658 | { |
||
| 659 | fatal_lang_error('package_upload_error_supports', false, array('zip, tgz, tar.gz')); |
||
| 660 | } |
||
| 661 | |||
| 662 | // We only need the filename... |
||
| 663 | $extension = ($extension == '.gz') ? '.tar.gz' : $extension ; |
||
| 664 | $packageName = time() . $extension; |
||
| 665 | |||
| 666 | // Setup the destination and throw an error if the file is already there! |
||
| 667 | $destination = $packagesdir . '/' . $packageName; |
||
| 668 | // @todo Maybe just roll it like we do for downloads? |
||
| 669 | if (file_exists($destination)) |
||
| 670 | fatal_lang_error('package_upload_error_exists'); |
||
| 671 | |||
| 672 | // Now move the file. |
||
| 673 | move_uploaded_file($_FILES['package']['tmp_name'], $destination); |
||
| 674 | smf_chmod($destination, 0777); |
||
| 675 | |||
| 676 | // If we got this far that should mean it's available. |
||
| 677 | $context['package'] = getPackageInfo($packageName); |
||
| 678 | $context['package_server'] = ''; |
||
| 679 | |||
| 680 | // Not really a package, you lazy bum! |
||
| 681 | if (!is_array($context['package'])) |
||
| 682 | { |
||
| 683 | @unlink($destination); |
||
|
0 ignored issues
–
show
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...
|
|||
| 684 | loadLanguage('Errors'); |
||
| 685 | $txt[$context['package']] = str_replace('{MANAGETHEMEURL}', $scripturl . '?action=admin;area=theme;sa=admin;' . $context['session_var'] . '=' . $context['session_id'] . '#theme_install', $txt[$context['package']]); |
||
| 686 | fatal_lang_error('package_upload_error_broken', false, $txt[$context['package']]); |
||
| 687 | } |
||
| 688 | // Is it already uploaded, maybe? |
||
| 689 | elseif ($dir = @opendir($packagesdir)) |
||
| 690 | { |
||
| 691 | while ($package = readdir($dir)) |
||
| 692 | { |
||
| 693 | 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')) |
|
| 694 | continue; |
||
| 695 | |||
| 696 | $packageInfo = getPackageInfo($package); |
||
| 697 | if (!is_array($packageInfo)) |
||
| 698 | continue; |
||
| 699 | |||
| 700 | if ($packageInfo['id'] == $context['package']['id'] && $packageInfo['version'] == $context['package']['version']) |
||
| 701 | { |
||
| 702 | @unlink($destination); |
||
|
0 ignored issues
–
show
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...
|
|||
| 703 | loadLanguage('Errors'); |
||
| 704 | fatal_lang_error('package_upload_error_exists'); |
||
| 705 | } |
||
| 706 | } |
||
| 707 | closedir($dir); |
||
| 708 | } |
||
| 709 | |||
| 710 | View Code Duplication | if ($context['package']['type'] == 'modification') |
|
| 711 | $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['install_mod'] . ' ]</a>'; |
||
| 712 | elseif ($context['package']['type'] == 'avatar') |
||
| 713 | $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['use_avatars'] . ' ]</a>'; |
||
| 714 | elseif ($context['package']['type'] == 'language') |
||
| 715 | $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['add_languages'] . ' ]</a>'; |
||
| 716 | else |
||
| 717 | $context['package']['install']['link'] = ''; |
||
| 718 | |||
| 719 | // Does a 3rd party hook want to do some additional changes? |
||
| 720 | call_integration_hook('integrate_package_upload'); |
||
| 721 | |||
| 722 | $context['package']['list_files']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=list;package=' . $context['package']['filename'] . '">[ ' . $txt['list_files'] . ' ]</a>'; |
||
| 723 | |||
| 724 | unset($context['package']['xml']); |
||
| 725 | |||
| 726 | $context['page_title'] = $txt['package_uploaded_success']; |
||
| 727 | } |
||
| 728 | |||
| 729 | /** |
||
| 730 | * Add a package server to the list. |
||
| 731 | */ |
||
| 732 | function PackageServerAdd() |
||
| 733 | { |
||
| 734 | global $smcFunc; |
||
| 735 | |||
| 736 | // Validate the user. |
||
| 737 | checkSession(); |
||
| 738 | |||
| 739 | // If they put a slash on the end, get rid of it. |
||
| 740 | if (substr($_POST['serverurl'], -1) == '/') |
||
| 741 | $_POST['serverurl'] = substr($_POST['serverurl'], 0, -1); |
||
| 742 | |||
| 743 | // Are they both nice and clean? |
||
| 744 | $servername = trim($smcFunc['htmlspecialchars']($_POST['servername'])); |
||
| 745 | $serverurl = trim($smcFunc['htmlspecialchars']($_POST['serverurl'])); |
||
| 746 | |||
| 747 | // Make sure the URL has the correct prefix. |
||
| 748 | if (strpos($serverurl, 'http://') !== 0 && strpos($serverurl, 'https://') !== 0) |
||
| 749 | $serverurl = 'http://' . $serverurl; |
||
| 750 | |||
| 751 | $smcFunc['db_insert']('', |
||
| 752 | '{db_prefix}package_servers', |
||
| 753 | array( |
||
| 754 | 'name' => 'string-255', 'url' => 'string-255', |
||
| 755 | ), |
||
| 756 | array( |
||
| 757 | $servername, $serverurl, |
||
| 758 | ), |
||
| 759 | array('id_server') |
||
| 760 | ); |
||
| 761 | |||
| 762 | redirectexit('action=admin;area=packages;get'); |
||
| 763 | } |
||
| 764 | |||
| 765 | /** |
||
| 766 | * Remove a server from the list. |
||
| 767 | */ |
||
| 768 | function PackageServerRemove() |
||
| 769 | { |
||
| 770 | global $smcFunc; |
||
| 771 | |||
| 772 | checkSession('get'); |
||
| 773 | |||
| 774 | $smcFunc['db_query']('', ' |
||
| 775 | DELETE FROM {db_prefix}package_servers |
||
| 776 | WHERE id_server = {int:current_server}', |
||
| 777 | array( |
||
| 778 | 'current_server' => (int) $_GET['server'], |
||
| 779 | ) |
||
| 780 | ); |
||
| 781 | |||
| 782 | redirectexit('action=admin;area=packages;get'); |
||
| 783 | } |
||
| 784 | |||
| 785 | ?> |
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:
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
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: