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 is the main 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 | * This is the notoriously defunct package manager..... :/. |
||
| 21 | */ |
||
| 22 | function Packages() |
||
| 23 | { |
||
| 24 | global $txt, $sourcedir, $context; |
||
| 25 | |||
| 26 | // @todo Remove this! |
||
| 27 | if (isset($_GET['get']) || isset($_GET['pgdownload'])) |
||
| 28 | { |
||
| 29 | require_once($sourcedir . '/PackageGet.php'); |
||
| 30 | return PackageGet(); |
||
| 31 | } |
||
| 32 | |||
| 33 | isAllowedTo('admin_forum'); |
||
| 34 | |||
| 35 | // Load all the basic stuff. |
||
| 36 | require_once($sourcedir . '/Subs-Package.php'); |
||
| 37 | loadLanguage('Packages'); |
||
| 38 | loadTemplate('Packages', 'admin'); |
||
| 39 | |||
| 40 | $context['page_title'] = $txt['package']; |
||
| 41 | |||
| 42 | // Delegation makes the world... that is, the package manager go 'round. |
||
| 43 | $subActions = array( |
||
| 44 | 'browse' => 'PackageBrowse', |
||
| 45 | 'remove' => 'PackageRemove', |
||
| 46 | 'list' => 'PackageList', |
||
| 47 | 'ftptest' => 'PackageFTPTest', |
||
| 48 | 'install' => 'PackageInstallTest', |
||
| 49 | 'install2' => 'PackageInstall', |
||
| 50 | 'uninstall' => 'PackageInstallTest', |
||
| 51 | 'uninstall2' => 'PackageInstall', |
||
| 52 | 'options' => 'PackageOptions', |
||
| 53 | 'perms' => 'PackagePermissions', |
||
| 54 | 'flush' => 'FlushInstall', |
||
| 55 | 'examine' => 'ExamineFile', |
||
| 56 | 'showoperations' => 'ViewOperations', |
||
| 57 | ); |
||
| 58 | |||
| 59 | // Work out exactly who it is we are calling. |
||
| 60 | if (isset($_REQUEST['sa']) && isset($subActions[$_REQUEST['sa']])) |
||
| 61 | $context['sub_action'] = $_REQUEST['sa']; |
||
| 62 | else |
||
| 63 | $context['sub_action'] = 'browse'; |
||
| 64 | |||
| 65 | // Set up some tabs... |
||
| 66 | $context[$context['admin_menu_name']]['tab_data'] = array( |
||
| 67 | 'title' => $txt['package_manager'], |
||
| 68 | // @todo 'help' => 'registrations', |
||
| 69 | 'description' => $txt['package_manager_desc'], |
||
| 70 | 'tabs' => array( |
||
| 71 | 'browse' => array( |
||
| 72 | ), |
||
| 73 | 'packageget' => array( |
||
| 74 | 'description' => $txt['download_packages_desc'], |
||
| 75 | ), |
||
| 76 | 'perms' => array( |
||
| 77 | 'description' => $txt['package_file_perms_desc'], |
||
| 78 | ), |
||
| 79 | 'options' => array( |
||
| 80 | 'description' => $txt['package_install_options_desc'], |
||
| 81 | ), |
||
| 82 | ), |
||
| 83 | ); |
||
| 84 | |||
| 85 | if ($context['sub_action'] == 'browse') |
||
| 86 | loadJavaScriptFile('suggest.js', array('defer' => false), 'smf_suggest'); |
||
| 87 | |||
| 88 | call_integration_hook('integrate_manage_packages', array(&$subActions)); |
||
| 89 | |||
| 90 | // Call the function we're handing control to. |
||
| 91 | call_helper($subActions[$context['sub_action']]); |
||
| 92 | } |
||
| 93 | |||
| 94 | /** |
||
| 95 | * Test install a package. |
||
| 96 | */ |
||
| 97 | function PackageInstallTest() |
||
| 98 | { |
||
| 99 | global $boarddir, $txt, $context, $scripturl, $sourcedir, $packagesdir, $modSettings, $smcFunc, $settings; |
||
| 100 | |||
| 101 | // You have to specify a file!! |
||
| 102 | if (!isset($_REQUEST['package']) || $_REQUEST['package'] == '') |
||
| 103 | redirectexit('action=admin;area=packages'); |
||
| 104 | $context['filename'] = preg_replace('~[\.]+~', '.', $_REQUEST['package']); |
||
| 105 | |||
| 106 | // Do we have an existing id, for uninstalls and the like. |
||
| 107 | $context['install_id'] = isset($_REQUEST['pid']) ? (int) $_REQUEST['pid'] : 0; |
||
| 108 | |||
| 109 | require_once($sourcedir . '/Subs-Package.php'); |
||
| 110 | |||
| 111 | // Load up the package FTP information? |
||
| 112 | create_chmod_control(); |
||
| 113 | |||
| 114 | // Make sure temp directory exists and is empty. |
||
| 115 | if (file_exists($packagesdir . '/temp')) |
||
| 116 | deltree($packagesdir . '/temp', false); |
||
| 117 | |||
| 118 | if (!mktree($packagesdir . '/temp', 0755)) |
||
| 119 | { |
||
| 120 | deltree($packagesdir . '/temp', false); |
||
| 121 | if (!mktree($packagesdir . '/temp', 0777)) |
||
| 122 | { |
||
| 123 | deltree($packagesdir . '/temp', false); |
||
| 124 | create_chmod_control(array($packagesdir . '/temp/delme.tmp'), array('destination_url' => $scripturl . '?action=admin;area=packages;sa=' . $_REQUEST['sa'] . ';package=' . $_REQUEST['package'], 'crash_on_error' => true)); |
||
| 125 | |||
| 126 | deltree($packagesdir . '/temp', false); |
||
| 127 | if (!mktree($packagesdir . '/temp', 0777)) |
||
| 128 | fatal_lang_error('package_cant_download', false); |
||
| 129 | } |
||
| 130 | } |
||
| 131 | |||
| 132 | $context['uninstalling'] = $_REQUEST['sa'] == 'uninstall'; |
||
| 133 | |||
| 134 | // Change our last link tree item for more information on this Packages area. |
||
| 135 | $context['linktree'][count($context['linktree']) - 1] = array( |
||
| 136 | 'url' => $scripturl . '?action=admin;area=packages;sa=browse', |
||
| 137 | 'name' => $context['uninstalling'] ? $txt['package_uninstall_actions'] : $txt['install_actions'] |
||
| 138 | ); |
||
| 139 | $context['page_title'] .= ' - ' . ($context['uninstalling'] ? $txt['package_uninstall_actions'] : $txt['install_actions']); |
||
| 140 | |||
| 141 | $context['sub_template'] = 'view_package'; |
||
| 142 | |||
| 143 | if (!file_exists($packagesdir . '/' . $context['filename'])) |
||
| 144 | { |
||
| 145 | deltree($packagesdir . '/temp'); |
||
| 146 | fatal_lang_error('package_no_file', false); |
||
| 147 | } |
||
| 148 | |||
| 149 | // Extract the files so we can get things like the readme, etc. |
||
| 150 | View Code Duplication | if (is_file($packagesdir . '/' . $context['filename'])) |
|
| 151 | { |
||
| 152 | $context['extracted_files'] = read_tgz_file($packagesdir . '/' . $context['filename'], $packagesdir . '/temp'); |
||
| 153 | |||
| 154 | if ($context['extracted_files'] && !file_exists($packagesdir . '/temp/package-info.xml')) |
||
| 155 | foreach ($context['extracted_files'] as $file) |
||
| 156 | if (basename($file['filename']) == 'package-info.xml') |
||
| 157 | { |
||
| 158 | $context['base_path'] = dirname($file['filename']) . '/'; |
||
| 159 | break; |
||
| 160 | } |
||
| 161 | |||
| 162 | if (!isset($context['base_path'])) |
||
| 163 | $context['base_path'] = ''; |
||
| 164 | } |
||
| 165 | elseif (is_dir($packagesdir . '/' . $context['filename'])) |
||
| 166 | { |
||
| 167 | copytree($packagesdir . '/' . $context['filename'], $packagesdir . '/temp'); |
||
| 168 | $context['extracted_files'] = listtree($packagesdir . '/temp'); |
||
| 169 | $context['base_path'] = ''; |
||
| 170 | } |
||
| 171 | else |
||
| 172 | fatal_lang_error('no_access', false); |
||
| 173 | |||
| 174 | // Load up any custom themes we may want to install into... |
||
| 175 | $request = $smcFunc['db_query']('', ' |
||
| 176 | SELECT id_theme, variable, value |
||
| 177 | FROM {db_prefix}themes |
||
| 178 | WHERE (id_theme = {int:default_theme} OR id_theme IN ({array_int:known_theme_list})) |
||
| 179 | AND variable IN ({string:name}, {string:theme_dir})', |
||
| 180 | array( |
||
| 181 | 'known_theme_list' => explode(',', $modSettings['knownThemes']), |
||
| 182 | 'default_theme' => 1, |
||
| 183 | 'name' => 'name', |
||
| 184 | 'theme_dir' => 'theme_dir', |
||
| 185 | ) |
||
| 186 | ); |
||
| 187 | $theme_paths = array(); |
||
| 188 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 189 | $theme_paths[$row['id_theme']][$row['variable']] = $row['value']; |
||
| 190 | $smcFunc['db_free_result']($request); |
||
| 191 | |||
| 192 | // Get the package info... |
||
| 193 | $packageInfo = getPackageInfo($context['filename']); |
||
| 194 | |||
| 195 | if (!is_array($packageInfo)) |
||
| 196 | fatal_lang_error($packageInfo); |
||
| 197 | |||
| 198 | $packageInfo['filename'] = $context['filename']; |
||
| 199 | $context['package_name'] = isset($packageInfo['name']) ? $packageInfo['name'] : $context['filename']; |
||
| 200 | |||
| 201 | // Set the type of extraction... |
||
| 202 | $context['extract_type'] = isset($packageInfo['type']) ? $packageInfo['type'] : 'modification'; |
||
| 203 | |||
| 204 | // The mod isn't installed.... unless proven otherwise. |
||
| 205 | $context['is_installed'] = false; |
||
| 206 | |||
| 207 | // See if it is installed? |
||
| 208 | $request = $smcFunc['db_query']('', ' |
||
| 209 | SELECT version, themes_installed, db_changes |
||
| 210 | FROM {db_prefix}log_packages |
||
| 211 | WHERE package_id = {string:current_package} |
||
| 212 | AND install_state != {int:not_installed} |
||
| 213 | ORDER BY time_installed DESC |
||
| 214 | LIMIT 1', |
||
| 215 | array( |
||
| 216 | 'not_installed' => 0, |
||
| 217 | 'current_package' => $packageInfo['id'], |
||
| 218 | ) |
||
| 219 | ); |
||
| 220 | |||
| 221 | View Code Duplication | while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
| 222 | { |
||
| 223 | $old_themes = explode(',', $row['themes_installed']); |
||
| 224 | $old_version = $row['version']; |
||
| 225 | $db_changes = empty($row['db_changes']) ? array() : $smcFunc['json_decode']($row['db_changes'], true); |
||
| 226 | } |
||
| 227 | $smcFunc['db_free_result']($request); |
||
| 228 | |||
| 229 | $context['database_changes'] = array(); |
||
| 230 | if (isset($packageInfo['uninstall']['database'])) |
||
| 231 | $context['database_changes'][] = $txt['execute_database_changes'] . ' - ' . $packageInfo['uninstall']['database']; |
||
| 232 | elseif (!empty($db_changes)) |
||
| 233 | { |
||
| 234 | foreach ($db_changes as $change) |
||
| 235 | { |
||
| 236 | if (isset($change[2]) && isset($txt['package_db_' . $change[0]])) |
||
| 237 | $context['database_changes'][] = sprintf($txt['package_db_' . $change[0]], $change[1], $change[2]); |
||
| 238 | elseif (isset($txt['package_db_' . $change[0]])) |
||
| 239 | $context['database_changes'][] = sprintf($txt['package_db_' . $change[0]], $change[1]); |
||
| 240 | else |
||
| 241 | $context['database_changes'][] = $change[0] . '-' . $change[1] . (isset($change[2]) ? '-' . $change[2] : ''); |
||
| 242 | } |
||
| 243 | } |
||
| 244 | |||
| 245 | // Uninstalling? |
||
| 246 | if ($context['uninstalling']) |
||
| 247 | { |
||
| 248 | // Wait, it's not installed yet! |
||
| 249 | if (!isset($old_version) && $context['uninstalling']) |
||
| 250 | { |
||
| 251 | deltree($packagesdir . '/temp'); |
||
| 252 | fatal_lang_error('package_cant_uninstall', false); |
||
| 253 | } |
||
| 254 | |||
| 255 | $actions = parsePackageInfo($packageInfo['xml'], true, 'uninstall'); |
||
| 256 | |||
| 257 | // Gadzooks! There's no uninstaller at all!? |
||
| 258 | if (empty($actions)) |
||
| 259 | { |
||
| 260 | deltree($packagesdir . '/temp'); |
||
| 261 | fatal_lang_error('package_uninstall_cannot', false); |
||
| 262 | } |
||
| 263 | |||
| 264 | // Can't edit the custom themes it's edited if you're uninstalling, they must be removed. |
||
| 265 | $context['themes_locked'] = true; |
||
| 266 | |||
| 267 | // Only let them uninstall themes it was installed into. |
||
| 268 | foreach ($theme_paths as $id => $data) |
||
| 269 | if ($id != 1 && !in_array($id, $old_themes)) |
||
|
0 ignored issues
–
show
|
|||
| 270 | unset($theme_paths[$id]); |
||
| 271 | } |
||
| 272 | View Code Duplication | elseif (isset($old_version) && $old_version != $packageInfo['version']) |
|
| 273 | { |
||
| 274 | // Look for an upgrade... |
||
| 275 | $actions = parsePackageInfo($packageInfo['xml'], true, 'upgrade', $old_version); |
||
| 276 | |||
| 277 | // There was no upgrade.... |
||
| 278 | if (empty($actions)) |
||
| 279 | $context['is_installed'] = true; |
||
| 280 | else |
||
| 281 | { |
||
| 282 | // Otherwise they can only upgrade themes from the first time around. |
||
| 283 | foreach ($theme_paths as $id => $data) |
||
| 284 | if ($id != 1 && !in_array($id, $old_themes)) |
||
| 285 | unset($theme_paths[$id]); |
||
| 286 | } |
||
| 287 | } |
||
| 288 | elseif (isset($old_version) && $old_version == $packageInfo['version']) |
||
| 289 | $context['is_installed'] = true; |
||
| 290 | |||
| 291 | View Code Duplication | if (!isset($old_version) || $context['is_installed']) |
|
| 292 | $actions = parsePackageInfo($packageInfo['xml'], true, 'install'); |
||
| 293 | |||
| 294 | $context['actions'] = array(); |
||
| 295 | $context['ftp_needed'] = false; |
||
| 296 | $context['has_failure'] = false; |
||
| 297 | $chmod_files = array(); |
||
| 298 | |||
| 299 | // no actions found, return so we can display an error |
||
| 300 | if (empty($actions)) |
||
| 301 | return; |
||
| 302 | |||
| 303 | // This will hold data about anything that can be installed in other themes. |
||
| 304 | $themeFinds = array( |
||
| 305 | 'candidates' => array(), |
||
| 306 | 'other_themes' => array(), |
||
| 307 | ); |
||
| 308 | |||
| 309 | // Now prepare things for the template. |
||
| 310 | foreach ($actions as $action) |
||
| 311 | { |
||
| 312 | // Not failed until proven otherwise. |
||
| 313 | $failed = false; |
||
| 314 | $thisAction = array(); |
||
| 315 | |||
| 316 | if ($action['type'] == 'chmod') |
||
| 317 | { |
||
| 318 | $chmod_files[] = $action['filename']; |
||
| 319 | continue; |
||
| 320 | } |
||
| 321 | elseif ($action['type'] == 'readme' || $action['type'] == 'license') |
||
| 322 | { |
||
| 323 | $type = 'package_' . $action['type']; |
||
| 324 | View Code Duplication | if (file_exists($packagesdir . '/temp/' . $context['base_path'] . $action['filename'])) |
|
| 325 | $context[$type] = $smcFunc['htmlspecialchars'](trim(file_get_contents($packagesdir . '/temp/' . $context['base_path'] . $action['filename']), "\n\r")); |
||
| 326 | elseif (file_exists($action['filename'])) |
||
| 327 | $context[$type] = $smcFunc['htmlspecialchars'](trim(file_get_contents($action['filename']), "\n\r")); |
||
| 328 | |||
| 329 | if (!empty($action['parse_bbc'])) |
||
| 330 | { |
||
| 331 | require_once($sourcedir . '/Subs-Post.php'); |
||
| 332 | $context[$type] = preg_replace('~\[[/]?html\]~i', '', $context[$type]); |
||
| 333 | preparsecode($context[$type]); |
||
| 334 | $context[$type] = parse_bbc($context[$type]); |
||
| 335 | } |
||
| 336 | else |
||
| 337 | $context[$type] = nl2br($context[$type]); |
||
| 338 | |||
| 339 | continue; |
||
| 340 | } |
||
| 341 | // Don't show redirects. |
||
| 342 | elseif ($action['type'] == 'redirect') |
||
| 343 | continue; |
||
| 344 | elseif ($action['type'] == 'error') |
||
| 345 | { |
||
| 346 | $context['has_failure'] = true; |
||
| 347 | if (isset($action['error_msg']) && isset($action['error_var'])) |
||
| 348 | $context['failure_details'] = sprintf($txt['package_will_fail_' . $action['error_msg']], $action['error_var']); |
||
| 349 | elseif (isset($action['error_msg'])) |
||
| 350 | $context['failure_details'] = isset($txt['package_will_fail_' . $action['error_msg']]) ? $txt['package_will_fail_' . $action['error_msg']] : $action['error_msg']; |
||
| 351 | } |
||
| 352 | elseif ($action['type'] == 'modification') |
||
| 353 | { |
||
| 354 | if (!file_exists($packagesdir . '/temp/' . $context['base_path'] . $action['filename'])) |
||
| 355 | { |
||
| 356 | $context['has_failure'] = true; |
||
| 357 | |||
| 358 | $context['actions'][] = array( |
||
| 359 | 'type' => $txt['execute_modification'], |
||
| 360 | 'action' => $smcFunc['htmlspecialchars'](strtr($action['filename'], array($boarddir => '.'))), |
||
| 361 | 'description' => $txt['package_action_missing'], |
||
| 362 | 'failed' => true, |
||
| 363 | ); |
||
| 364 | } |
||
| 365 | else |
||
| 366 | { |
||
| 367 | |||
| 368 | View Code Duplication | if ($action['boardmod']) |
|
| 369 | $mod_actions = parseBoardMod(@file_get_contents($packagesdir . '/temp/' . $context['base_path'] . $action['filename']), true, $action['reverse'], $theme_paths); |
||
| 370 | else |
||
| 371 | $mod_actions = parseModification(@file_get_contents($packagesdir . '/temp/' . $context['base_path'] . $action['filename']), true, $action['reverse'], $theme_paths); |
||
| 372 | |||
| 373 | if (count($mod_actions) == 1 && isset($mod_actions[0]) && $mod_actions[0]['type'] == 'error' && $mod_actions[0]['filename'] == '-') |
||
| 374 | $mod_actions[0]['filename'] = $action['filename']; |
||
| 375 | |||
| 376 | foreach ($mod_actions as $key => $mod_action) |
||
| 377 | { |
||
| 378 | // Lets get the last section of the file name. |
||
| 379 | View Code Duplication | if (isset($mod_action['filename']) && substr($mod_action['filename'], -13) != '.template.php') |
|
| 380 | $actual_filename = strtolower(substr(strrchr($mod_action['filename'], '/'), 1) . '||' . $action['filename']); |
||
| 381 | elseif (isset($mod_action['filename']) && preg_match('~([\w]*)/([\w]*)\.template\.php$~', $mod_action['filename'], $matches)) |
||
| 382 | $actual_filename = strtolower($matches[1] . '/' . $matches[2] . '.template.php' . '||' . $action['filename']); |
||
| 383 | else |
||
| 384 | $actual_filename = $key; |
||
| 385 | |||
| 386 | if ($mod_action['type'] == 'opened') |
||
| 387 | $failed = false; |
||
| 388 | elseif ($mod_action['type'] == 'failure') |
||
| 389 | { |
||
| 390 | if (empty($mod_action['is_custom'])) |
||
| 391 | $context['has_failure'] = true; |
||
| 392 | $failed = true; |
||
| 393 | } |
||
| 394 | elseif ($mod_action['type'] == 'chmod') |
||
| 395 | { |
||
| 396 | $chmod_files[] = $mod_action['filename']; |
||
| 397 | } |
||
| 398 | elseif ($mod_action['type'] == 'saved') |
||
| 399 | { |
||
| 400 | if (!empty($mod_action['is_custom'])) |
||
| 401 | { |
||
| 402 | if (!isset($context['theme_actions'][$mod_action['is_custom']])) |
||
| 403 | $context['theme_actions'][$mod_action['is_custom']] = array( |
||
| 404 | 'name' => $theme_paths[$mod_action['is_custom']]['name'], |
||
| 405 | 'actions' => array(), |
||
| 406 | 'has_failure' => $failed, |
||
| 407 | ); |
||
| 408 | else |
||
| 409 | $context['theme_actions'][$mod_action['is_custom']]['has_failure'] |= $failed; |
||
| 410 | |||
| 411 | $context['theme_actions'][$mod_action['is_custom']]['actions'][$actual_filename] = array( |
||
| 412 | 'type' => $txt['execute_modification'], |
||
| 413 | 'action' => $smcFunc['htmlspecialchars'](strtr($mod_action['filename'], array($boarddir => '.'))), |
||
| 414 | 'description' => $failed ? $txt['package_action_failure'] : $txt['package_action_success'], |
||
| 415 | 'failed' => $failed, |
||
| 416 | ); |
||
| 417 | } |
||
| 418 | elseif (!isset($context['actions'][$actual_filename])) |
||
| 419 | { |
||
| 420 | $context['actions'][$actual_filename] = array( |
||
| 421 | 'type' => $txt['execute_modification'], |
||
| 422 | 'action' => $smcFunc['htmlspecialchars'](strtr($mod_action['filename'], array($boarddir => '.'))), |
||
| 423 | 'description' => $failed ? $txt['package_action_failure'] : $txt['package_action_success'], |
||
| 424 | 'failed' => $failed, |
||
| 425 | ); |
||
| 426 | } |
||
| 427 | else |
||
| 428 | { |
||
| 429 | $context['actions'][$actual_filename]['failed'] |= $failed; |
||
| 430 | $context['actions'][$actual_filename]['description'] = $context['actions'][$actual_filename]['failed'] ? $txt['package_action_failure'] : $txt['package_action_success']; |
||
| 431 | } |
||
| 432 | } |
||
| 433 | View Code Duplication | elseif ($mod_action['type'] == 'skipping') |
|
| 434 | { |
||
| 435 | $context['actions'][$actual_filename] = array( |
||
| 436 | 'type' => $txt['execute_modification'], |
||
| 437 | 'action' => $smcFunc['htmlspecialchars'](strtr($mod_action['filename'], array($boarddir => '.'))), |
||
| 438 | 'description' => $txt['package_action_skipping'] |
||
| 439 | ); |
||
| 440 | } |
||
| 441 | elseif ($mod_action['type'] == 'missing' && empty($mod_action['is_custom'])) |
||
| 442 | { |
||
| 443 | $context['has_failure'] = true; |
||
| 444 | $context['actions'][$actual_filename] = array( |
||
| 445 | 'type' => $txt['execute_modification'], |
||
| 446 | 'action' => $smcFunc['htmlspecialchars'](strtr($mod_action['filename'], array($boarddir => '.'))), |
||
| 447 | 'description' => $txt['package_action_missing'], |
||
| 448 | 'failed' => true, |
||
| 449 | ); |
||
| 450 | } |
||
| 451 | View Code Duplication | elseif ($mod_action['type'] == 'error') |
|
| 452 | $context['actions'][$actual_filename] = array( |
||
| 453 | 'type' => $txt['execute_modification'], |
||
| 454 | 'action' => $smcFunc['htmlspecialchars'](strtr($mod_action['filename'], array($boarddir => '.'))), |
||
| 455 | 'description' => $txt['package_action_error'], |
||
| 456 | 'failed' => true, |
||
| 457 | ); |
||
| 458 | } |
||
| 459 | |||
| 460 | // We need to loop again just to get the operations down correctly. |
||
| 461 | foreach ($mod_actions as $operation_key => $mod_action) |
||
| 462 | { |
||
| 463 | // Lets get the last section of the file name. |
||
| 464 | View Code Duplication | if (isset($mod_action['filename']) && substr($mod_action['filename'], -13) != '.template.php') |
|
| 465 | $actual_filename = strtolower(substr(strrchr($mod_action['filename'], '/'), 1) . '||' . $action['filename']); |
||
| 466 | elseif (isset($mod_action['filename']) && preg_match('~([\w]*)/([\w]*)\.template\.php$~', $mod_action['filename'], $matches)) |
||
| 467 | $actual_filename = strtolower($matches[1] . '/' . $matches[2] . '.template.php' . '||' . $action['filename']); |
||
| 468 | else |
||
| 469 | $actual_filename = $key; |
||
|
0 ignored issues
–
show
The variable
$key seems to be defined by a foreach iteration on line 376. Are you sure the iterator is never empty, otherwise this variable is not defined?
It seems like you are relying on a variable being defined by an iteration: foreach ($a as $b) {
}
// $b is defined here only if $a has elements, for example if $a is array()
// then $b would not be defined here. To avoid that, we recommend to set a
// default value for $b.
// Better
$b = 0; // or whatever default makes sense in your context
foreach ($a as $b) {
}
// $b is now guaranteed to be defined here.
Loading history...
|
|||
| 470 | |||
| 471 | // We just need it for actual parse changes. |
||
| 472 | if (!in_array($mod_action['type'], array('error', 'result', 'opened', 'saved', 'end', 'missing', 'skipping', 'chmod'))) |
||
| 473 | { |
||
| 474 | if (empty($mod_action['is_custom'])) |
||
| 475 | $context['actions'][$actual_filename]['operations'][] = array( |
||
| 476 | 'type' => $txt['execute_modification'], |
||
| 477 | 'action' => $smcFunc['htmlspecialchars'](strtr($mod_action['filename'], array($boarddir => '.'))), |
||
| 478 | 'description' => $mod_action['failed'] ? $txt['package_action_failure'] : $txt['package_action_success'], |
||
| 479 | 'position' => $mod_action['position'], |
||
| 480 | 'operation_key' => $operation_key, |
||
| 481 | 'filename' => $action['filename'], |
||
| 482 | 'is_boardmod' => $action['boardmod'], |
||
| 483 | 'failed' => $mod_action['failed'], |
||
| 484 | 'ignore_failure' => !empty($mod_action['ignore_failure']), |
||
| 485 | ); |
||
| 486 | |||
| 487 | // Themes are under the saved type. |
||
| 488 | if (isset($mod_action['is_custom']) && isset($context['theme_actions'][$mod_action['is_custom']])) |
||
| 489 | $context['theme_actions'][$mod_action['is_custom']]['actions'][$actual_filename]['operations'][] = array( |
||
| 490 | 'type' => $txt['execute_modification'], |
||
| 491 | 'action' => $smcFunc['htmlspecialchars'](strtr($mod_action['filename'], array($boarddir => '.'))), |
||
| 492 | 'description' => $mod_action['failed'] ? $txt['package_action_failure'] : $txt['package_action_success'], |
||
| 493 | 'position' => $mod_action['position'], |
||
| 494 | 'operation_key' => $operation_key, |
||
| 495 | 'filename' => $action['filename'], |
||
| 496 | 'is_boardmod' => $action['boardmod'], |
||
| 497 | 'failed' => $mod_action['failed'], |
||
| 498 | 'ignore_failure' => !empty($mod_action['ignore_failure']), |
||
| 499 | ); |
||
| 500 | } |
||
| 501 | } |
||
| 502 | } |
||
| 503 | } |
||
| 504 | View Code Duplication | elseif ($action['type'] == 'code') |
|
| 505 | { |
||
| 506 | $thisAction = array( |
||
| 507 | 'type' => $txt['execute_code'], |
||
| 508 | 'action' => $smcFunc['htmlspecialchars']($action['filename']), |
||
| 509 | ); |
||
| 510 | } |
||
| 511 | View Code Duplication | elseif ($action['type'] == 'database') |
|
| 512 | { |
||
| 513 | $thisAction = array( |
||
| 514 | 'type' => $txt['execute_database_changes'], |
||
| 515 | 'action' => $smcFunc['htmlspecialchars']($action['filename']), |
||
| 516 | ); |
||
| 517 | } |
||
| 518 | elseif (in_array($action['type'], array('create-dir', 'create-file'))) |
||
| 519 | { |
||
| 520 | $thisAction = array( |
||
| 521 | 'type' => $txt['package_create'] . ' ' . ($action['type'] == 'create-dir' ? $txt['package_tree'] : $txt['package_file']), |
||
| 522 | 'action' => $smcFunc['htmlspecialchars'](strtr($action['destination'], array($boarddir => '.'))) |
||
| 523 | ); |
||
| 524 | } |
||
| 525 | elseif ($action['type'] == 'hook') |
||
| 526 | { |
||
| 527 | $action['description'] = !isset($action['hook'], $action['function']) ? $txt['package_action_failure'] : $txt['package_action_success']; |
||
| 528 | |||
| 529 | if (!isset($action['hook'], $action['function'])) |
||
| 530 | $context['has_failure'] = true; |
||
| 531 | |||
| 532 | $thisAction = array( |
||
| 533 | 'type' => $action['reverse'] ? $txt['execute_hook_remove'] : $txt['execute_hook_add'], |
||
| 534 | 'action' => sprintf($txt['execute_hook_action' . ($action['reverse'] ? '_inverse' : '')], $smcFunc['htmlspecialchars']($action['hook'])), |
||
| 535 | ); |
||
| 536 | } |
||
| 537 | elseif ($action['type'] == 'credits') |
||
| 538 | { |
||
| 539 | $thisAction = array( |
||
| 540 | 'type' => $txt['execute_credits_add'], |
||
| 541 | 'action' => sprintf($txt['execute_credits_action'], $smcFunc['htmlspecialchars']($action['title'])), |
||
| 542 | ); |
||
| 543 | } |
||
| 544 | elseif ($action['type'] == 'requires') |
||
| 545 | { |
||
| 546 | $installed = false; |
||
| 547 | $version = true; |
||
| 548 | |||
| 549 | // package missing required values? |
||
| 550 | if (!isset($action['id'])) |
||
| 551 | $context['has_failure'] = true; |
||
| 552 | else |
||
| 553 | { |
||
| 554 | // See if this dependancy is installed |
||
| 555 | $request = $smcFunc['db_query']('', ' |
||
| 556 | SELECT version |
||
| 557 | FROM {db_prefix}log_packages |
||
| 558 | WHERE package_id = {string:current_package} |
||
| 559 | AND install_state != {int:not_installed} |
||
| 560 | ORDER BY time_installed DESC |
||
| 561 | LIMIT 1', |
||
| 562 | array( |
||
| 563 | 'not_installed' => 0, |
||
| 564 | 'current_package' => $action['id'], |
||
| 565 | ) |
||
| 566 | ); |
||
| 567 | $installed = ($smcFunc['db_num_rows']($request) !== 0); |
||
| 568 | if ($installed) |
||
| 569 | list ($version) = $smcFunc['db_fetch_row']($request); |
||
| 570 | $smcFunc['db_free_result']($request); |
||
| 571 | |||
| 572 | // do a version level check (if requested) in the most basic way |
||
| 573 | $version = (isset($action['version']) ? $version == $action['version'] : true); |
||
| 574 | } |
||
| 575 | |||
| 576 | // Set success or failure information |
||
| 577 | $action['description'] = ($installed && $version) ? $txt['package_action_success'] : $txt['package_action_failure']; |
||
| 578 | $context['has_failure'] = !($installed && $version); |
||
| 579 | |||
| 580 | $thisAction = array( |
||
| 581 | 'type' => $txt['package_requires'], |
||
| 582 | 'action' => $txt['package_check_for'] . ' ' . $action['id'] . (isset($action['version']) ? (' / ' . ($version ? $action['version'] : '<span class="error">' . $action['version'] . '</span>')) : ''), |
||
| 583 | ); |
||
| 584 | } |
||
| 585 | elseif (in_array($action['type'], array('require-dir', 'require-file'))) |
||
| 586 | { |
||
| 587 | // Do this one... |
||
| 588 | $thisAction = array( |
||
| 589 | 'type' => $txt['package_extract'] . ' ' . ($action['type'] == 'require-dir' ? $txt['package_tree'] : $txt['package_file']), |
||
| 590 | 'action' => $smcFunc['htmlspecialchars'](strtr($action['destination'], array($boarddir => '.'))) |
||
| 591 | ); |
||
| 592 | |||
| 593 | // Could this be theme related? |
||
| 594 | if (!empty($action['unparsed_destination']) && preg_match('~^\$(languagedir|languages_dir|imagesdir|themedir|themes_dir)~i', $action['unparsed_destination'], $matches)) |
||
| 595 | { |
||
| 596 | // Is the action already stated? |
||
| 597 | $theme_action = !empty($action['theme_action']) && in_array($action['theme_action'], array('no', 'yes', 'auto')) ? $action['theme_action'] : 'auto'; |
||
| 598 | // If it's not auto do we think we have something we can act upon? |
||
| 599 | View Code Duplication | if ($theme_action != 'auto' && !in_array($matches[1], array('languagedir', 'languages_dir', 'imagesdir', 'themedir'))) |
|
| 600 | $theme_action = ''; |
||
| 601 | // ... or if it's auto do we even want to do anything? |
||
| 602 | elseif ($theme_action == 'auto' && $matches[1] != 'imagesdir') |
||
| 603 | $theme_action = ''; |
||
| 604 | |||
| 605 | // So, we still want to do something? |
||
| 606 | View Code Duplication | if ($theme_action != '') |
|
| 607 | $themeFinds['candidates'][] = $action; |
||
| 608 | // Otherwise is this is going into another theme record it. |
||
| 609 | elseif ($matches[1] == 'themes_dir') |
||
| 610 | $themeFinds['other_themes'][] = strtolower(strtr(parse_path($action['unparsed_destination']), array('\\' => '/')) . '/' . basename($action['filename'])); |
||
| 611 | } |
||
| 612 | } |
||
| 613 | elseif (in_array($action['type'], array('move-dir', 'move-file'))) |
||
| 614 | $thisAction = array( |
||
| 615 | 'type' => $txt['package_move'] . ' ' . ($action['type'] == 'move-dir' ? $txt['package_tree'] : $txt['package_file']), |
||
| 616 | 'action' => $smcFunc['htmlspecialchars'](strtr($action['source'], array($boarddir => '.'))) . ' => ' . $smcFunc['htmlspecialchars'](strtr($action['destination'], array($boarddir => '.'))) |
||
| 617 | ); |
||
| 618 | elseif (in_array($action['type'], array('remove-dir', 'remove-file'))) |
||
| 619 | { |
||
| 620 | $thisAction = array( |
||
| 621 | 'type' => $txt['package_delete'] . ' ' . ($action['type'] == 'remove-dir' ? $txt['package_tree'] : $txt['package_file']), |
||
| 622 | 'action' => $smcFunc['htmlspecialchars'](strtr($action['filename'], array($boarddir => '.'))) |
||
| 623 | ); |
||
| 624 | |||
| 625 | // Could this be theme related? |
||
| 626 | if (!empty($action['unparsed_filename']) && preg_match('~^\$(languagedir|languages_dir|imagesdir|themedir|themes_dir)~i', $action['unparsed_filename'], $matches)) |
||
| 627 | { |
||
| 628 | |||
| 629 | // Is the action already stated? |
||
| 630 | $theme_action = !empty($action['theme_action']) && in_array($action['theme_action'], array('no', 'yes', 'auto')) ? $action['theme_action'] : 'auto'; |
||
| 631 | $action['unparsed_destination'] = $action['unparsed_filename']; |
||
| 632 | |||
| 633 | // If it's not auto do we think we have something we can act upon? |
||
| 634 | View Code Duplication | if ($theme_action != 'auto' && !in_array($matches[1], array('languagedir', 'languages_dir', 'imagesdir', 'themedir'))) |
|
| 635 | $theme_action = ''; |
||
| 636 | // ... or if it's auto do we even want to do anything? |
||
| 637 | elseif ($theme_action == 'auto' && $matches[1] != 'imagesdir') |
||
| 638 | $theme_action = ''; |
||
| 639 | |||
| 640 | // So, we still want to do something? |
||
| 641 | View Code Duplication | if ($theme_action != '') |
|
| 642 | $themeFinds['candidates'][] = $action; |
||
| 643 | // Otherwise is this is going into another theme record it. |
||
| 644 | elseif ($matches[1] == 'themes_dir') |
||
| 645 | $themeFinds['other_themes'][] = strtolower(strtr(parse_path($action['unparsed_filename']), array('\\' => '/')) . '/' . basename($action['filename'])); |
||
| 646 | } |
||
| 647 | } |
||
| 648 | |||
| 649 | if (empty($thisAction)) |
||
| 650 | continue; |
||
| 651 | |||
| 652 | if (!in_array($action['type'], array('hook', 'credits'))) |
||
| 653 | { |
||
| 654 | if ($context['uninstalling']) |
||
| 655 | $file = in_array($action['type'], array('remove-dir', 'remove-file')) ? $action['filename'] : $packagesdir . '/temp/' . $context['base_path'] . $action['filename']; |
||
| 656 | else |
||
| 657 | $file = $packagesdir . '/temp/' . $context['base_path'] . $action['filename']; |
||
| 658 | } |
||
| 659 | |||
| 660 | // Don't fail if a file/directory we're trying to create doesn't exist... |
||
| 661 | if (isset($action['filename']) && !file_exists($file) && !in_array($action['type'], array('create-dir', 'create-file'))) |
||
|
0 ignored issues
–
show
The variable
$file 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...
|
|||
| 662 | { |
||
| 663 | $context['has_failure'] = true; |
||
| 664 | |||
| 665 | $thisAction += array( |
||
| 666 | 'description' => $txt['package_action_missing'], |
||
| 667 | 'failed' => true, |
||
| 668 | ); |
||
| 669 | } |
||
| 670 | |||
| 671 | // @todo None given? |
||
| 672 | View Code Duplication | if (empty($thisAction['description'])) |
|
| 673 | $thisAction['description'] = isset($action['description']) ? $action['description'] : ''; |
||
| 674 | |||
| 675 | $context['actions'][] = $thisAction; |
||
| 676 | } |
||
| 677 | |||
| 678 | // Have we got some things which we might want to do "multi-theme"? |
||
| 679 | if (!empty($themeFinds['candidates'])) |
||
| 680 | { |
||
| 681 | foreach ($themeFinds['candidates'] as $action_data) |
||
| 682 | { |
||
| 683 | // Get the part of the file we'll be dealing with. |
||
| 684 | preg_match('~^\$(languagedir|languages_dir|imagesdir|themedir)(\\|/)*(.+)*~i', $action_data['unparsed_destination'], $matches); |
||
| 685 | |||
| 686 | if ($matches[1] == 'imagesdir') |
||
| 687 | $path = '/' . basename($settings['default_images_url']); |
||
| 688 | elseif ($matches[1] == 'languagedir' || $matches[1] == 'languages_dir') |
||
| 689 | $path = '/languages'; |
||
| 690 | else |
||
| 691 | $path = ''; |
||
| 692 | |||
| 693 | if (!empty($matches[3])) |
||
| 694 | $path .= $matches[3]; |
||
| 695 | |||
| 696 | if (!$context['uninstalling']) |
||
| 697 | $path .= '/' . basename($action_data['filename']); |
||
| 698 | |||
| 699 | // Loop through each custom theme to note it's candidacy! |
||
| 700 | foreach ($theme_paths as $id => $theme_data) |
||
| 701 | { |
||
| 702 | if (isset($theme_data['theme_dir']) && $id != 1) |
||
| 703 | { |
||
| 704 | $real_path = $theme_data['theme_dir'] . $path; |
||
| 705 | |||
| 706 | // Confirm that we don't already have this dealt with by another entry. |
||
| 707 | if (!in_array(strtolower(strtr($real_path, array('\\' => '/'))), $themeFinds['other_themes'])) |
||
| 708 | { |
||
| 709 | // Check if we will need to chmod this. |
||
| 710 | if (!mktree(dirname($real_path), false)) |
||
| 711 | { |
||
| 712 | $temp = dirname($real_path); |
||
| 713 | while (!file_exists($temp) && strlen($temp) > 1) |
||
| 714 | $temp = dirname($temp); |
||
| 715 | $chmod_files[] = $temp; |
||
| 716 | } |
||
| 717 | |||
| 718 | if ($action_data['type'] == 'require-dir' && !is_writable($real_path) && (file_exists($real_path) || !is_writable(dirname($real_path)))) |
||
| 719 | $chmod_files[] = $real_path; |
||
| 720 | |||
| 721 | if (!isset($context['theme_actions'][$id])) |
||
| 722 | $context['theme_actions'][$id] = array( |
||
| 723 | 'name' => $theme_data['name'], |
||
| 724 | 'actions' => array(), |
||
| 725 | ); |
||
| 726 | |||
| 727 | if ($context['uninstalling']) |
||
| 728 | $context['theme_actions'][$id]['actions'][] = array( |
||
| 729 | 'type' => $txt['package_delete'] . ' ' . ($action_data['type'] == 'require-dir' ? $txt['package_tree'] : $txt['package_file']), |
||
| 730 | 'action' => strtr($real_path, array('\\' => '/', $boarddir => '.')), |
||
| 731 | 'description' => '', |
||
| 732 | 'value' => base64_encode($smcFunc['json_encode'](array('type' => $action_data['type'], 'orig' => $action_data['filename'], 'future' => $real_path, 'id' => $id))), |
||
| 733 | 'not_mod' => true, |
||
| 734 | ); |
||
| 735 | else |
||
| 736 | $context['theme_actions'][$id]['actions'][] = array( |
||
| 737 | 'type' => $txt['package_extract'] . ' ' . ($action_data['type'] == 'require-dir' ? $txt['package_tree'] : $txt['package_file']), |
||
| 738 | 'action' => strtr($real_path, array('\\' => '/', $boarddir => '.')), |
||
| 739 | 'description' => '', |
||
| 740 | 'value' => base64_encode($smcFunc['json_encode'](array('type' => $action_data['type'], 'orig' => $action_data['destination'], 'future' => $real_path, 'id' => $id))), |
||
| 741 | 'not_mod' => true, |
||
| 742 | ); |
||
| 743 | } |
||
| 744 | } |
||
| 745 | } |
||
| 746 | } |
||
| 747 | } |
||
| 748 | |||
| 749 | // Trash the cache... which will also check permissions for us! |
||
| 750 | package_flush_cache(true); |
||
| 751 | |||
| 752 | if (file_exists($packagesdir . '/temp')) |
||
| 753 | deltree($packagesdir . '/temp'); |
||
| 754 | |||
| 755 | if (!empty($chmod_files)) |
||
| 756 | { |
||
| 757 | $ftp_status = create_chmod_control($chmod_files); |
||
| 758 | $context['ftp_needed'] = !empty($ftp_status['files']['notwritable']) && !empty($context['package_ftp']); |
||
| 759 | } |
||
| 760 | |||
| 761 | $context['post_url'] = $scripturl . '?action=admin;area=packages;sa=' . ($context['uninstalling'] ? 'uninstall' : 'install') . ($context['ftp_needed'] ? '' : '2') . ';package=' . $context['filename'] . ';pid=' . $context['install_id']; |
||
| 762 | checkSubmitOnce('register'); |
||
| 763 | } |
||
| 764 | |||
| 765 | /** |
||
| 766 | * Apply another type of (avatar, language, etc.) package. |
||
| 767 | */ |
||
| 768 | function PackageInstall() |
||
| 769 | { |
||
| 770 | global $txt, $context, $boardurl, $scripturl, $sourcedir, $packagesdir, $modSettings; |
||
| 771 | global $user_info, $smcFunc; |
||
| 772 | |||
| 773 | // Make sure we don't install this mod twice. |
||
| 774 | checkSubmitOnce('check'); |
||
| 775 | checkSession(); |
||
| 776 | |||
| 777 | // If there's no file, what are we installing? |
||
| 778 | if (!isset($_REQUEST['package']) || $_REQUEST['package'] == '') |
||
| 779 | redirectexit('action=admin;area=packages'); |
||
| 780 | $context['filename'] = $_REQUEST['package']; |
||
| 781 | |||
| 782 | // If this is an uninstall, we'll have an id. |
||
| 783 | $context['install_id'] = isset($_REQUEST['pid']) ? (int) $_REQUEST['pid'] : 0; |
||
| 784 | |||
| 785 | require_once($sourcedir . '/Subs-Package.php'); |
||
| 786 | |||
| 787 | // @todo Perhaps do it in steps, if necessary? |
||
| 788 | |||
| 789 | $context['uninstalling'] = $_REQUEST['sa'] == 'uninstall2'; |
||
| 790 | |||
| 791 | // Set up the linktree for other. |
||
| 792 | $context['linktree'][count($context['linktree']) - 1] = array( |
||
| 793 | 'url' => $scripturl . '?action=admin;area=packages;sa=browse', |
||
| 794 | 'name' => $context['uninstalling'] ? $txt['uninstall'] : $txt['extracting'] |
||
| 795 | ); |
||
| 796 | $context['page_title'] .= ' - ' . ($context['uninstalling'] ? $txt['uninstall'] : $txt['extracting']); |
||
| 797 | |||
| 798 | $context['sub_template'] = 'extract_package'; |
||
| 799 | |||
| 800 | if (!file_exists($packagesdir . '/' . $context['filename'])) |
||
| 801 | fatal_lang_error('package_no_file', false); |
||
| 802 | |||
| 803 | // Load up the package FTP information? |
||
| 804 | create_chmod_control(array(), array('destination_url' => $scripturl . '?action=admin;area=packages;sa=' . $_REQUEST['sa'] . ';package=' . $_REQUEST['package'])); |
||
| 805 | |||
| 806 | // Make sure temp directory exists and is empty! |
||
| 807 | if (file_exists($packagesdir . '/temp')) |
||
| 808 | deltree($packagesdir . '/temp', false); |
||
| 809 | else |
||
| 810 | mktree($packagesdir . '/temp', 0777); |
||
| 811 | |||
| 812 | // Let the unpacker do the work. |
||
| 813 | View Code Duplication | if (is_file($packagesdir . '/' . $context['filename'])) |
|
| 814 | { |
||
| 815 | $context['extracted_files'] = read_tgz_file($packagesdir . '/' . $context['filename'], $packagesdir . '/temp'); |
||
| 816 | |||
| 817 | if (!file_exists($packagesdir . '/temp/package-info.xml')) |
||
| 818 | foreach ($context['extracted_files'] as $file) |
||
| 819 | if (basename($file['filename']) == 'package-info.xml') |
||
| 820 | { |
||
| 821 | $context['base_path'] = dirname($file['filename']) . '/'; |
||
| 822 | break; |
||
| 823 | } |
||
| 824 | |||
| 825 | if (!isset($context['base_path'])) |
||
| 826 | $context['base_path'] = ''; |
||
| 827 | } |
||
| 828 | elseif (is_dir($packagesdir . '/' . $context['filename'])) |
||
| 829 | { |
||
| 830 | copytree($packagesdir . '/' . $context['filename'], $packagesdir . '/temp'); |
||
| 831 | $context['extracted_files'] = listtree($packagesdir . '/temp'); |
||
| 832 | $context['base_path'] = ''; |
||
| 833 | } |
||
| 834 | else |
||
| 835 | fatal_lang_error('no_access', false); |
||
| 836 | |||
| 837 | // Are we installing this into any custom themes? |
||
| 838 | $custom_themes = array(1); |
||
| 839 | $known_themes = explode(',', $modSettings['knownThemes']); |
||
| 840 | if (!empty($_POST['custom_theme'])) |
||
| 841 | { |
||
| 842 | foreach ($_POST['custom_theme'] as $tid) |
||
| 843 | if (in_array($tid, $known_themes)) |
||
| 844 | $custom_themes[] = (int) $tid; |
||
| 845 | } |
||
| 846 | |||
| 847 | // Now load up the paths of the themes that we need to know about. |
||
| 848 | $request = $smcFunc['db_query']('', ' |
||
| 849 | SELECT id_theme, variable, value |
||
| 850 | FROM {db_prefix}themes |
||
| 851 | WHERE id_theme IN ({array_int:custom_themes}) |
||
| 852 | AND variable IN ({string:name}, {string:theme_dir})', |
||
| 853 | array( |
||
| 854 | 'custom_themes' => $custom_themes, |
||
| 855 | 'name' => 'name', |
||
| 856 | 'theme_dir' => 'theme_dir', |
||
| 857 | ) |
||
| 858 | ); |
||
| 859 | $theme_paths = array(); |
||
| 860 | $themes_installed = array(1); |
||
| 861 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 862 | $theme_paths[$row['id_theme']][$row['variable']] = $row['value']; |
||
| 863 | $smcFunc['db_free_result']($request); |
||
| 864 | |||
| 865 | // Are there any theme copying that we want to take place? |
||
| 866 | $context['theme_copies'] = array( |
||
| 867 | 'require-file' => array(), |
||
| 868 | 'require-dir' => array(), |
||
| 869 | ); |
||
| 870 | if (!empty($_POST['theme_changes'])) |
||
| 871 | { |
||
| 872 | foreach ($_POST['theme_changes'] as $change) |
||
| 873 | { |
||
| 874 | if (empty($change)) |
||
| 875 | continue; |
||
| 876 | $theme_data = $smcFunc['json_decode'](base64_decode($change), true); |
||
| 877 | if (empty($theme_data['type'])) |
||
| 878 | continue; |
||
| 879 | |||
| 880 | $themes_installed[] = $theme_data['id']; |
||
| 881 | $context['theme_copies'][$theme_data['type']][$theme_data['orig']][] = $theme_data['future']; |
||
| 882 | } |
||
| 883 | } |
||
| 884 | |||
| 885 | // Get the package info... |
||
| 886 | $packageInfo = getPackageInfo($context['filename']); |
||
| 887 | if (!is_array($packageInfo)) |
||
| 888 | fatal_lang_error($packageInfo); |
||
| 889 | |||
| 890 | $packageInfo['filename'] = $context['filename']; |
||
| 891 | |||
| 892 | // Set the type of extraction... |
||
| 893 | $context['extract_type'] = isset($packageInfo['type']) ? $packageInfo['type'] : 'modification'; |
||
| 894 | |||
| 895 | // Create a backup file to roll back to! (but if they do this more than once, don't run it a zillion times.) |
||
| 896 | if (!empty($modSettings['package_make_full_backups']) && (!isset($_SESSION['last_backup_for']) || $_SESSION['last_backup_for'] != $context['filename'] . ($context['uninstalling'] ? '$$' : '$'))) |
||
| 897 | { |
||
| 898 | $_SESSION['last_backup_for'] = $context['filename'] . ($context['uninstalling'] ? '$$' : '$'); |
||
| 899 | $result = package_create_backup(($context['uninstalling'] ? 'backup_' : 'before_') . strtok($context['filename'], '.')); |
||
| 900 | if (!$result) |
||
| 901 | fatal_lang_error('could_not_package_backup', false); |
||
| 902 | } |
||
| 903 | |||
| 904 | // The mod isn't installed.... unless proven otherwise. |
||
| 905 | $context['is_installed'] = false; |
||
| 906 | |||
| 907 | // Is it actually installed? |
||
| 908 | $request = $smcFunc['db_query']('', ' |
||
| 909 | SELECT version, themes_installed, db_changes |
||
| 910 | FROM {db_prefix}log_packages |
||
| 911 | WHERE package_id = {string:current_package} |
||
| 912 | AND install_state != {int:not_installed} |
||
| 913 | ORDER BY time_installed DESC |
||
| 914 | LIMIT 1', |
||
| 915 | array( |
||
| 916 | 'not_installed' => 0, |
||
| 917 | 'current_package' => $packageInfo['id'], |
||
| 918 | ) |
||
| 919 | ); |
||
| 920 | View Code Duplication | while ($row = $smcFunc['db_fetch_assoc']($request)) |
|
| 921 | { |
||
| 922 | $old_themes = explode(',', $row['themes_installed']); |
||
| 923 | $old_version = $row['version']; |
||
| 924 | $db_changes = empty($row['db_changes']) ? array() : $smcFunc['json_decode']($row['db_changes'], true); |
||
| 925 | } |
||
| 926 | $smcFunc['db_free_result']($request); |
||
| 927 | |||
| 928 | // Wait, it's not installed yet! |
||
| 929 | // @todo Replace with a better error message! |
||
| 930 | if (!isset($old_version) && $context['uninstalling']) |
||
| 931 | { |
||
| 932 | deltree($packagesdir . '/temp'); |
||
| 933 | fatal_error('Hacker?', false); |
||
| 934 | } |
||
| 935 | // Uninstalling? |
||
| 936 | elseif ($context['uninstalling']) |
||
| 937 | { |
||
| 938 | $install_log = parsePackageInfo($packageInfo['xml'], false, 'uninstall'); |
||
| 939 | |||
| 940 | // Gadzooks! There's no uninstaller at all!? |
||
| 941 | if (empty($install_log)) |
||
| 942 | fatal_lang_error('package_uninstall_cannot', false); |
||
| 943 | |||
| 944 | // They can only uninstall from what it was originally installed into. |
||
| 945 | foreach ($theme_paths as $id => $data) |
||
| 946 | if ($id != 1 && !in_array($id, $old_themes)) |
||
|
0 ignored issues
–
show
The variable
$old_themes 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...
|
|||
| 947 | unset($theme_paths[$id]); |
||
| 948 | } |
||
| 949 | View Code Duplication | elseif (isset($old_version) && $old_version != $packageInfo['version']) |
|
| 950 | { |
||
| 951 | // Look for an upgrade... |
||
| 952 | $install_log = parsePackageInfo($packageInfo['xml'], false, 'upgrade', $old_version); |
||
| 953 | |||
| 954 | // There was no upgrade.... |
||
| 955 | if (empty($install_log)) |
||
| 956 | $context['is_installed'] = true; |
||
| 957 | else |
||
| 958 | { |
||
| 959 | // Upgrade previous themes only! |
||
| 960 | foreach ($theme_paths as $id => $data) |
||
| 961 | if ($id != 1 && !in_array($id, $old_themes)) |
||
| 962 | unset($theme_paths[$id]); |
||
| 963 | } |
||
| 964 | } |
||
| 965 | elseif (isset($old_version) && $old_version == $packageInfo['version']) |
||
| 966 | $context['is_installed'] = true; |
||
| 967 | |||
| 968 | View Code Duplication | if (!isset($old_version) || $context['is_installed']) |
|
| 969 | $install_log = parsePackageInfo($packageInfo['xml'], false, 'install'); |
||
| 970 | |||
| 971 | $context['install_finished'] = false; |
||
| 972 | |||
| 973 | // @todo Make a log of any errors that occurred and output them? |
||
| 974 | |||
| 975 | if (!empty($install_log)) |
||
| 976 | { |
||
| 977 | $failed_steps = array(); |
||
| 978 | $failed_count = 0; |
||
| 979 | |||
| 980 | foreach ($install_log as $action) |
||
| 981 | { |
||
| 982 | $failed_count++; |
||
| 983 | |||
| 984 | if ($action['type'] == 'modification' && !empty($action['filename'])) |
||
| 985 | { |
||
| 986 | View Code Duplication | if ($action['boardmod']) |
|
| 987 | $mod_actions = parseBoardMod(file_get_contents($packagesdir . '/temp/' . $context['base_path'] . $action['filename']), false, $action['reverse'], $theme_paths); |
||
| 988 | else |
||
| 989 | $mod_actions = parseModification(file_get_contents($packagesdir . '/temp/' . $context['base_path'] . $action['filename']), false, $action['reverse'], $theme_paths); |
||
| 990 | |||
| 991 | // Any errors worth noting? |
||
| 992 | foreach ($mod_actions as $key => $modAction) |
||
| 993 | { |
||
| 994 | if ($modAction['type'] == 'failure') |
||
| 995 | $failed_steps[] = array( |
||
| 996 | 'file' => $modAction['filename'], |
||
| 997 | 'large_step' => $failed_count, |
||
| 998 | 'sub_step' => $key, |
||
| 999 | 'theme' => 1, |
||
| 1000 | ); |
||
| 1001 | |||
| 1002 | // Gather the themes we installed into. |
||
| 1003 | if (!empty($modAction['is_custom'])) |
||
| 1004 | $themes_installed[] = $modAction['is_custom']; |
||
| 1005 | } |
||
| 1006 | } |
||
| 1007 | elseif ($action['type'] == 'code' && !empty($action['filename'])) |
||
| 1008 | { |
||
| 1009 | // This is just here as reference for what is available. |
||
| 1010 | global $txt, $boarddir, $sourcedir, $modSettings, $context, $settings, $forum_version, $smcFunc; |
||
| 1011 | |||
| 1012 | // Now include the file and be done with it ;). |
||
| 1013 | View Code Duplication | if (file_exists($packagesdir . '/temp/' . $context['base_path'] . $action['filename'])) |
|
| 1014 | require($packagesdir . '/temp/' . $context['base_path'] . $action['filename']); |
||
| 1015 | } |
||
| 1016 | View Code Duplication | elseif ($action['type'] == 'credits') |
|
| 1017 | { |
||
| 1018 | // Time to build the billboard |
||
| 1019 | $credits_tag = array( |
||
| 1020 | 'url' => $action['url'], |
||
| 1021 | 'license' => $action['license'], |
||
| 1022 | 'licenseurl' => $action['licenseurl'], |
||
| 1023 | 'copyright' => $action['copyright'], |
||
| 1024 | 'title' => $action['title'], |
||
| 1025 | ); |
||
| 1026 | } |
||
| 1027 | elseif ($action['type'] == 'hook' && isset($action['hook'], $action['function'])) |
||
| 1028 | { |
||
| 1029 | if ($action['reverse']) |
||
| 1030 | remove_integration_function($action['hook'], $action['function'], true, $action['include_file'], $action['object']); |
||
| 1031 | else |
||
| 1032 | add_integration_function($action['hook'], $action['function'], true, $action['include_file'], $action['object']); |
||
| 1033 | } |
||
| 1034 | // Only do the database changes on uninstall if requested. |
||
| 1035 | elseif ($action['type'] == 'database' && !empty($action['filename']) && (!$context['uninstalling'] || !empty($_POST['do_db_changes']))) |
||
| 1036 | { |
||
| 1037 | // These can also be there for database changes. |
||
| 1038 | global $txt, $boarddir, $sourcedir, $modSettings, $context, $settings, $forum_version, $smcFunc; |
||
| 1039 | global $db_package_log; |
||
| 1040 | |||
| 1041 | // We'll likely want the package specific database functionality! |
||
| 1042 | db_extend('packages'); |
||
| 1043 | |||
| 1044 | // Let the file work its magic ;) |
||
| 1045 | View Code Duplication | if (file_exists($packagesdir . '/temp/' . $context['base_path'] . $action['filename'])) |
|
| 1046 | require($packagesdir . '/temp/' . $context['base_path'] . $action['filename']); |
||
| 1047 | } |
||
| 1048 | // Handle a redirect... |
||
| 1049 | elseif ($action['type'] == 'redirect' && !empty($action['redirect_url'])) |
||
| 1050 | { |
||
| 1051 | $context['redirect_url'] = $action['redirect_url']; |
||
| 1052 | $context['redirect_text'] = !empty($action['filename']) && file_exists($packagesdir . '/temp/' . $context['base_path'] . $action['filename']) ? $smcFunc['htmlspecialchars'](file_get_contents($packagesdir . '/temp/' . $context['base_path'] . $action['filename'])) : ($context['uninstalling'] ? $txt['package_uninstall_done'] : $txt['package_installed_done']); |
||
| 1053 | $context['redirect_timeout'] = $action['redirect_timeout']; |
||
| 1054 | if (!empty($action['parse_bbc'])) |
||
| 1055 | { |
||
| 1056 | require_once($sourcedir . '/Subs-Post.php'); |
||
| 1057 | $context['redirect_text'] = preg_replace('~\[[/]?html\]~i', '', $context['redirect_text']); |
||
| 1058 | preparsecode($context['redirect_text']); |
||
| 1059 | $context['redirect_text'] = parse_bbc($context['redirect_text']); |
||
| 1060 | } |
||
| 1061 | |||
| 1062 | // Parse out a couple of common urls. |
||
| 1063 | $urls = array( |
||
| 1064 | '$boardurl' => $boardurl, |
||
| 1065 | '$scripturl' => $scripturl, |
||
| 1066 | '$session_var' => $context['session_var'], |
||
| 1067 | '$session_id' => $context['session_id'], |
||
| 1068 | ); |
||
| 1069 | |||
| 1070 | $context['redirect_url'] = strtr($context['redirect_url'], $urls); |
||
| 1071 | } |
||
| 1072 | } |
||
| 1073 | |||
| 1074 | package_flush_cache(); |
||
| 1075 | |||
| 1076 | // See if this is already installed, and change it's state as required. |
||
| 1077 | $request = $smcFunc['db_query']('', ' |
||
| 1078 | SELECT package_id, install_state, db_changes |
||
| 1079 | FROM {db_prefix}log_packages |
||
| 1080 | WHERE install_state != {int:not_installed} |
||
| 1081 | AND package_id = {string:current_package} |
||
| 1082 | ' . ($context['install_id'] ? ' AND id_install = {int:install_id} ' : '') . ' |
||
| 1083 | ORDER BY time_installed DESC |
||
| 1084 | LIMIT 1', |
||
| 1085 | array( |
||
| 1086 | 'not_installed' => 0, |
||
| 1087 | 'install_id' => $context['install_id'], |
||
| 1088 | 'current_package' => $packageInfo['id'], |
||
| 1089 | ) |
||
| 1090 | ); |
||
| 1091 | $is_upgrade = false; |
||
| 1092 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1093 | { |
||
| 1094 | // Uninstalling? |
||
| 1095 | if ($context['uninstalling']) |
||
| 1096 | { |
||
| 1097 | $smcFunc['db_query']('', ' |
||
| 1098 | UPDATE {db_prefix}log_packages |
||
| 1099 | SET install_state = {int:not_installed}, member_removed = {string:member_name}, id_member_removed = {int:current_member}, |
||
| 1100 | time_removed = {int:current_time} |
||
| 1101 | WHERE package_id = {string:package_id} |
||
| 1102 | AND id_install = {int:install_id}', |
||
| 1103 | array( |
||
| 1104 | 'current_member' => $user_info['id'], |
||
| 1105 | 'not_installed' => 0, |
||
| 1106 | 'current_time' => time(), |
||
| 1107 | 'package_id' => $row['package_id'], |
||
| 1108 | 'member_name' => $user_info['name'], |
||
| 1109 | 'install_id' => $context['install_id'], |
||
| 1110 | ) |
||
| 1111 | ); |
||
| 1112 | } |
||
| 1113 | // Otherwise must be an upgrade. |
||
| 1114 | else |
||
| 1115 | { |
||
| 1116 | $is_upgrade = true; |
||
| 1117 | $old_db_changes = empty($row['db_changes']) ? array() : $smcFunc['json_decode']($row['db_changes'], true); |
||
| 1118 | } |
||
| 1119 | } |
||
| 1120 | |||
| 1121 | // Assuming we're not uninstalling, add the entry. |
||
| 1122 | if (!$context['uninstalling']) |
||
| 1123 | { |
||
| 1124 | // Reload the settings table for mods that have altered them upon installation |
||
| 1125 | reloadSettings(); |
||
| 1126 | |||
| 1127 | // Any db changes from older version? |
||
| 1128 | if (!empty($old_db_changes)) |
||
| 1129 | $db_package_log = empty($db_package_log) ? $old_db_changes : array_merge($old_db_changes, $db_package_log); |
||
| 1130 | |||
| 1131 | // If there are some database changes we might want to remove then filter them out. |
||
| 1132 | if (!empty($db_package_log)) |
||
| 1133 | { |
||
| 1134 | // We're really just checking for entries which are create table AND add columns (etc). |
||
| 1135 | $tables = array(); |
||
| 1136 | /** |
||
| 1137 | * Table sorting function used in usort |
||
| 1138 | * |
||
| 1139 | * @param array $a |
||
| 1140 | * @param array $b |
||
| 1141 | * @return int |
||
| 1142 | */ |
||
| 1143 | function sort_table_first($a, $b) |
||
| 1144 | { |
||
| 1145 | if ($a[0] == $b[0]) |
||
| 1146 | return 0; |
||
| 1147 | return $a[0] == 'remove_table' ? -1 : 1; |
||
| 1148 | } |
||
| 1149 | usort($db_package_log, 'sort_table_first'); |
||
| 1150 | foreach ($db_package_log as $k => $log) |
||
| 1151 | { |
||
| 1152 | if ($log[0] == 'remove_table') |
||
| 1153 | $tables[] = $log[1]; |
||
| 1154 | elseif (in_array($log[1], $tables)) |
||
| 1155 | unset($db_package_log[$k]); |
||
| 1156 | } |
||
| 1157 | $db_changes = $smcFunc['json_encode']($db_package_log); |
||
| 1158 | } |
||
| 1159 | else |
||
| 1160 | $db_changes = ''; |
||
| 1161 | |||
| 1162 | // What themes did we actually install? |
||
| 1163 | $themes_installed = array_unique($themes_installed); |
||
| 1164 | $themes_installed = implode(',', $themes_installed); |
||
| 1165 | |||
| 1166 | // What failed steps? |
||
| 1167 | $failed_step_insert = $smcFunc['json_encode']($failed_steps); |
||
| 1168 | |||
| 1169 | // Un-sanitize things before we insert them... |
||
| 1170 | $keys = array('filename', 'name', 'id', 'version'); |
||
| 1171 | foreach ($keys as $key) |
||
| 1172 | { |
||
| 1173 | // Yay for variable variables... |
||
| 1174 | ${"package_$key"} = un_htmlspecialchars($packageInfo[$key]); |
||
| 1175 | } |
||
| 1176 | |||
| 1177 | // Credits tag? |
||
| 1178 | $credits_tag = (empty($credits_tag)) ? '' : $smcFunc['json_encode']($credits_tag); |
||
| 1179 | $smcFunc['db_insert']('', |
||
| 1180 | '{db_prefix}log_packages', |
||
| 1181 | array( |
||
| 1182 | 'filename' => 'string', 'name' => 'string', 'package_id' => 'string', 'version' => 'string', |
||
| 1183 | 'id_member_installed' => 'int', 'member_installed' => 'string', 'time_installed' => 'int', |
||
| 1184 | 'install_state' => 'int', 'failed_steps' => 'string', 'themes_installed' => 'string', |
||
| 1185 | 'member_removed' => 'int', 'db_changes' => 'string', 'credits' => 'string', |
||
| 1186 | ), |
||
| 1187 | array( |
||
| 1188 | $package_filename, $package_name, $package_id, $package_version, |
||
|
0 ignored issues
–
show
The variable
$package_filename does not exist. Did you forget to declare it?
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug. Loading history...
The variable
$package_name does not exist. Did you forget to declare it?
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug. Loading history...
The variable
$package_version does not exist. Did you forget to declare it?
This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug. Loading history...
|
|||
| 1189 | $user_info['id'], $user_info['name'], time(), |
||
| 1190 | $is_upgrade ? 2 : 1, $failed_step_insert, $themes_installed, |
||
| 1191 | 0, $db_changes, $credits_tag, |
||
| 1192 | ), |
||
| 1193 | array('id_install') |
||
| 1194 | ); |
||
| 1195 | } |
||
| 1196 | $smcFunc['db_free_result']($request); |
||
| 1197 | |||
| 1198 | $context['install_finished'] = true; |
||
| 1199 | } |
||
| 1200 | |||
| 1201 | // If there's database changes - and they want them removed - let's do it last! |
||
| 1202 | if (!empty($db_changes) && !empty($_POST['do_db_changes'])) |
||
| 1203 | { |
||
| 1204 | // We're gonna be needing the package db functions! |
||
| 1205 | db_extend('packages'); |
||
| 1206 | |||
| 1207 | foreach ($db_changes as $change) |
||
| 1208 | { |
||
| 1209 | if ($change[0] == 'remove_table' && isset($change[1])) |
||
| 1210 | $smcFunc['db_drop_table']($change[1]); |
||
| 1211 | View Code Duplication | elseif ($change[0] == 'remove_column' && isset($change[2])) |
|
| 1212 | $smcFunc['db_remove_column']($change[1], $change[2]); |
||
| 1213 | View Code Duplication | elseif ($change[0] == 'remove_index' && isset($change[2])) |
|
| 1214 | $smcFunc['db_remove_index']($change[1], $change[2]); |
||
| 1215 | } |
||
| 1216 | } |
||
| 1217 | |||
| 1218 | // Clean house... get rid of the evidence ;). |
||
| 1219 | if (file_exists($packagesdir . '/temp')) |
||
| 1220 | deltree($packagesdir . '/temp'); |
||
| 1221 | |||
| 1222 | // Log what we just did. |
||
| 1223 | logAction($context['uninstalling'] ? 'uninstall_package' : (!empty($is_upgrade) ? 'upgrade_package' : 'install_package'), array('package' => $smcFunc['htmlspecialchars']($packageInfo['name']), 'version' => $smcFunc['htmlspecialchars']($packageInfo['version'])), 'admin'); |
||
| 1224 | |||
| 1225 | // Just in case, let's clear the whole cache to avoid anything going up the swanny. |
||
| 1226 | clean_cache(); |
||
| 1227 | |||
| 1228 | // Restore file permissions? |
||
| 1229 | create_chmod_control(array(), array(), true); |
||
| 1230 | } |
||
| 1231 | |||
| 1232 | /** |
||
| 1233 | * List the files in a package. |
||
| 1234 | */ |
||
| 1235 | function PackageList() |
||
| 1236 | { |
||
| 1237 | global $txt, $scripturl, $context, $sourcedir, $packagesdir; |
||
| 1238 | |||
| 1239 | require_once($sourcedir . '/Subs-Package.php'); |
||
| 1240 | |||
| 1241 | // No package? Show him or her the door. |
||
| 1242 | if (!isset($_REQUEST['package']) || $_REQUEST['package'] == '') |
||
| 1243 | redirectexit('action=admin;area=packages'); |
||
| 1244 | |||
| 1245 | $context['linktree'][] = array( |
||
| 1246 | 'url' => $scripturl . '?action=admin;area=packages;sa=list;package=' . $_REQUEST['package'], |
||
| 1247 | 'name' => $txt['list_file'] |
||
| 1248 | ); |
||
| 1249 | $context['page_title'] .= ' - ' . $txt['list_file']; |
||
| 1250 | $context['sub_template'] = 'list'; |
||
| 1251 | |||
| 1252 | // The filename... |
||
| 1253 | $context['filename'] = $_REQUEST['package']; |
||
| 1254 | |||
| 1255 | // Let the unpacker do the work. |
||
| 1256 | if (is_file($packagesdir . '/' . $context['filename'])) |
||
| 1257 | $context['files'] = read_tgz_file($packagesdir . '/' . $context['filename'], null); |
||
| 1258 | elseif (is_dir($packagesdir . '/' . $context['filename'])) |
||
| 1259 | $context['files'] = listtree($packagesdir . '/' . $context['filename']); |
||
| 1260 | } |
||
| 1261 | |||
| 1262 | /** |
||
| 1263 | * Display one of the files in a package. |
||
| 1264 | */ |
||
| 1265 | function ExamineFile() |
||
| 1266 | { |
||
| 1267 | global $txt, $scripturl, $context, $sourcedir, $packagesdir, $smcFunc; |
||
| 1268 | |||
| 1269 | require_once($sourcedir . '/Subs-Package.php'); |
||
| 1270 | |||
| 1271 | // No package? Show him or her the door. |
||
| 1272 | if (!isset($_REQUEST['package']) || $_REQUEST['package'] == '') |
||
| 1273 | redirectexit('action=admin;area=packages'); |
||
| 1274 | |||
| 1275 | // No file? Show him or her the door. |
||
| 1276 | if (!isset($_REQUEST['file']) || $_REQUEST['file'] == '') |
||
| 1277 | redirectexit('action=admin;area=packages'); |
||
| 1278 | |||
| 1279 | $_REQUEST['package'] = preg_replace('~[\.]+~', '.', strtr($_REQUEST['package'], array('/' => '_', '\\' => '_'))); |
||
| 1280 | $_REQUEST['file'] = preg_replace('~[\.]+~', '.', $_REQUEST['file']); |
||
| 1281 | |||
| 1282 | if (isset($_REQUEST['raw'])) |
||
| 1283 | { |
||
| 1284 | if (is_file($packagesdir . '/' . $_REQUEST['package'])) |
||
| 1285 | echo read_tgz_file($packagesdir . '/' . $_REQUEST['package'], $_REQUEST['file'], true); |
||
| 1286 | elseif (is_dir($packagesdir . '/' . $_REQUEST['package'])) |
||
| 1287 | echo file_get_contents($packagesdir . '/' . $_REQUEST['package'] . '/' . $_REQUEST['file']); |
||
| 1288 | |||
| 1289 | obExit(false); |
||
| 1290 | } |
||
| 1291 | |||
| 1292 | $context['linktree'][count($context['linktree']) - 1] = array( |
||
| 1293 | 'url' => $scripturl . '?action=admin;area=packages;sa=list;package=' . $_REQUEST['package'], |
||
| 1294 | 'name' => $txt['package_examine_file'] |
||
| 1295 | ); |
||
| 1296 | $context['page_title'] .= ' - ' . $txt['package_examine_file']; |
||
| 1297 | $context['sub_template'] = 'examine'; |
||
| 1298 | |||
| 1299 | // The filename... |
||
| 1300 | $context['package'] = $_REQUEST['package']; |
||
| 1301 | $context['filename'] = $_REQUEST['file']; |
||
| 1302 | |||
| 1303 | // Let the unpacker do the work.... but make sure we handle images properly. |
||
| 1304 | if (in_array(strtolower(strrchr($_REQUEST['file'], '.')), array('.bmp', '.gif', '.jpeg', '.jpg', '.png'))) |
||
| 1305 | $context['filedata'] = '<img src="' . $scripturl . '?action=admin;area=packages;sa=examine;package=' . $_REQUEST['package'] . ';file=' . $_REQUEST['file'] . ';raw" alt="' . $_REQUEST['file'] . '">'; |
||
| 1306 | else |
||
| 1307 | { |
||
| 1308 | if (is_file($packagesdir . '/' . $_REQUEST['package'])) |
||
| 1309 | $context['filedata'] = $smcFunc['htmlspecialchars'](read_tgz_file($packagesdir . '/' . $_REQUEST['package'], $_REQUEST['file'], true)); |
||
| 1310 | elseif (is_dir($packagesdir . '/' . $_REQUEST['package'])) |
||
| 1311 | $context['filedata'] = $smcFunc['htmlspecialchars'](file_get_contents($packagesdir . '/' . $_REQUEST['package'] . '/' . $_REQUEST['file'])); |
||
| 1312 | |||
| 1313 | if (strtolower(strrchr($_REQUEST['file'], '.')) == '.php') |
||
| 1314 | $context['filedata'] = highlight_php_code($context['filedata']); |
||
| 1315 | } |
||
| 1316 | } |
||
| 1317 | |||
| 1318 | /** |
||
| 1319 | * Delete a package. |
||
| 1320 | */ |
||
| 1321 | function PackageRemove() |
||
| 1322 | { |
||
| 1323 | global $scripturl, $packagesdir; |
||
| 1324 | |||
| 1325 | // Check it. |
||
| 1326 | checkSession('get'); |
||
| 1327 | |||
| 1328 | // Ack, don't allow deletion of arbitrary files here, could become a security hole somehow! |
||
| 1329 | if (!isset($_GET['package']) || $_GET['package'] == 'index.php' || $_GET['package'] == 'backups') |
||
| 1330 | redirectexit('action=admin;area=packages;sa=browse'); |
||
| 1331 | $_GET['package'] = preg_replace('~[\.]+~', '.', strtr($_GET['package'], array('/' => '_', '\\' => '_'))); |
||
| 1332 | |||
| 1333 | // Can't delete what's not there. |
||
| 1334 | if (file_exists($packagesdir . '/' . $_GET['package']) && (substr($_GET['package'], -4) == '.zip' || substr($_GET['package'], -4) == '.tgz' || substr($_GET['package'], -7) == '.tar.gz' || is_dir($packagesdir . '/' . $_GET['package'])) && $_GET['package'] != 'backups' && substr($_GET['package'], 0, 1) != '.') |
||
| 1335 | { |
||
| 1336 | create_chmod_control(array($packagesdir . '/' . $_GET['package']), array('destination_url' => $scripturl . '?action=admin;area=packages;sa=remove;package=' . $_GET['package'], 'crash_on_error' => true)); |
||
| 1337 | |||
| 1338 | if (is_dir($packagesdir . '/' . $_GET['package'])) |
||
| 1339 | deltree($packagesdir . '/' . $_GET['package']); |
||
| 1340 | else |
||
| 1341 | { |
||
| 1342 | smf_chmod($packagesdir . '/' . $_GET['package'], 0777); |
||
| 1343 | unlink($packagesdir . '/' . $_GET['package']); |
||
| 1344 | } |
||
| 1345 | } |
||
| 1346 | |||
| 1347 | redirectexit('action=admin;area=packages;sa=browse'); |
||
| 1348 | } |
||
| 1349 | |||
| 1350 | /** |
||
| 1351 | * Browse a list of installed packages. |
||
| 1352 | */ |
||
| 1353 | function PackageBrowse() |
||
| 1354 | { |
||
| 1355 | global $txt, $scripturl, $context, $forum_version, $sourcedir, $smcFunc; |
||
| 1356 | |||
| 1357 | $context['page_title'] .= ' - ' . $txt['browse_packages']; |
||
| 1358 | |||
| 1359 | $context['forum_version'] = $forum_version; |
||
| 1360 | $context['modification_types'] = array('modification', 'avatar', 'language', 'unknown'); |
||
| 1361 | |||
| 1362 | call_integration_hook('integrate_modification_types'); |
||
| 1363 | |||
| 1364 | require_once($sourcedir . '/Subs-List.php'); |
||
| 1365 | |||
| 1366 | foreach ($context['modification_types'] as $type) |
||
| 1367 | { |
||
| 1368 | // Use the standard templates for showing this. |
||
| 1369 | $listOptions = array( |
||
| 1370 | 'id' => 'packages_lists_' . $type, |
||
| 1371 | 'title' => $txt[$type . '_package'], |
||
| 1372 | 'no_items_label' => $txt['no_packages'], |
||
| 1373 | 'get_items' => array( |
||
| 1374 | 'function' => 'list_getPackages', |
||
| 1375 | 'params' => array('type' => $type), |
||
| 1376 | ), |
||
| 1377 | 'base_href' => $scripturl . '?action=admin;area=packages;sa=browse;type=' . $type, |
||
| 1378 | 'default_sort_col' => 'id' . $type, |
||
| 1379 | 'columns' => array( |
||
| 1380 | 'id' . $type => array( |
||
| 1381 | 'header' => array( |
||
| 1382 | 'value' => $txt['package_id'], |
||
| 1383 | 'style' => 'width: 40px;', |
||
| 1384 | ), |
||
| 1385 | 'data' => array( |
||
| 1386 | View Code Duplication | 'function' => function($package_md5) use ($type, &$context) |
|
| 1387 | { |
||
| 1388 | if (isset($context['available_' . $type . ''][$package_md5])) |
||
| 1389 | return $context['available_' . $type . ''][$package_md5]['sort_id']; |
||
| 1390 | }, |
||
| 1391 | ), |
||
| 1392 | 'sort' => array( |
||
| 1393 | 'default' => 'sort_id', |
||
| 1394 | 'reverse' => 'sort_id' |
||
| 1395 | ), |
||
| 1396 | ), |
||
| 1397 | 'mod_name' . $type => array( |
||
| 1398 | 'header' => array( |
||
| 1399 | 'value' => $txt['mod_name'], |
||
| 1400 | 'style' => 'width: 25%;', |
||
| 1401 | ), |
||
| 1402 | 'data' => array( |
||
| 1403 | View Code Duplication | 'function' => function($package_md5) use ($type, &$context) |
|
| 1404 | { |
||
| 1405 | if (isset($context['available_' . $type . ''][$package_md5])) |
||
| 1406 | return $context['available_' . $type . ''][$package_md5]['name']; |
||
| 1407 | }, |
||
| 1408 | ), |
||
| 1409 | 'sort' => array( |
||
| 1410 | 'default' => 'name', |
||
| 1411 | 'reverse' => 'name', |
||
| 1412 | ), |
||
| 1413 | ), |
||
| 1414 | 'version' . $type => array( |
||
| 1415 | 'header' => array( |
||
| 1416 | 'value' => $txt['mod_version'], |
||
| 1417 | ), |
||
| 1418 | 'data' => array( |
||
| 1419 | View Code Duplication | 'function' => function($package_md5) use ($type, &$context) |
|
| 1420 | { |
||
| 1421 | if (isset($context['available_' . $type . ''][$package_md5])) |
||
| 1422 | return $context['available_' . $type . ''][$package_md5]['version']; |
||
| 1423 | }, |
||
| 1424 | ), |
||
| 1425 | 'sort' => array( |
||
| 1426 | 'default' => 'version', |
||
| 1427 | 'reverse' => 'version', |
||
| 1428 | ), |
||
| 1429 | ), |
||
| 1430 | 'time_installed' . $type => array( |
||
| 1431 | 'header' => array( |
||
| 1432 | 'value' => $txt['mod_installed_time'], |
||
| 1433 | ), |
||
| 1434 | 'data' => array( |
||
| 1435 | 'function' => function($package_md5) use ($type, $txt, &$context) |
||
| 1436 | { |
||
| 1437 | if (isset($context['available_' . $type . ''][$package_md5])) |
||
| 1438 | return !empty($context['available_' . $type . ''][$package_md5]['time_installed']) ? timeformat($context['available_' . $type . ''][$package_md5]['time_installed']) : $txt['not_applicable']; |
||
| 1439 | }, |
||
| 1440 | 'class' => 'smalltext', |
||
| 1441 | ), |
||
| 1442 | 'sort' => array( |
||
| 1443 | 'default' => 'time_installed', |
||
| 1444 | 'reverse' => 'time_installed', |
||
| 1445 | ), |
||
| 1446 | ), |
||
| 1447 | 'operations' . $type => array( |
||
| 1448 | 'header' => array( |
||
| 1449 | 'value' => '', |
||
| 1450 | ), |
||
| 1451 | 'data' => array( |
||
| 1452 | 'function' => function($package_md5) use ($type, &$context, $scripturl, $txt) |
||
| 1453 | { |
||
| 1454 | if (!isset($context['available_' . $type . ''][$package_md5])) |
||
| 1455 | return ''; |
||
| 1456 | |||
| 1457 | // Rewrite shortcut |
||
| 1458 | $package = $context['available_' . $type . ''][$package_md5]; |
||
| 1459 | $return = ''; |
||
| 1460 | |||
| 1461 | if ($package['can_uninstall']) |
||
| 1462 | $return = ' |
||
| 1463 | <a href="' . $scripturl . '?action=admin;area=packages;sa=uninstall;package=' . $package['filename'] . ';pid=' . $package['installed_id'] . '" class="button">' . $txt['uninstall'] . '</a>'; |
||
| 1464 | elseif ($package['can_emulate_uninstall']) |
||
| 1465 | $return = ' |
||
| 1466 | <a href="' . $scripturl . '?action=admin;area=packages;sa=uninstall;ve=' . $package['can_emulate_uninstall'] . ';package=' . $package['filename'] . ';pid=' . $package['installed_id'] . '" class="button">' . $txt['package_emulate_uninstall'] . ' ' . $package['can_emulate_uninstall'] . '</a>'; |
||
| 1467 | View Code Duplication | elseif ($package['can_upgrade']) |
|
| 1468 | $return = ' |
||
| 1469 | <a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $package['filename'] . '" class="button">' . $txt['package_upgrade'] . '</a>'; |
||
| 1470 | View Code Duplication | elseif ($package['can_install']) |
|
| 1471 | $return = ' |
||
| 1472 | <a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $package['filename'] . '" class="button">' . $txt['install_mod'] . '</a>'; |
||
| 1473 | elseif ($package['can_emulate_install']) |
||
| 1474 | $return = ' |
||
| 1475 | <a href="' . $scripturl . '?action=admin;area=packages;sa=install;ve=' . $package['can_emulate_install'] . ';package=' . $package['filename'] . '" class="button">' . $txt['package_emulate_install'] . ' ' . $package['can_emulate_install'] . '</a>'; |
||
| 1476 | |||
| 1477 | return $return . ' |
||
| 1478 | <a href="' . $scripturl . '?action=admin;area=packages;sa=list;package=' . $package['filename'] . '" class="button">' . $txt['list_files'] . '</a> |
||
| 1479 | <a href="' . $scripturl . '?action=admin;area=packages;sa=remove;package=' . $package['filename'] . ';' . $context['session_var'] . '=' . $context['session_id'] . '"' . ($package['is_installed'] && $package['is_current'] ? ' data-confirm="' . $txt['package_delete_bad'] . '"' : '') . ' class="button' . ($package['is_installed'] && $package['is_current'] ? ' you_sure' : '') . '">' . $txt['package_delete'] . '</a>'; |
||
| 1480 | }, |
||
| 1481 | 'class' => 'righttext', |
||
| 1482 | ), |
||
| 1483 | ), |
||
| 1484 | ), |
||
| 1485 | ); |
||
| 1486 | |||
| 1487 | createList($listOptions); |
||
| 1488 | } |
||
| 1489 | |||
| 1490 | $context['sub_template'] = 'browse'; |
||
| 1491 | $context['default_list'] = 'packages_lists'; |
||
| 1492 | |||
| 1493 | // Empty lists for now. |
||
| 1494 | $context['available_mods'] = array(); |
||
| 1495 | $context['available_avatars'] = array(); |
||
| 1496 | $context['available_languages'] = array(); |
||
| 1497 | $context['available_other'] = array(); |
||
| 1498 | $context['available_all'] = array(); |
||
| 1499 | |||
| 1500 | $get_versions = $smcFunc['db_query']('', ' |
||
| 1501 | SELECT data FROM {db_prefix}admin_info_files WHERE filename={string:versionsfile} AND path={string:smf}', |
||
| 1502 | array( |
||
| 1503 | 'versionsfile' => 'latest-versions.txt', |
||
| 1504 | 'smf' => '/smf/', |
||
| 1505 | ) |
||
| 1506 | ); |
||
| 1507 | |||
| 1508 | $data = $smcFunc['db_fetch_assoc']($get_versions); |
||
| 1509 | $smcFunc['db_free_result']($get_versions); |
||
| 1510 | |||
| 1511 | // Decode the data. |
||
| 1512 | $items = $smcFunc['json_decode']($data['data'], true); |
||
| 1513 | |||
| 1514 | $context['emulation_versions'] = preg_replace('~^SMF ~', '', $items); |
||
| 1515 | |||
| 1516 | // Current SMF version, which is selected by default |
||
| 1517 | $context['default_version'] = preg_replace('~^SMF ~', '', $forum_version); |
||
| 1518 | |||
| 1519 | // Version we're currently emulating, if any |
||
| 1520 | $context['selected_version'] = preg_replace('~^SMF ~', '', $context['forum_version']); |
||
| 1521 | } |
||
| 1522 | |||
| 1523 | /** |
||
| 1524 | * Get a listing of all the packages |
||
| 1525 | * Determines if the package is a mod, avatar, language package |
||
| 1526 | * Determines if the package has been installed or not |
||
| 1527 | * |
||
| 1528 | * @param int $start The item to start with (not used here) |
||
| 1529 | * @param int $items_per_page The number of items to show per page (not used here) |
||
| 1530 | * @param string $sort A string indicating how to sort the results |
||
| 1531 | * @param string? $params A key for the $packages array |
||
| 1532 | * @return array An array of information about the packages |
||
| 1533 | */ |
||
| 1534 | function list_getPackages($start, $items_per_page, $sort, $params) |
||
| 1535 | { |
||
| 1536 | global $scripturl, $packagesdir, $context, $forum_version; |
||
| 1537 | static $packages, $installed_mods; |
||
| 1538 | |||
| 1539 | // Start things up |
||
| 1540 | if (!isset($packages[$params])) |
||
| 1541 | $packages[$params] = array(); |
||
| 1542 | |||
| 1543 | // We need the packages directory to be writable for this. |
||
| 1544 | if (!@is_writable($packagesdir)) |
||
| 1545 | create_chmod_control(array($packagesdir), array('destination_url' => $scripturl . '?action=admin;area=packages', 'crash_on_error' => true)); |
||
| 1546 | |||
| 1547 | $the_version = strtr($forum_version, array('SMF ' => '')); |
||
| 1548 | |||
| 1549 | // Here we have a little code to help those who class themselves as something of gods, version emulation ;) |
||
| 1550 | if (isset($_GET['version_emulate']) && strtr($_GET['version_emulate'], array('SMF ' => '')) == $the_version) |
||
| 1551 | { |
||
| 1552 | unset($_SESSION['version_emulate']); |
||
| 1553 | } |
||
| 1554 | elseif (isset($_GET['version_emulate'])) |
||
| 1555 | { |
||
| 1556 | if (($_GET['version_emulate'] === 0 || $_GET['version_emulate'] === $forum_version) && isset($_SESSION['version_emulate'])) |
||
| 1557 | unset($_SESSION['version_emulate']); |
||
| 1558 | elseif ($_GET['version_emulate'] !== 0) |
||
| 1559 | $_SESSION['version_emulate'] = strtr($_GET['version_emulate'], array('-' => ' ', '+' => ' ', 'SMF ' => '')); |
||
| 1560 | } |
||
| 1561 | if (!empty($_SESSION['version_emulate'])) |
||
| 1562 | { |
||
| 1563 | $context['forum_version'] = 'SMF ' . $_SESSION['version_emulate']; |
||
| 1564 | $the_version = $_SESSION['version_emulate']; |
||
| 1565 | } |
||
| 1566 | if (isset($_SESSION['single_version_emulate'])) |
||
| 1567 | unset($_SESSION['single_version_emulate']); |
||
| 1568 | |||
| 1569 | if (empty($installed_mods)) |
||
| 1570 | { |
||
| 1571 | $instmods = loadInstalledPackages(); |
||
| 1572 | $installed_mods = array(); |
||
| 1573 | // Look through the list of installed mods... |
||
| 1574 | foreach ($instmods as $installed_mod) |
||
| 1575 | $installed_mods[$installed_mod['package_id']] = array( |
||
| 1576 | 'id' => $installed_mod['id'], |
||
| 1577 | 'version' => $installed_mod['version'], |
||
| 1578 | 'time_installed' => $installed_mod['time_installed'], |
||
| 1579 | ); |
||
| 1580 | |||
| 1581 | // Get a list of all the ids installed, so the latest packages won't include already installed ones. |
||
| 1582 | $context['installed_mods'] = array_keys($installed_mods); |
||
| 1583 | } |
||
| 1584 | |||
| 1585 | if (empty($packages)) |
||
| 1586 | foreach ($context['modification_types'] as $type) |
||
| 1587 | $packages[$type] = array(); |
||
| 1588 | |||
| 1589 | if ($dir = @opendir($packagesdir)) |
||
| 1590 | { |
||
| 1591 | $dirs = array(); |
||
| 1592 | $sort_id = array( |
||
| 1593 | 'mod' => 1, |
||
| 1594 | 'modification' => 1, |
||
| 1595 | 'avatar' => 1, |
||
| 1596 | 'language' => 1, |
||
| 1597 | 'unknown' => 1, |
||
| 1598 | ); |
||
| 1599 | call_integration_hook('integrate_packages_sort_id', array(&$sort_id, &$packages)); |
||
| 1600 | |||
| 1601 | while ($package = readdir($dir)) |
||
| 1602 | { |
||
| 1603 | View Code Duplication | if ($package == '.' || $package == '..' || $package == 'temp' || (!(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')) |
|
| 1604 | continue; |
||
| 1605 | |||
| 1606 | $skip = false; |
||
| 1607 | foreach ($context['modification_types'] as $type) |
||
| 1608 | if (isset($context['available_' . $type][md5($package)])) |
||
| 1609 | $skip = true; |
||
| 1610 | |||
| 1611 | if ($skip) |
||
| 1612 | continue; |
||
| 1613 | |||
| 1614 | // Skip directories or files that are named the same. |
||
| 1615 | if (is_dir($packagesdir . '/' . $package)) |
||
| 1616 | { |
||
| 1617 | if (in_array($package, $dirs)) |
||
| 1618 | continue; |
||
| 1619 | $dirs[] = $package; |
||
| 1620 | } |
||
| 1621 | elseif (substr(strtolower($package), -7) == '.tar.gz') |
||
| 1622 | { |
||
| 1623 | if (in_array(substr($package, 0, -7), $dirs)) |
||
| 1624 | continue; |
||
| 1625 | $dirs[] = substr($package, 0, -7); |
||
| 1626 | } |
||
| 1627 | elseif (substr(strtolower($package), -4) == '.zip' || substr(strtolower($package), -4) == '.tgz') |
||
| 1628 | { |
||
| 1629 | if (in_array(substr($package, 0, -4), $dirs)) |
||
| 1630 | continue; |
||
| 1631 | $dirs[] = substr($package, 0, -4); |
||
| 1632 | } |
||
| 1633 | |||
| 1634 | $packageInfo = getPackageInfo($package); |
||
| 1635 | if (!is_array($packageInfo)) |
||
| 1636 | continue; |
||
| 1637 | |||
| 1638 | if (!empty($packageInfo)) |
||
| 1639 | { |
||
| 1640 | $packageInfo['installed_id'] = isset($installed_mods[$packageInfo['id']]) ? $installed_mods[$packageInfo['id']]['id'] : 0; |
||
| 1641 | $packageInfo['time_installed'] = isset($installed_mods[$packageInfo['id']]) ? $installed_mods[$packageInfo['id']]['time_installed'] : 0; |
||
| 1642 | |||
| 1643 | if (!isset($sort_id[$packageInfo['type']])) |
||
| 1644 | $packageInfo['sort_id'] = $sort_id['unknown']; |
||
| 1645 | else |
||
| 1646 | $packageInfo['sort_id'] = $sort_id[$packageInfo['type']]; |
||
| 1647 | |||
| 1648 | $packageInfo['is_installed'] = isset($installed_mods[$packageInfo['id']]); |
||
| 1649 | $packageInfo['is_current'] = $packageInfo['is_installed'] && ($installed_mods[$packageInfo['id']]['version'] == $packageInfo['version']); |
||
| 1650 | $packageInfo['is_newer'] = $packageInfo['is_installed'] && ($installed_mods[$packageInfo['id']]['version'] > $packageInfo['version']); |
||
| 1651 | |||
| 1652 | $packageInfo['can_install'] = false; |
||
| 1653 | $packageInfo['can_uninstall'] = false; |
||
| 1654 | $packageInfo['can_upgrade'] = false; |
||
| 1655 | $packageInfo['can_emulate_install'] = false; |
||
| 1656 | $packageInfo['can_emulate_uninstall'] = false; |
||
| 1657 | |||
| 1658 | // This package is currently NOT installed. Check if it can be. |
||
| 1659 | if (!$packageInfo['is_installed'] && $packageInfo['xml']->exists('install')) |
||
| 1660 | { |
||
| 1661 | // Check if there's an install for *THIS* version of SMF. |
||
| 1662 | $installs = $packageInfo['xml']->set('install'); |
||
| 1663 | View Code Duplication | foreach ($installs as $install) |
|
| 1664 | { |
||
| 1665 | if (!$install->exists('@for') || matchPackageVersion($the_version, $install->fetch('@for'))) |
||
| 1666 | { |
||
| 1667 | // Okay, this one is good to go. |
||
| 1668 | $packageInfo['can_install'] = true; |
||
| 1669 | break; |
||
| 1670 | } |
||
| 1671 | } |
||
| 1672 | |||
| 1673 | // no install found for this version, lets see if one exists for another |
||
| 1674 | View Code Duplication | if ($packageInfo['can_install'] === false && $install->exists('@for') && empty($_SESSION['version_emulate'])) |
|
|
0 ignored issues
–
show
The variable
$install 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...
|
|||
| 1675 | { |
||
| 1676 | $reset = true; |
||
| 1677 | |||
| 1678 | // Get the highest install version that is available from the package |
||
| 1679 | foreach ($installs as $install) |
||
| 1680 | { |
||
| 1681 | $packageInfo['can_emulate_install'] = matchHighestPackageVersion($install->fetch('@for'), $reset, $the_version); |
||
| 1682 | $reset = false; |
||
| 1683 | } |
||
| 1684 | } |
||
| 1685 | } |
||
| 1686 | // An already installed, but old, package. Can we upgrade it? |
||
| 1687 | elseif ($packageInfo['is_installed'] && !$packageInfo['is_current'] && $packageInfo['xml']->exists('upgrade')) |
||
| 1688 | { |
||
| 1689 | $upgrades = $packageInfo['xml']->set('upgrade'); |
||
| 1690 | |||
| 1691 | // First go through, and check against the current version of SMF. |
||
| 1692 | foreach ($upgrades as $upgrade) |
||
| 1693 | { |
||
| 1694 | // Even if it is for this SMF, is it for the installed version of the mod? |
||
| 1695 | if (!$upgrade->exists('@for') || matchPackageVersion($the_version, $upgrade->fetch('@for'))) |
||
| 1696 | if (!$upgrade->exists('@from') || matchPackageVersion($installed_mods[$packageInfo['id']]['version'], $upgrade->fetch('@from'))) |
||
| 1697 | { |
||
| 1698 | $packageInfo['can_upgrade'] = true; |
||
| 1699 | break; |
||
| 1700 | } |
||
| 1701 | } |
||
| 1702 | } |
||
| 1703 | // Note that it has to be the current version to be uninstallable. Shucks. |
||
| 1704 | elseif ($packageInfo['is_installed'] && $packageInfo['is_current'] && $packageInfo['xml']->exists('uninstall')) |
||
| 1705 | { |
||
| 1706 | $uninstalls = $packageInfo['xml']->set('uninstall'); |
||
| 1707 | |||
| 1708 | // Can we find any uninstallation methods that work for this SMF version? |
||
| 1709 | View Code Duplication | foreach ($uninstalls as $uninstall) |
|
| 1710 | { |
||
| 1711 | if (!$uninstall->exists('@for') || matchPackageVersion($the_version, $uninstall->fetch('@for'))) |
||
| 1712 | { |
||
| 1713 | $packageInfo['can_uninstall'] = true; |
||
| 1714 | break; |
||
| 1715 | } |
||
| 1716 | } |
||
| 1717 | |||
| 1718 | // no uninstall found for this version, lets see if one exists for another |
||
| 1719 | View Code Duplication | if ($packageInfo['can_uninstall'] === false && $uninstall->exists('@for') && empty($_SESSION['version_emulate'])) |
|
|
0 ignored issues
–
show
The variable
$uninstall 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...
|
|||
| 1720 | { |
||
| 1721 | $reset = true; |
||
| 1722 | |||
| 1723 | // Get the highest install version that is available from the package |
||
| 1724 | foreach ($uninstalls as $uninstall) |
||
| 1725 | { |
||
| 1726 | $packageInfo['can_emulate_uninstall'] = matchHighestPackageVersion($uninstall->fetch('@for'), $reset, $the_version); |
||
| 1727 | $reset = false; |
||
| 1728 | } |
||
| 1729 | } |
||
| 1730 | } |
||
| 1731 | |||
| 1732 | // Modification. |
||
| 1733 | if ($packageInfo['type'] == 'modification' || $packageInfo['type'] == 'mod') |
||
| 1734 | { |
||
| 1735 | $sort_id['modification']++; |
||
| 1736 | $sort_id['mod']++; |
||
| 1737 | $packages['modification'][strtolower($packageInfo[$sort]) . '_' . $sort_id['mod']] = md5($package); |
||
| 1738 | $context['available_modification'][md5($package)] = $packageInfo; |
||
| 1739 | } |
||
| 1740 | // Avatar package. |
||
| 1741 | View Code Duplication | elseif ($packageInfo['type'] == 'avatar') |
|
| 1742 | { |
||
| 1743 | $sort_id[$packageInfo['type']]++; |
||
| 1744 | $packages['avatar'][strtolower($packageInfo[$sort])] = md5($package); |
||
| 1745 | $context['available_avatar'][md5($package)] = $packageInfo; |
||
| 1746 | } |
||
| 1747 | // Language package. |
||
| 1748 | View Code Duplication | elseif ($packageInfo['type'] == 'language') |
|
| 1749 | { |
||
| 1750 | $sort_id[$packageInfo['type']]++; |
||
| 1751 | $packages['language'][strtolower($packageInfo[$sort])] = md5($package); |
||
| 1752 | $context['available_language'][md5($package)] = $packageInfo; |
||
| 1753 | } |
||
| 1754 | // This might be a 3rd party section. |
||
| 1755 | elseif (isset($sort_id[$packageInfo['type']], $packages[$packageInfo['type']], $context['available_' . $packageInfo['type']])) |
||
| 1756 | { |
||
| 1757 | $sort_id[$packageInfo['type']]++; |
||
| 1758 | $packages[$packageInfo['type']][strtolower($packageInfo[$sort])] = md5($package); |
||
| 1759 | $context['available_' . $packageInfo['type']][md5($package)] = $packageInfo; |
||
| 1760 | } |
||
| 1761 | // Other stuff. |
||
| 1762 | else |
||
| 1763 | { |
||
| 1764 | $sort_id['unknown']++; |
||
| 1765 | $packages['unknown'][strtolower($packageInfo[$sort])] = md5($package); |
||
| 1766 | $context['available_unknown'][md5($package)] = $packageInfo; |
||
| 1767 | } |
||
| 1768 | } |
||
| 1769 | } |
||
| 1770 | closedir($dir); |
||
| 1771 | } |
||
| 1772 | |||
| 1773 | if (isset($_GET['type']) && $_GET['type'] == $params) |
||
| 1774 | { |
||
| 1775 | if (isset($_GET['desc'])) |
||
| 1776 | krsort($packages[$params]); |
||
| 1777 | else |
||
| 1778 | ksort($packages[$params]); |
||
| 1779 | } |
||
| 1780 | |||
| 1781 | return $packages[$params]; |
||
| 1782 | } |
||
| 1783 | |||
| 1784 | /** |
||
| 1785 | * Used when a temp FTP access is needed to package functions |
||
| 1786 | */ |
||
| 1787 | function PackageOptions() |
||
| 1788 | { |
||
| 1789 | global $txt, $context, $modSettings, $smcFunc; |
||
| 1790 | |||
| 1791 | if (isset($_POST['save'])) |
||
| 1792 | { |
||
| 1793 | checkSession(); |
||
| 1794 | |||
| 1795 | updateSettings(array( |
||
| 1796 | 'package_server' => trim($smcFunc['htmlspecialchars']($_POST['pack_server'])), |
||
| 1797 | 'package_port' => trim($smcFunc['htmlspecialchars']($_POST['pack_port'])), |
||
| 1798 | 'package_username' => trim($smcFunc['htmlspecialchars']($_POST['pack_user'])), |
||
| 1799 | 'package_make_backups' => !empty($_POST['package_make_backups']), |
||
| 1800 | 'package_make_full_backups' => !empty($_POST['package_make_full_backups']) |
||
| 1801 | )); |
||
| 1802 | $_SESSION['adm-save'] = true; |
||
| 1803 | |||
| 1804 | redirectexit('action=admin;area=packages;sa=options'); |
||
| 1805 | } |
||
| 1806 | |||
| 1807 | if (preg_match('~^/home\d*/([^/]+?)/public_html~', $_SERVER['DOCUMENT_ROOT'], $match)) |
||
| 1808 | $default_username = $match[1]; |
||
| 1809 | else |
||
| 1810 | $default_username = ''; |
||
| 1811 | |||
| 1812 | $context['page_title'] = $txt['package_settings']; |
||
| 1813 | $context['sub_template'] = 'install_options'; |
||
| 1814 | |||
| 1815 | $context['package_ftp_server'] = isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost'; |
||
| 1816 | $context['package_ftp_port'] = isset($modSettings['package_port']) ? $modSettings['package_port'] : '21'; |
||
| 1817 | $context['package_ftp_username'] = isset($modSettings['package_username']) ? $modSettings['package_username'] : $default_username; |
||
| 1818 | $context['package_make_backups'] = !empty($modSettings['package_make_backups']); |
||
| 1819 | $context['package_make_full_backups'] = !empty($modSettings['package_make_full_backups']); |
||
| 1820 | |||
| 1821 | if (!empty($_SESSION['adm-save'])) |
||
| 1822 | { |
||
| 1823 | $context['saved_successful'] = true; |
||
| 1824 | unset ($_SESSION['adm-save']); |
||
| 1825 | } |
||
| 1826 | } |
||
| 1827 | |||
| 1828 | /** |
||
| 1829 | * List operations |
||
| 1830 | */ |
||
| 1831 | function ViewOperations() |
||
| 1832 | { |
||
| 1833 | global $context, $txt, $sourcedir, $packagesdir, $smcFunc, $modSettings; |
||
| 1834 | |||
| 1835 | // Can't be in here buddy. |
||
| 1836 | isAllowedTo('admin_forum'); |
||
| 1837 | |||
| 1838 | // We need to know the operation key for the search and replace, mod file looking at, is it a board mod? |
||
| 1839 | if (!isset($_REQUEST['operation_key'], $_REQUEST['filename']) && !is_numeric($_REQUEST['operation_key'])) |
||
| 1840 | fatal_lang_error('operation_invalid', 'general'); |
||
| 1841 | |||
| 1842 | // Load the required file. |
||
| 1843 | require_once($sourcedir . '/Subs-Package.php'); |
||
| 1844 | |||
| 1845 | // Uninstalling the mod? |
||
| 1846 | $reverse = isset($_REQUEST['reverse']) ? true : false; |
||
| 1847 | |||
| 1848 | // Get the base name. |
||
| 1849 | $context['filename'] = preg_replace('~[\.]+~', '.', $_REQUEST['package']); |
||
| 1850 | |||
| 1851 | // We need to extract this again. |
||
| 1852 | View Code Duplication | if (is_file($packagesdir . '/' . $context['filename'])) |
|
| 1853 | { |
||
| 1854 | $context['extracted_files'] = read_tgz_file($packagesdir . '/' . $context['filename'], $packagesdir . '/temp'); |
||
| 1855 | |||
| 1856 | if ($context['extracted_files'] && !file_exists($packagesdir . '/temp/package-info.xml')) |
||
| 1857 | foreach ($context['extracted_files'] as $file) |
||
| 1858 | if (basename($file['filename']) == 'package-info.xml') |
||
| 1859 | { |
||
| 1860 | $context['base_path'] = dirname($file['filename']) . '/'; |
||
| 1861 | break; |
||
| 1862 | } |
||
| 1863 | |||
| 1864 | if (!isset($context['base_path'])) |
||
| 1865 | $context['base_path'] = ''; |
||
| 1866 | } |
||
| 1867 | elseif (is_dir($packagesdir . '/' . $context['filename'])) |
||
| 1868 | { |
||
| 1869 | copytree($packagesdir . '/' . $context['filename'], $packagesdir . '/temp'); |
||
| 1870 | $context['extracted_files'] = listtree($packagesdir . '/temp'); |
||
| 1871 | $context['base_path'] = ''; |
||
| 1872 | } |
||
| 1873 | |||
| 1874 | // Load up any custom themes we may want to install into... |
||
| 1875 | $request = $smcFunc['db_query']('', ' |
||
| 1876 | SELECT id_theme, variable, value |
||
| 1877 | FROM {db_prefix}themes |
||
| 1878 | WHERE (id_theme = {int:default_theme} OR id_theme IN ({array_int:known_theme_list})) |
||
| 1879 | AND variable IN ({string:name}, {string:theme_dir})', |
||
| 1880 | array( |
||
| 1881 | 'known_theme_list' => explode(',', $modSettings['knownThemes']), |
||
| 1882 | 'default_theme' => 1, |
||
| 1883 | 'name' => 'name', |
||
| 1884 | 'theme_dir' => 'theme_dir', |
||
| 1885 | ) |
||
| 1886 | ); |
||
| 1887 | $theme_paths = array(); |
||
| 1888 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 1889 | $theme_paths[$row['id_theme']][$row['variable']] = $row['value']; |
||
| 1890 | $smcFunc['db_free_result']($request); |
||
| 1891 | |||
| 1892 | // If we're viewing uninstall operations, only consider themes that |
||
| 1893 | // the package is actually installed into. |
||
| 1894 | if (isset($_REQUEST['reverse']) && !empty($_REQUEST['install_id'])) |
||
| 1895 | { |
||
| 1896 | $install_id = (int) $_REQUEST['install_id']; |
||
| 1897 | if ($install_id > 0) |
||
| 1898 | { |
||
| 1899 | $old_themes = array(); |
||
| 1900 | $request = $smcFunc['db_query']('', ' |
||
| 1901 | SELECT themes_installed |
||
| 1902 | FROM {db_prefix}log_packages |
||
| 1903 | WHERE id_install = {int:install_id}', |
||
| 1904 | array( |
||
| 1905 | 'install_id' => $install_id, |
||
| 1906 | ) |
||
| 1907 | ); |
||
| 1908 | |||
| 1909 | if ($smcFunc['db_num_rows']($request) == 1) |
||
| 1910 | { |
||
| 1911 | list ($old_themes) = $smcFunc['db_fetch_row']($request); |
||
| 1912 | $old_themes = explode(',', $old_themes); |
||
| 1913 | |||
| 1914 | foreach ($theme_paths as $id => $data) |
||
| 1915 | if ($id != 1 && !in_array($id, $old_themes)) |
||
| 1916 | unset($theme_paths[$id]); |
||
| 1917 | } |
||
| 1918 | $smcFunc['db_free_result']($request); |
||
| 1919 | } |
||
| 1920 | } |
||
| 1921 | |||
| 1922 | // Boardmod? |
||
| 1923 | View Code Duplication | if (isset($_REQUEST['boardmod'])) |
|
| 1924 | $mod_actions = parseBoardMod(@file_get_contents($packagesdir . '/temp/' . $context['base_path'] . $_REQUEST['filename']), true, $reverse, $theme_paths); |
||
| 1925 | else |
||
| 1926 | $mod_actions = parseModification(@file_get_contents($packagesdir . '/temp/' . $context['base_path'] . $_REQUEST['filename']), true, $reverse, $theme_paths); |
||
| 1927 | |||
| 1928 | // Ok lets get the content of the file. |
||
| 1929 | $context['operations'] = array( |
||
| 1930 | 'search' => strtr($smcFunc['htmlspecialchars']($mod_actions[$_REQUEST['operation_key']]['search_original']), array('[' => '[', ']' => ']')), |
||
| 1931 | 'replace' => strtr($smcFunc['htmlspecialchars']($mod_actions[$_REQUEST['operation_key']]['replace_original']), array('[' => '[', ']' => ']')), |
||
| 1932 | 'position' => $mod_actions[$_REQUEST['operation_key']]['position'], |
||
| 1933 | ); |
||
| 1934 | |||
| 1935 | // Let's do some formatting... |
||
| 1936 | $operation_text = $context['operations']['position'] == 'replace' ? 'operation_replace' : ($context['operations']['position'] == 'before' ? 'operation_after' : 'operation_before'); |
||
| 1937 | $context['operations']['search'] = parse_bbc('[code=' . $txt['operation_find'] . ']' . ($context['operations']['position'] == 'end' ? '?>' : $context['operations']['search']) . '[/code]'); |
||
| 1938 | $context['operations']['replace'] = parse_bbc('[code=' . $txt[$operation_text] . ']' . $context['operations']['replace'] . '[/code]'); |
||
| 1939 | |||
| 1940 | // No layers |
||
| 1941 | $context['template_layers'] = array(); |
||
| 1942 | $context['sub_template'] = 'view_operations'; |
||
| 1943 | } |
||
| 1944 | |||
| 1945 | /** |
||
| 1946 | * Allow the admin to reset permissions on files. |
||
| 1947 | */ |
||
| 1948 | function PackagePermissions() |
||
| 1949 | { |
||
| 1950 | global $context, $txt, $modSettings, $boarddir, $sourcedir, $cachedir, $smcFunc, $package_ftp; |
||
| 1951 | |||
| 1952 | // Let's try and be good, yes? |
||
| 1953 | checkSession('get'); |
||
| 1954 | |||
| 1955 | // If we're restoring permissions this is just a pass through really. |
||
| 1956 | if (isset($_GET['restore'])) |
||
| 1957 | { |
||
| 1958 | create_chmod_control(array(), array(), true); |
||
| 1959 | fatal_lang_error('no_access', false); |
||
| 1960 | } |
||
| 1961 | |||
| 1962 | // This is a memory eat. |
||
| 1963 | setMemoryLimit('128M'); |
||
| 1964 | @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...
|
|||
| 1965 | |||
| 1966 | // Load up some FTP stuff. |
||
| 1967 | create_chmod_control(); |
||
| 1968 | |||
| 1969 | if (empty($package_ftp) && !isset($_POST['skip_ftp'])) |
||
| 1970 | { |
||
| 1971 | require_once($sourcedir . '/Class-Package.php'); |
||
| 1972 | $ftp = new ftp_connection(null); |
||
| 1973 | list ($username, $detect_path, $found_path) = $ftp->detect_path($boarddir); |
||
| 1974 | |||
| 1975 | $context['package_ftp'] = array( |
||
| 1976 | 'server' => isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost', |
||
| 1977 | 'port' => isset($modSettings['package_port']) ? $modSettings['package_port'] : '21', |
||
| 1978 | 'username' => empty($username) ? (isset($modSettings['package_username']) ? $modSettings['package_username'] : '') : $username, |
||
| 1979 | 'path' => $detect_path, |
||
| 1980 | 'form_elements_only' => true, |
||
| 1981 | ); |
||
| 1982 | } |
||
| 1983 | else |
||
| 1984 | $context['ftp_connected'] = true; |
||
| 1985 | |||
| 1986 | // Define the template. |
||
| 1987 | $context['page_title'] = $txt['package_file_perms']; |
||
| 1988 | $context['sub_template'] = 'file_permissions'; |
||
| 1989 | |||
| 1990 | // Define what files we're interested in, as a tree. |
||
| 1991 | $context['file_tree'] = array( |
||
| 1992 | strtr($boarddir, array('\\' => '/')) => array( |
||
| 1993 | 'type' => 'dir', |
||
| 1994 | 'contents' => array( |
||
| 1995 | 'agreement.txt' => array( |
||
| 1996 | 'type' => 'file', |
||
| 1997 | 'writable_on' => 'standard', |
||
| 1998 | ), |
||
| 1999 | 'Settings.php' => array( |
||
| 2000 | 'type' => 'file', |
||
| 2001 | 'writable_on' => 'restrictive', |
||
| 2002 | ), |
||
| 2003 | 'Settings_bak.php' => array( |
||
| 2004 | 'type' => 'file', |
||
| 2005 | 'writable_on' => 'restrictive', |
||
| 2006 | ), |
||
| 2007 | 'attachments' => array( |
||
| 2008 | 'type' => 'dir', |
||
| 2009 | 'writable_on' => 'restrictive', |
||
| 2010 | ), |
||
| 2011 | 'avatars' => array( |
||
| 2012 | 'type' => 'dir', |
||
| 2013 | 'writable_on' => 'standard', |
||
| 2014 | ), |
||
| 2015 | 'cache' => array( |
||
| 2016 | 'type' => 'dir', |
||
| 2017 | 'writable_on' => 'restrictive', |
||
| 2018 | ), |
||
| 2019 | 'custom_avatar_dir' => array( |
||
| 2020 | 'type' => 'dir', |
||
| 2021 | 'writable_on' => 'restrictive', |
||
| 2022 | ), |
||
| 2023 | 'Smileys' => array( |
||
| 2024 | 'type' => 'dir_recursive', |
||
| 2025 | 'writable_on' => 'standard', |
||
| 2026 | ), |
||
| 2027 | 'Sources' => array( |
||
| 2028 | 'type' => 'dir_recursive', |
||
| 2029 | 'list_contents' => true, |
||
| 2030 | 'writable_on' => 'standard', |
||
| 2031 | 'contents' => array( |
||
| 2032 | 'tasks' => array( |
||
| 2033 | 'type' => 'dir', |
||
| 2034 | 'list_contents' => true, |
||
| 2035 | ), |
||
| 2036 | ), |
||
| 2037 | ), |
||
| 2038 | 'Themes' => array( |
||
| 2039 | 'type' => 'dir_recursive', |
||
| 2040 | 'writable_on' => 'standard', |
||
| 2041 | 'contents' => array( |
||
| 2042 | 'default' => array( |
||
| 2043 | 'type' => 'dir_recursive', |
||
| 2044 | 'list_contents' => true, |
||
| 2045 | 'contents' => array( |
||
| 2046 | 'languages' => array( |
||
| 2047 | 'type' => 'dir', |
||
| 2048 | 'list_contents' => true, |
||
| 2049 | ), |
||
| 2050 | ), |
||
| 2051 | ), |
||
| 2052 | ), |
||
| 2053 | ), |
||
| 2054 | 'Packages' => array( |
||
| 2055 | 'type' => 'dir', |
||
| 2056 | 'writable_on' => 'standard', |
||
| 2057 | 'contents' => array( |
||
| 2058 | 'temp' => array( |
||
| 2059 | 'type' => 'dir', |
||
| 2060 | ), |
||
| 2061 | 'backup' => array( |
||
| 2062 | 'type' => 'dir', |
||
| 2063 | ), |
||
| 2064 | ), |
||
| 2065 | ), |
||
| 2066 | ), |
||
| 2067 | ), |
||
| 2068 | ); |
||
| 2069 | |||
| 2070 | // Directories that can move. |
||
| 2071 | if (substr($sourcedir, 0, strlen($boarddir)) != $boarddir) |
||
| 2072 | { |
||
| 2073 | unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Sources']); |
||
| 2074 | $context['file_tree'][strtr($sourcedir, array('\\' => '/'))] = array( |
||
| 2075 | 'type' => 'dir', |
||
| 2076 | 'list_contents' => true, |
||
| 2077 | 'writable_on' => 'standard', |
||
| 2078 | ); |
||
| 2079 | } |
||
| 2080 | |||
| 2081 | // Moved the cache? |
||
| 2082 | if (substr($cachedir, 0, strlen($boarddir)) != $boarddir) |
||
| 2083 | { |
||
| 2084 | unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['cache']); |
||
| 2085 | $context['file_tree'][strtr($cachedir, array('\\' => '/'))] = array( |
||
| 2086 | 'type' => 'dir', |
||
| 2087 | 'list_contents' => false, |
||
| 2088 | 'writable_on' => 'restrictive', |
||
| 2089 | ); |
||
| 2090 | } |
||
| 2091 | |||
| 2092 | // Are we using multiple attachment directories? |
||
| 2093 | if (!empty($modSettings['currentAttachmentUploadDir'])) |
||
| 2094 | { |
||
| 2095 | unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['attachments']); |
||
| 2096 | |||
| 2097 | if (!is_array($modSettings['attachmentUploadDir'])) |
||
| 2098 | $modSettings['attachmentUploadDir'] = $smcFunc['json_decode']($modSettings['attachmentUploadDir'], true); |
||
| 2099 | |||
| 2100 | // @todo Should we suggest non-current directories be read only? |
||
| 2101 | foreach ($modSettings['attachmentUploadDir'] as $dir) |
||
| 2102 | $context['file_tree'][strtr($dir, array('\\' => '/'))] = array( |
||
| 2103 | 'type' => 'dir', |
||
| 2104 | 'writable_on' => 'restrictive', |
||
| 2105 | ); |
||
| 2106 | |||
| 2107 | } |
||
| 2108 | View Code Duplication | elseif (substr($modSettings['attachmentUploadDir'], 0, strlen($boarddir)) != $boarddir) |
|
| 2109 | { |
||
| 2110 | unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['attachments']); |
||
| 2111 | $context['file_tree'][strtr($modSettings['attachmentUploadDir'], array('\\' => '/'))] = array( |
||
| 2112 | 'type' => 'dir', |
||
| 2113 | 'writable_on' => 'restrictive', |
||
| 2114 | ); |
||
| 2115 | } |
||
| 2116 | |||
| 2117 | View Code Duplication | if (substr($modSettings['smileys_dir'], 0, strlen($boarddir)) != $boarddir) |
|
| 2118 | { |
||
| 2119 | unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Smileys']); |
||
| 2120 | $context['file_tree'][strtr($modSettings['smileys_dir'], array('\\' => '/'))] = array( |
||
| 2121 | 'type' => 'dir_recursive', |
||
| 2122 | 'writable_on' => 'standard', |
||
| 2123 | ); |
||
| 2124 | } |
||
| 2125 | View Code Duplication | if (substr($modSettings['avatar_directory'], 0, strlen($boarddir)) != $boarddir) |
|
| 2126 | { |
||
| 2127 | unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['avatars']); |
||
| 2128 | $context['file_tree'][strtr($modSettings['avatar_directory'], array('\\' => '/'))] = array( |
||
| 2129 | 'type' => 'dir', |
||
| 2130 | 'writable_on' => 'standard', |
||
| 2131 | ); |
||
| 2132 | } |
||
| 2133 | View Code Duplication | if (isset($modSettings['custom_avatar_dir']) && substr($modSettings['custom_avatar_dir'], 0, strlen($boarddir)) != $boarddir) |
|
| 2134 | { |
||
| 2135 | unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['custom_avatar_dir']); |
||
| 2136 | $context['file_tree'][strtr($modSettings['custom_avatar_dir'], array('\\' => '/'))] = array( |
||
| 2137 | 'type' => 'dir', |
||
| 2138 | 'writable_on' => 'restrictive', |
||
| 2139 | ); |
||
| 2140 | } |
||
| 2141 | |||
| 2142 | // Load up any custom themes. |
||
| 2143 | $request = $smcFunc['db_query']('', ' |
||
| 2144 | SELECT value |
||
| 2145 | FROM {db_prefix}themes |
||
| 2146 | WHERE id_theme > {int:default_theme_id} |
||
| 2147 | AND id_member = {int:guest_id} |
||
| 2148 | AND variable = {string:theme_dir} |
||
| 2149 | ORDER BY value ASC', |
||
| 2150 | array( |
||
| 2151 | 'default_theme_id' => 1, |
||
| 2152 | 'guest_id' => 0, |
||
| 2153 | 'theme_dir' => 'theme_dir', |
||
| 2154 | ) |
||
| 2155 | ); |
||
| 2156 | while ($row = $smcFunc['db_fetch_assoc']($request)) |
||
| 2157 | { |
||
| 2158 | if (substr(strtolower(strtr($row['value'], array('\\' => '/'))), 0, strlen($boarddir) + 7) == strtolower(strtr($boarddir, array('\\' => '/')) . '/Themes')) |
||
| 2159 | $context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Themes']['contents'][substr($row['value'], strlen($boarddir) + 8)] = array( |
||
| 2160 | 'type' => 'dir_recursive', |
||
| 2161 | 'list_contents' => true, |
||
| 2162 | 'contents' => array( |
||
| 2163 | 'languages' => array( |
||
| 2164 | 'type' => 'dir', |
||
| 2165 | 'list_contents' => true, |
||
| 2166 | ), |
||
| 2167 | ), |
||
| 2168 | ); |
||
| 2169 | else |
||
| 2170 | { |
||
| 2171 | $context['file_tree'][strtr($row['value'], array('\\' => '/'))] = array( |
||
| 2172 | 'type' => 'dir_recursive', |
||
| 2173 | 'list_contents' => true, |
||
| 2174 | 'contents' => array( |
||
| 2175 | 'languages' => array( |
||
| 2176 | 'type' => 'dir', |
||
| 2177 | 'list_contents' => true, |
||
| 2178 | ), |
||
| 2179 | ), |
||
| 2180 | ); |
||
| 2181 | } |
||
| 2182 | } |
||
| 2183 | $smcFunc['db_free_result']($request); |
||
| 2184 | |||
| 2185 | // If we're submitting then let's move on to another function to keep things cleaner.. |
||
| 2186 | if (isset($_POST['action_changes'])) |
||
| 2187 | return PackagePermissionsAction(); |
||
| 2188 | |||
| 2189 | $context['look_for'] = array(); |
||
| 2190 | // Are we looking for a particular tree - normally an expansion? |
||
| 2191 | if (!empty($_REQUEST['find'])) |
||
| 2192 | $context['look_for'][] = base64_decode($_REQUEST['find']); |
||
| 2193 | // Only that tree? |
||
| 2194 | $context['only_find'] = isset($_GET['xml']) && !empty($_REQUEST['onlyfind']) ? $_REQUEST['onlyfind'] : ''; |
||
| 2195 | if ($context['only_find']) |
||
| 2196 | $context['look_for'][] = $context['only_find']; |
||
| 2197 | |||
| 2198 | // Have we got a load of back-catalogue trees to expand from a submit etc? |
||
| 2199 | if (!empty($_GET['back_look'])) |
||
| 2200 | { |
||
| 2201 | $potententialTrees = $smcFunc['json_decode'](base64_decode($_GET['back_look']), true); |
||
| 2202 | foreach ($potententialTrees as $tree) |
||
| 2203 | $context['look_for'][] = $tree; |
||
| 2204 | } |
||
| 2205 | // ... maybe posted? |
||
| 2206 | if (!empty($_POST['back_look'])) |
||
| 2207 | $context['only_find'] = array_merge($context['only_find'], $_POST['back_look']); |
||
| 2208 | |||
| 2209 | $context['back_look_data'] = base64_encode($smcFunc['json_encode'](array_slice($context['look_for'], 0, 15))); |
||
| 2210 | |||
| 2211 | // Are we finding more files than first thought? |
||
| 2212 | $context['file_offset'] = !empty($_REQUEST['fileoffset']) ? (int) $_REQUEST['fileoffset'] : 0; |
||
| 2213 | // Don't list more than this many files in a directory. |
||
| 2214 | $context['file_limit'] = 150; |
||
| 2215 | |||
| 2216 | // How many levels shall we show? |
||
| 2217 | $context['default_level'] = empty($context['only_find']) ? 2 : 25; |
||
| 2218 | |||
| 2219 | // This will be used if we end up catching XML data. |
||
| 2220 | $context['xml_data'] = array( |
||
| 2221 | 'roots' => array( |
||
| 2222 | 'identifier' => 'root', |
||
| 2223 | 'children' => array( |
||
| 2224 | array( |
||
| 2225 | 'value' => preg_replace('~[^A-Za-z0-9_\-=:]~', ':-:', $context['only_find']), |
||
| 2226 | ), |
||
| 2227 | ), |
||
| 2228 | ), |
||
| 2229 | 'folders' => array( |
||
| 2230 | 'identifier' => 'folder', |
||
| 2231 | 'children' => array(), |
||
| 2232 | ), |
||
| 2233 | ); |
||
| 2234 | |||
| 2235 | foreach ($context['file_tree'] as $path => $data) |
||
| 2236 | { |
||
| 2237 | // Run this directory. |
||
| 2238 | if (file_exists($path) && (empty($context['only_find']) || substr($context['only_find'], 0, strlen($path)) == $path)) |
||
| 2239 | { |
||
| 2240 | // Get the first level down only. |
||
| 2241 | fetchPerms__recursive($path, $context['file_tree'][$path], 1); |
||
| 2242 | $context['file_tree'][$path]['perms'] = array( |
||
| 2243 | 'chmod' => @is_writable($path), |
||
| 2244 | 'perms' => @fileperms($path), |
||
| 2245 | ); |
||
| 2246 | } |
||
| 2247 | else |
||
| 2248 | unset($context['file_tree'][$path]); |
||
| 2249 | } |
||
| 2250 | |||
| 2251 | // Is this actually xml? |
||
| 2252 | if (isset($_GET['xml'])) |
||
| 2253 | { |
||
| 2254 | loadTemplate('Xml'); |
||
| 2255 | $context['sub_template'] = 'generic_xml'; |
||
| 2256 | $context['template_layers'] = array(); |
||
| 2257 | } |
||
| 2258 | } |
||
| 2259 | |||
| 2260 | /** |
||
| 2261 | * Checkes the permissions of all the areas that will be affected by the package |
||
| 2262 | * |
||
| 2263 | * @param string $path The path to the directiory to check permissions for |
||
| 2264 | * @param array $data An array of data about the directory |
||
| 2265 | * @param int $level How far deep to go |
||
| 2266 | */ |
||
| 2267 | function fetchPerms__recursive($path, &$data, $level) |
||
| 2268 | { |
||
| 2269 | global $context; |
||
| 2270 | |||
| 2271 | $isLikelyPath = false; |
||
| 2272 | foreach ($context['look_for'] as $possiblePath) |
||
| 2273 | if (substr($possiblePath, 0, strlen($path)) == $path) |
||
| 2274 | $isLikelyPath = true; |
||
| 2275 | |||
| 2276 | // Is this where we stop? |
||
| 2277 | if (isset($_GET['xml']) && !empty($context['look_for']) && !$isLikelyPath) |
||
| 2278 | return; |
||
| 2279 | elseif ($level > $context['default_level'] && !$isLikelyPath) |
||
| 2280 | return; |
||
| 2281 | |||
| 2282 | // Are we actually interested in saving this data? |
||
| 2283 | $save_data = empty($context['only_find']) || $context['only_find'] == $path; |
||
| 2284 | |||
| 2285 | // @todo Shouldn't happen - but better error message? |
||
| 2286 | if (!is_dir($path)) |
||
| 2287 | fatal_lang_error('no_access', false); |
||
| 2288 | |||
| 2289 | // This is where we put stuff we've found for sorting. |
||
| 2290 | $foundData = array( |
||
| 2291 | 'files' => array(), |
||
| 2292 | 'folders' => array(), |
||
| 2293 | ); |
||
| 2294 | |||
| 2295 | $dh = opendir($path); |
||
| 2296 | while ($entry = readdir($dh)) |
||
| 2297 | { |
||
| 2298 | // Some kind of file? |
||
| 2299 | if (is_file($path . '/' . $entry)) |
||
| 2300 | { |
||
| 2301 | // Are we listing PHP files in this directory? |
||
| 2302 | if ($save_data && !empty($data['list_contents']) && substr($entry, -4) == '.php') |
||
| 2303 | $foundData['files'][$entry] = true; |
||
| 2304 | // A file we were looking for. |
||
| 2305 | elseif ($save_data && isset($data['contents'][$entry])) |
||
| 2306 | $foundData['files'][$entry] = true; |
||
| 2307 | } |
||
| 2308 | // It's a directory - we're interested one way or another, probably... |
||
| 2309 | elseif ($entry != '.' && $entry != '..') |
||
| 2310 | { |
||
| 2311 | // Going further? |
||
| 2312 | if ((!empty($data['type']) && $data['type'] == 'dir_recursive') || (isset($data['contents'][$entry]) && (!empty($data['contents'][$entry]['list_contents']) || (!empty($data['contents'][$entry]['type']) && $data['contents'][$entry]['type'] == 'dir_recursive')))) |
||
| 2313 | { |
||
| 2314 | if (!isset($data['contents'][$entry])) |
||
| 2315 | $foundData['folders'][$entry] = 'dir_recursive'; |
||
| 2316 | else |
||
| 2317 | $foundData['folders'][$entry] = true; |
||
| 2318 | |||
| 2319 | // If this wasn't expected inherit the recusiveness... |
||
| 2320 | if (!isset($data['contents'][$entry])) |
||
| 2321 | // We need to do this as we will be going all recursive. |
||
| 2322 | $data['contents'][$entry] = array( |
||
| 2323 | 'type' => 'dir_recursive', |
||
| 2324 | ); |
||
| 2325 | |||
| 2326 | // Actually do the recursive stuff... |
||
| 2327 | fetchPerms__recursive($path . '/' . $entry, $data['contents'][$entry], $level + 1); |
||
| 2328 | } |
||
| 2329 | // Maybe it is a folder we are not descending into. |
||
| 2330 | elseif (isset($data['contents'][$entry])) |
||
| 2331 | $foundData['folders'][$entry] = true; |
||
| 2332 | // Otherwise we stop here. |
||
| 2333 | } |
||
| 2334 | } |
||
| 2335 | closedir($dh); |
||
| 2336 | |||
| 2337 | // Nothing to see here? |
||
| 2338 | if (!$save_data) |
||
| 2339 | return; |
||
| 2340 | |||
| 2341 | // Now actually add the data, starting with the folders. |
||
| 2342 | ksort($foundData['folders']); |
||
| 2343 | foreach ($foundData['folders'] as $folder => $type) |
||
| 2344 | { |
||
| 2345 | $additional_data = array( |
||
| 2346 | 'perms' => array( |
||
| 2347 | 'chmod' => @is_writable($path . '/' . $folder), |
||
| 2348 | 'perms' => @fileperms($path . '/' . $folder), |
||
| 2349 | ), |
||
| 2350 | ); |
||
| 2351 | if ($type !== true) |
||
| 2352 | $additional_data['type'] = $type; |
||
| 2353 | |||
| 2354 | // If there's an offset ignore any folders in XML mode. |
||
| 2355 | if (isset($_GET['xml']) && $context['file_offset'] == 0) |
||
| 2356 | { |
||
| 2357 | $context['xml_data']['folders']['children'][] = array( |
||
| 2358 | 'attributes' => array( |
||
| 2359 | 'writable' => $additional_data['perms']['chmod'] ? 1 : 0, |
||
| 2360 | 'permissions' => substr(sprintf('%o', $additional_data['perms']['perms']), -4), |
||
| 2361 | 'folder' => 1, |
||
| 2362 | 'path' => $context['only_find'], |
||
| 2363 | 'level' => $level, |
||
| 2364 | 'more' => 0, |
||
| 2365 | 'offset' => $context['file_offset'], |
||
| 2366 | 'my_ident' => preg_replace('~[^A-Za-z0-9_\-=:]~', ':-:', $context['only_find'] . '/' . $folder), |
||
| 2367 | 'ident' => preg_replace('~[^A-Za-z0-9_\-=:]~', ':-:', $context['only_find']), |
||
| 2368 | ), |
||
| 2369 | 'value' => $folder, |
||
| 2370 | ); |
||
| 2371 | } |
||
| 2372 | View Code Duplication | elseif (!isset($_GET['xml'])) |
|
| 2373 | { |
||
| 2374 | if (isset($data['contents'][$folder])) |
||
| 2375 | $data['contents'][$folder] = array_merge($data['contents'][$folder], $additional_data); |
||
| 2376 | else |
||
| 2377 | $data['contents'][$folder] = $additional_data; |
||
| 2378 | } |
||
| 2379 | } |
||
| 2380 | |||
| 2381 | // Now we want to do a similar thing with files. |
||
| 2382 | ksort($foundData['files']); |
||
| 2383 | $counter = -1; |
||
| 2384 | foreach ($foundData['files'] as $file => $dummy) |
||
| 2385 | { |
||
| 2386 | $counter++; |
||
| 2387 | |||
| 2388 | // Have we reached our offset? |
||
| 2389 | if ($context['file_offset'] > $counter) |
||
| 2390 | continue; |
||
| 2391 | // Gone too far? |
||
| 2392 | if ($counter > ($context['file_offset'] + $context['file_limit'])) |
||
| 2393 | continue; |
||
| 2394 | |||
| 2395 | $additional_data = array( |
||
| 2396 | 'perms' => array( |
||
| 2397 | 'chmod' => @is_writable($path . '/' . $file), |
||
| 2398 | 'perms' => @fileperms($path . '/' . $file), |
||
| 2399 | ), |
||
| 2400 | ); |
||
| 2401 | |||
| 2402 | // XML? |
||
| 2403 | if (isset($_GET['xml'])) |
||
| 2404 | { |
||
| 2405 | $context['xml_data']['folders']['children'][] = array( |
||
| 2406 | 'attributes' => array( |
||
| 2407 | 'writable' => $additional_data['perms']['chmod'] ? 1 : 0, |
||
| 2408 | 'permissions' => substr(sprintf('%o', $additional_data['perms']['perms']), -4), |
||
| 2409 | 'folder' => 0, |
||
| 2410 | 'path' => $context['only_find'], |
||
| 2411 | 'level' => $level, |
||
| 2412 | 'more' => $counter == ($context['file_offset'] + $context['file_limit']) ? 1 : 0, |
||
| 2413 | 'offset' => $context['file_offset'], |
||
| 2414 | 'my_ident' => preg_replace('~[^A-Za-z0-9_\-=:]~', ':-:', $context['only_find'] . '/' . $file), |
||
| 2415 | 'ident' => preg_replace('~[^A-Za-z0-9_\-=:]~', ':-:', $context['only_find']), |
||
| 2416 | ), |
||
| 2417 | 'value' => $file, |
||
| 2418 | ); |
||
| 2419 | } |
||
| 2420 | elseif ($counter != ($context['file_offset'] + $context['file_limit'])) |
||
| 2421 | { |
||
| 2422 | View Code Duplication | if (isset($data['contents'][$file])) |
|
| 2423 | $data['contents'][$file] = array_merge($data['contents'][$file], $additional_data); |
||
| 2424 | else |
||
| 2425 | $data['contents'][$file] = $additional_data; |
||
| 2426 | } |
||
| 2427 | } |
||
| 2428 | } |
||
| 2429 | |||
| 2430 | /** |
||
| 2431 | * Actually action the permission changes they want. |
||
| 2432 | */ |
||
| 2433 | function PackagePermissionsAction() |
||
| 2434 | { |
||
| 2435 | global $smcFunc, $context, $txt, $time_start, $package_ftp; |
||
| 2436 | |||
| 2437 | umask(0); |
||
| 2438 | |||
| 2439 | $timeout_limit = 5; |
||
| 2440 | |||
| 2441 | $context['method'] = $_POST['method'] == 'individual' ? 'individual' : 'predefined'; |
||
| 2442 | $context['sub_template'] = 'action_permissions'; |
||
| 2443 | $context['page_title'] = $txt['package_file_perms_applying']; |
||
| 2444 | $context['back_look_data'] = isset($_POST['back_look']) ? $_POST['back_look'] : array(); |
||
| 2445 | |||
| 2446 | // Skipping use of FTP? |
||
| 2447 | if (empty($package_ftp)) |
||
| 2448 | $context['skip_ftp'] = true; |
||
| 2449 | |||
| 2450 | // We'll start off in a good place, security. Make sure that if we're dealing with individual files that they seem in the right place. |
||
| 2451 | if ($context['method'] == 'individual') |
||
| 2452 | { |
||
| 2453 | // Only these path roots are legal. |
||
| 2454 | $legal_roots = array_keys($context['file_tree']); |
||
| 2455 | $context['custom_value'] = (int) $_POST['custom_value']; |
||
| 2456 | |||
| 2457 | // Continuing? |
||
| 2458 | if (isset($_POST['toProcess'])) |
||
| 2459 | $_POST['permStatus'] = $smcFunc['json_decode'](base64_decode($_POST['toProcess']), true); |
||
| 2460 | |||
| 2461 | if (isset($_POST['permStatus'])) |
||
| 2462 | { |
||
| 2463 | $context['to_process'] = array(); |
||
| 2464 | $validate_custom = false; |
||
| 2465 | foreach ($_POST['permStatus'] as $path => $status) |
||
| 2466 | { |
||
| 2467 | // Nothing to see here? |
||
| 2468 | if ($status == 'no_change') |
||
| 2469 | continue; |
||
| 2470 | $legal = false; |
||
| 2471 | foreach ($legal_roots as $root) |
||
| 2472 | if (substr($path, 0, strlen($root)) == $root) |
||
| 2473 | $legal = true; |
||
| 2474 | |||
| 2475 | if (!$legal) |
||
| 2476 | continue; |
||
| 2477 | |||
| 2478 | // Check it exists. |
||
| 2479 | if (!file_exists($path)) |
||
| 2480 | continue; |
||
| 2481 | |||
| 2482 | if ($status == 'custom') |
||
| 2483 | $validate_custom = true; |
||
| 2484 | |||
| 2485 | // Now add it. |
||
| 2486 | $context['to_process'][$path] = $status; |
||
| 2487 | } |
||
| 2488 | $context['total_items'] = isset($_POST['totalItems']) ? (int) $_POST['totalItems'] : count($context['to_process']); |
||
| 2489 | |||
| 2490 | // Make sure the chmod status is valid? |
||
| 2491 | if ($validate_custom) |
||
| 2492 | { |
||
| 2493 | if (preg_match('~^[4567][4567][4567]$~', $context['custom_value']) == false) |
||
|
0 ignored issues
–
show
|
|||
| 2494 | fatal_error($txt['chmod_value_invalid']); |
||
| 2495 | } |
||
| 2496 | |||
| 2497 | // Nothing to do? |
||
| 2498 | if (empty($context['to_process'])) |
||
| 2499 | redirectexit('action=admin;area=packages;sa=perms' . (!empty($context['back_look_data']) ? ';back_look=' . base64_encode($smcFunc['json_encode']($context['back_look_data'])) : '') . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 2500 | } |
||
| 2501 | // Should never get here, |
||
| 2502 | else |
||
| 2503 | fatal_lang_error('no_access', false); |
||
| 2504 | |||
| 2505 | // Setup the custom value. |
||
| 2506 | $custom_value = octdec('0' . $context['custom_value']); |
||
| 2507 | |||
| 2508 | // Start processing items. |
||
| 2509 | foreach ($context['to_process'] as $path => $status) |
||
| 2510 | { |
||
| 2511 | if (in_array($status, array('execute', 'writable', 'read'))) |
||
| 2512 | package_chmod($path, $status); |
||
| 2513 | elseif ($status == 'custom' && !empty($custom_value)) |
||
| 2514 | { |
||
| 2515 | // Use FTP if we have it. |
||
| 2516 | if (!empty($package_ftp) && !empty($_SESSION['pack_ftp'])) |
||
| 2517 | { |
||
| 2518 | $ftp_file = strtr($path, array($_SESSION['pack_ftp']['root'] => '')); |
||
| 2519 | $package_ftp->chmod($ftp_file, $custom_value); |
||
| 2520 | } |
||
| 2521 | else |
||
| 2522 | smf_chmod($path, $custom_value); |
||
| 2523 | } |
||
| 2524 | |||
| 2525 | // This fish is fried... |
||
| 2526 | unset($context['to_process'][$path]); |
||
| 2527 | |||
| 2528 | // See if we're out of time? |
||
| 2529 | if (time() - array_sum(explode(' ', $time_start)) > $timeout_limit) |
||
| 2530 | { |
||
| 2531 | // Prepare template usage for to_process. |
||
| 2532 | $context['to_process_encode'] = base64_encode($smcFunc['json_encode']($context['to_process'])); |
||
| 2533 | |||
| 2534 | return false; |
||
| 2535 | } |
||
| 2536 | } |
||
| 2537 | |||
| 2538 | // Prepare template usage for to_process. |
||
| 2539 | $context['to_process_encode'] = base64_encode($smcFunc['json_encode']($context['to_process'])); |
||
| 2540 | } |
||
| 2541 | // If predefined this is a little different. |
||
| 2542 | else |
||
| 2543 | { |
||
| 2544 | $context['predefined_type'] = isset($_POST['predefined']) ? $_POST['predefined'] : 'restricted'; |
||
| 2545 | |||
| 2546 | $context['total_items'] = isset($_POST['totalItems']) ? (int) $_POST['totalItems'] : 0; |
||
| 2547 | $context['directory_list'] = isset($_POST['dirList']) ? $smcFunc['json_decode'](base64_decode($_POST['dirList']), true) : array(); |
||
| 2548 | |||
| 2549 | $context['file_offset'] = isset($_POST['fileOffset']) ? (int) $_POST['fileOffset'] : 0; |
||
| 2550 | |||
| 2551 | // Haven't counted the items yet? |
||
| 2552 | if (empty($context['total_items'])) |
||
| 2553 | { |
||
| 2554 | /** |
||
| 2555 | * Counts all the directories under a given path |
||
| 2556 | * |
||
| 2557 | * @param type $dir |
||
| 2558 | * @return integer |
||
| 2559 | */ |
||
| 2560 | function count_directories__recursive($dir) |
||
| 2561 | { |
||
| 2562 | global $context; |
||
| 2563 | |||
| 2564 | $count = 0; |
||
| 2565 | $dh = @opendir($dir); |
||
| 2566 | while ($entry = readdir($dh)) |
||
| 2567 | { |
||
| 2568 | if ($entry != '.' && $entry != '..' && is_dir($dir . '/' . $entry)) |
||
| 2569 | { |
||
| 2570 | $context['directory_list'][$dir . '/' . $entry] = 1; |
||
| 2571 | $count++; |
||
| 2572 | $count += count_directories__recursive($dir . '/' . $entry); |
||
| 2573 | } |
||
| 2574 | } |
||
| 2575 | closedir($dh); |
||
| 2576 | |||
| 2577 | return $count; |
||
| 2578 | } |
||
| 2579 | |||
| 2580 | foreach ($context['file_tree'] as $path => $data) |
||
| 2581 | { |
||
| 2582 | if (is_dir($path)) |
||
| 2583 | { |
||
| 2584 | $context['directory_list'][$path] = 1; |
||
| 2585 | $context['total_items'] += count_directories__recursive($path); |
||
| 2586 | $context['total_items']++; |
||
| 2587 | } |
||
| 2588 | } |
||
| 2589 | } |
||
| 2590 | |||
| 2591 | // Have we built up our list of special files? |
||
| 2592 | if (!isset($_POST['specialFiles']) && $context['predefined_type'] != 'free') |
||
| 2593 | { |
||
| 2594 | $context['special_files'] = array(); |
||
| 2595 | |||
| 2596 | /** |
||
| 2597 | * Builds a list of special files recursively for a given path |
||
| 2598 | * |
||
| 2599 | * @param type $path |
||
| 2600 | * @param type $data |
||
| 2601 | */ |
||
| 2602 | function build_special_files__recursive($path, &$data) |
||
| 2603 | { |
||
| 2604 | global $context; |
||
| 2605 | |||
| 2606 | if (!empty($data['writable_on'])) |
||
| 2607 | if ($context['predefined_type'] == 'standard' || $data['writable_on'] == 'restrictive') |
||
| 2608 | $context['special_files'][$path] = 1; |
||
| 2609 | |||
| 2610 | if (!empty($data['contents'])) |
||
| 2611 | foreach ($data['contents'] as $name => $contents) |
||
| 2612 | build_special_files__recursive($path . '/' . $name, $contents); |
||
| 2613 | } |
||
| 2614 | |||
| 2615 | foreach ($context['file_tree'] as $path => $data) |
||
| 2616 | build_special_files__recursive($path, $data); |
||
| 2617 | } |
||
| 2618 | // Free doesn't need special files. |
||
| 2619 | elseif ($context['predefined_type'] == 'free') |
||
| 2620 | $context['special_files'] = array(); |
||
| 2621 | else |
||
| 2622 | $context['special_files'] = $smcFunc['json_decode'](base64_decode($_POST['specialFiles']), true); |
||
| 2623 | |||
| 2624 | // Now we definitely know where we are, we need to go through again doing the chmod! |
||
| 2625 | foreach ($context['directory_list'] as $path => $dummy) |
||
| 2626 | { |
||
| 2627 | // Do the contents of the directory first. |
||
| 2628 | $dh = @opendir($path); |
||
| 2629 | $file_count = 0; |
||
| 2630 | $dont_chmod = false; |
||
| 2631 | while ($entry = readdir($dh)) |
||
| 2632 | { |
||
| 2633 | $file_count++; |
||
| 2634 | // Actually process this file? |
||
| 2635 | if (!$dont_chmod && !is_dir($path . '/' . $entry) && (empty($context['file_offset']) || $context['file_offset'] < $file_count)) |
||
| 2636 | { |
||
| 2637 | $status = $context['predefined_type'] == 'free' || isset($context['special_files'][$path . '/' . $entry]) ? 'writable' : 'execute'; |
||
| 2638 | package_chmod($path . '/' . $entry, $status); |
||
| 2639 | } |
||
| 2640 | |||
| 2641 | // See if we're out of time? |
||
| 2642 | if (!$dont_chmod && time() - array_sum(explode(' ', $time_start)) > $timeout_limit) |
||
| 2643 | { |
||
| 2644 | $dont_chmod = true; |
||
| 2645 | // Don't do this again. |
||
| 2646 | $context['file_offset'] = $file_count; |
||
| 2647 | } |
||
| 2648 | } |
||
| 2649 | closedir($dh); |
||
| 2650 | |||
| 2651 | // If this is set it means we timed out half way through. |
||
| 2652 | if ($dont_chmod) |
||
| 2653 | { |
||
| 2654 | $context['total_files'] = $file_count; |
||
| 2655 | return false; |
||
| 2656 | } |
||
| 2657 | |||
| 2658 | // Do the actual directory. |
||
| 2659 | $status = $context['predefined_type'] == 'free' || isset($context['special_files'][$path]) ? 'writable' : 'execute'; |
||
| 2660 | package_chmod($path, $status); |
||
| 2661 | |||
| 2662 | // We've finished the directory so no file offset, and no record. |
||
| 2663 | $context['file_offset'] = 0; |
||
| 2664 | unset($context['directory_list'][$path]); |
||
| 2665 | |||
| 2666 | // See if we're out of time? |
||
| 2667 | if (time() - array_sum(explode(' ', $time_start)) > $timeout_limit) |
||
| 2668 | { |
||
| 2669 | // Prepare this for usage on templates. |
||
| 2670 | $context['directory_list_encode'] = base64_encode($smcFunc['json_encode']($context['directory_list'])); |
||
| 2671 | $context['special_files_encode'] = base64_encode($smcFunc['json_encode']($context['special_files'])); |
||
| 2672 | |||
| 2673 | return false; |
||
| 2674 | } |
||
| 2675 | } |
||
| 2676 | |||
| 2677 | // Prepare this for usage on templates. |
||
| 2678 | $context['directory_list_encode'] = base64_encode($smcFunc['json_encode']($context['directory_list'])); |
||
| 2679 | $context['special_files_encode'] = base64_encode($smcFunc['json_encode']($context['special_files'])); |
||
| 2680 | } |
||
| 2681 | |||
| 2682 | // If we're here we are done! |
||
| 2683 | redirectexit('action=admin;area=packages;sa=perms' . (!empty($context['back_look_data']) ? ';back_look=' . base64_encode($smcFunc['json_encode']($context['back_look_data'])) : '') . ';' . $context['session_var'] . '=' . $context['session_id']); |
||
| 2684 | } |
||
| 2685 | |||
| 2686 | /** |
||
| 2687 | * Test an FTP connection. |
||
| 2688 | */ |
||
| 2689 | function PackageFTPTest() |
||
| 2690 | { |
||
| 2691 | global $context, $txt, $package_ftp; |
||
| 2692 | |||
| 2693 | checkSession('get'); |
||
| 2694 | |||
| 2695 | // Try to make the FTP connection. |
||
| 2696 | create_chmod_control(array(), array('force_find_error' => true)); |
||
| 2697 | |||
| 2698 | // Deal with the template stuff. |
||
| 2699 | loadTemplate('Xml'); |
||
| 2700 | $context['sub_template'] = 'generic_xml'; |
||
| 2701 | $context['template_layers'] = array(); |
||
| 2702 | |||
| 2703 | // Define the return data, this is simple. |
||
| 2704 | $context['xml_data'] = array( |
||
| 2705 | 'results' => array( |
||
| 2706 | 'identifier' => 'result', |
||
| 2707 | 'children' => array( |
||
| 2708 | array( |
||
| 2709 | 'attributes' => array( |
||
| 2710 | 'success' => !empty($package_ftp) ? 1 : 0, |
||
| 2711 | ), |
||
| 2712 | 'value' => !empty($package_ftp) ? $txt['package_ftp_test_success'] : (isset($context['package_ftp'], $context['package_ftp']['error']) ? $context['package_ftp']['error'] : $txt['package_ftp_test_failed']), |
||
| 2713 | ), |
||
| 2714 | ), |
||
| 2715 | ), |
||
| 2716 | ); |
||
| 2717 | } |
||
| 2718 | |||
| 2719 | ?> |
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: