function InstallSmileySet() { global $sourcedir, $boarddir, $modSettings; isAllowedTo('manage_smileys'); checkSession('request'); require_once $sourcedir . '/Subs-Package.php'; $name = strtok(basename(isset($_FILES['set_gz']) ? $_FILES['set_gz']['name'] : $_REQUEST['set_gz']), '.'); $name = preg_replace(array('/\\s/', '/\\.[\\.]+/', '/[^\\w_\\.\\-]/'), array('_', '.', ''), $name); // !!! Decide: overwrite or not? if (isset($_FILES['set_gz']) && is_uploaded_file($_FILES['set_gz']['tmp_name']) && (@ini_get('open_basedir') != '' || file_exists($_FILES['set_gz']['tmp_name']))) { $extracted = read_tgz_file($_FILES['set_gz']['tmp_name'], $boarddir . '/Smileys/' . $name); } elseif (isset($_REQUEST['set_gz'])) { checkSession('request'); // Check that the theme is from simplemachines.org, for now... maybe add mirroring later. if (preg_match('~^http://[\\w_\\-]+\\.simplemachines\\.org/~', $_REQUEST['set_gz']) == 0 || strpos($_REQUEST['set_gz'], 'dlattach') !== false) { fatal_lang_error('not_on_simplemachines'); } $extracted = read_tgz_file($_REQUEST['set_gz'], $boarddir . '/Smileys/' . $name); } else { redirectexit('action=smileys'); } updateSettings(array('smiley_sets_known' => addslashes($modSettings['smiley_sets_known'] . ',' . $name), 'smiley_sets_names' => addslashes($modSettings['smiley_sets_names'] . "\n" . strtok(basename(isset($_FILES['set_gz']) ? $_FILES['set_gz']['name'] : $_REQUEST['set_gz']), '.')))); cache_put_data('parsing_smileys', null, 480); cache_put_data('posting_smileys', null, 480); // !!! Add some confirmation? redirectexit('action=smileys'); }
function DownloadLanguage() { global $context, $sourcedir, $forum_version, $boarddir, $txt, $smcFunc, $scripturl, $modSettings; loadLanguage('ManageSettings'); require_once $sourcedir . '/Subs-Package.php'; // Clearly we need to know what to request. if (!isset($_GET['did'])) { fatal_lang_error('no_access', false); } // Some lovely context. $context['download_id'] = $_GET['did']; $context['sub_template'] = 'download_language'; $context['menu_data_' . $context['admin_menu_id']]['current_subsection'] = 'add'; // Can we actually do the installation - and do they want to? if (!empty($_POST['do_install']) && !empty($_POST['copy_file'])) { checkSession('get'); $chmod_files = array(); $install_files = array(); // Check writable status. foreach ($_POST['copy_file'] as $file) { // Check it's not very bad. if (strpos($file, '..') !== false || substr($file, 0, 6) != 'Themes' && !preg_match('~agreement\\.[A-Za-z-_0-9]+\\.txt$~', $file)) { fatal_error($txt['languages_download_illegal_paths']); } $chmod_files[] = $boarddir . '/' . $file; $install_files[] = $file; } // Call this in case we have work to do. $file_status = create_chmod_control($chmod_files); $files_left = $file_status['files']['notwritable']; // Something not writable? if (!empty($files_left)) { $context['error_message'] = $txt['languages_download_not_chmod']; } elseif (!empty($install_files)) { $archive_content = read_tgz_file('http://download.simplemachines.org/fetch_language.php?version=' . urlencode(strtr($forum_version, array('SMF ' => ''))) . ';fetch=' . urlencode($_GET['did']), $boarddir, false, true, $install_files); // Make sure the files aren't stuck in the cache. package_flush_cache(); $context['install_complete'] = sprintf($txt['languages_download_complete_desc'], $scripturl . '?action=admin;area=languages'); return; } } // Open up the old china. if (!isset($archive_content)) { $archive_content = read_tgz_file('http://download.simplemachines.org/fetch_language.php?version=' . urlencode(strtr($forum_version, array('SMF ' => ''))) . ';fetch=' . urlencode($_GET['did']), null); } if (empty($archive_content)) { fatal_error($txt['add_language_error_no_response']); } // Now for each of the files, let's do some *stuff* $context['files'] = array('lang' => array(), 'other' => array()); $context['make_writable'] = array(); foreach ($archive_content as $file) { $dirname = dirname($file['filename']); $filename = basename($file['filename']); $extension = substr($filename, strrpos($filename, '.') + 1); // Don't do anything with files we don't understand. if (!in_array($extension, array('php', 'jpg', 'gif', 'jpeg', 'png', 'txt'))) { continue; } // Basic data. $context_data = array('name' => $filename, 'destination' => $boarddir . '/' . $file['filename'], 'generaldest' => $file['filename'], 'size' => $file['size'], 'writable' => false, 'default_copy' => true, 'exists' => false); // Does the file exist, is it different and can we overwrite? if (file_exists($boarddir . '/' . $file['filename'])) { if (is_writable($boarddir . '/' . $file['filename'])) { $context_data['writable'] = true; } // Finally, do we actually think the content has changed? if ($file['size'] == filesize($boarddir . '/' . $file['filename']) && $file['md5'] == md5_file($boarddir . '/' . $file['filename'])) { $context_data['exists'] = 'same'; $context_data['default_copy'] = false; } elseif ($file['md5'] == md5(preg_replace("~[\r]?\n~", "\r\n", file_get_contents($boarddir . '/' . $file['filename'])))) { $context_data['exists'] = 'same'; $context_data['default_copy'] = false; } else { $context_data['exists'] = 'different'; } } else { // Can we at least stick it in the directory... if (is_writable($boarddir . '/' . $dirname)) { $context_data['writable'] = true; } } // I love PHP files, that's why I'm a developer and not an artistic type spending my time drinking absinth and living a life of sin... if ($extension == 'php' && preg_match('~\\w+\\.\\w+(?:-utf8)?\\.php~', $filename)) { $context_data += array('version' => '??', 'cur_version' => false, 'version_compare' => 'newer'); list($name, $language) = explode('.', $filename); // Let's get the new version, I like versions, they tell me that I'm up to date. if (preg_match('~\\s*Version:\\s+(.+?);\\s*' . preg_quote($name, '~') . '~i', $file['preview'], $match) == 1) { $context_data['version'] = $match[1]; } // Now does the old file exist - if so what is it's version? if (file_exists($boarddir . '/' . $file['filename'])) { // OK - what is the current version? $fp = fopen($boarddir . '/' . $file['filename'], 'rb'); $header = fread($fp, 768); fclose($fp); // Find the version. if (preg_match('~(?://|/\\*)\\s*Version:\\s+(.+?);\\s*' . preg_quote($name, '~') . '(?:[\\s]{2}|\\*/)~i', $header, $match) == 1) { $context_data['cur_version'] = $match[1]; // How does this compare? if ($context_data['cur_version'] == $context_data['version']) { $context_data['version_compare'] = 'same'; } elseif ($context_data['cur_version'] > $context_data['version']) { $context_data['version_compare'] = 'older'; } // Don't recommend copying if the version is the same. if ($context_data['version_compare'] != 'newer') { $context_data['default_copy'] = false; } } } // Add the context data to the main set. $context['files']['lang'][] = $context_data; } else { // If we think it's a theme thing, work out what the theme is. if (substr($dirname, 0, 6) == 'Themes' && preg_match('~Themes[\\/]([^\\/]+)[\\/]~', $dirname, $match)) { $theme_name = $match[1]; } else { $theme_name = 'misc'; } // Assume it's an image, could be an acceptance note etc but rare. $context['files']['images'][$theme_name][] = $context_data; } // Collect together all non-writable areas. if (!$context_data['writable']) { $context['make_writable'][] = $context_data['destination']; } } // So, I'm a perfectionist - let's get the theme names. $theme_indexes = array(); foreach ($context['files']['images'] as $k => $dummy) { $indexes[] = $k; } $context['theme_names'] = array(); if (!empty($indexes)) { $value_data = array('query' => array(), 'params' => array()); foreach ($indexes as $k => $index) { $value_data['query'][] = 'value LIKE {string:value_' . $k . '}'; $value_data['params']['value_' . $k] = '%' . $index; } $request = $smcFunc['db_query']('', ' SELECT id_theme, value FROM {db_prefix}themes WHERE id_member = {int:no_member} AND variable = {string:theme_dir} AND (' . implode(' OR ', $value_data['query']) . ')', array_merge($value_data['params'], array('no_member' => 0, 'theme_dir' => 'theme_dir', 'index_compare_explode' => 'value LIKE \'%' . implode('\' OR value LIKE \'%', $indexes) . '\''))); $themes = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { // Find the right one. foreach ($indexes as $index) { if (strpos($row['value'], $index) !== false) { $themes[$row['id_theme']] = $index; } } } $smcFunc['db_free_result']($request); if (!empty($themes)) { // Now we have the id_theme we can get the pretty description. $request = $smcFunc['db_query']('', ' SELECT id_theme, value FROM {db_prefix}themes WHERE id_member = {int:no_member} AND variable = {string:name} AND id_theme IN ({array_int:theme_list})', array('theme_list' => array_keys($themes), 'no_member' => 0, 'name' => 'name')); while ($row = $smcFunc['db_fetch_assoc']($request)) { // Now we have it... $context['theme_names'][$themes[$row['id_theme']]] = $row['value']; } $smcFunc['db_free_result']($request); } } // Before we go to far can we make anything writable, eh, eh? if (!empty($context['make_writable'])) { // What is left to be made writable? $file_status = create_chmod_control($context['make_writable']); $context['still_not_writable'] = $file_status['files']['notwritable']; // Mark those which are now writable as such. foreach ($context['files'] as $type => $data) { if ($type == 'lang') { foreach ($data as $k => $file) { if (!$file['writable'] && !in_array($file['destination'], $context['still_not_writable'])) { $context['files'][$type][$k]['writable'] = true; } } } else { foreach ($data as $theme => $files) { foreach ($files as $k => $file) { if (!$file['writable'] && !in_array($file['destination'], $context['still_not_writable'])) { $context['files'][$type][$theme][$k]['writable'] = true; } } } } } // Are we going to need more language stuff? if (!empty($context['still_not_writable'])) { loadLanguage('Packages'); } } // This is the list for the main files. $listOptions = array('id' => 'lang_main_files_list', 'title' => $txt['languages_download_main_files'], 'get_items' => array('function' => create_function('', ' global $context; return $context[\'files\'][\'lang\']; ')), 'columns' => array('name' => array('header' => array('value' => $txt['languages_download_filename']), 'data' => array('function' => create_function('$rowData', ' global $context, $txt; return \'<strong>\' . $rowData[\'name\'] . \'</strong><br /><span class="smalltext">\' . $txt[\'languages_download_dest\'] . \': \' . $rowData[\'destination\'] . \'</span>\' . ($rowData[\'version_compare\'] == \'older\' ? \'<br />\' . $txt[\'languages_download_older\'] : \'\'); '))), 'writable' => array('header' => array('value' => $txt['languages_download_writable']), 'data' => array('function' => create_function('$rowData', ' global $txt; return \'<span style="color: \' . ($rowData[\'writable\'] ? \'green\' : \'red\') . \';">\' . ($rowData[\'writable\'] ? $txt[\'yes\'] : $txt[\'no\']) . \'</span>\'; '), 'style' => 'text-align: center')), 'version' => array('header' => array('value' => $txt['languages_download_version']), 'data' => array('function' => create_function('$rowData', ' global $txt; return \'<span style="color: \' . ($rowData[\'version_compare\'] == \'older\' ? \'red\' : ($rowData[\'version_compare\'] == \'same\' ? \'orange\' : \'green\')) . \';">\' . $rowData[\'version\'] . \'</span>\'; '))), 'exists' => array('header' => array('value' => $txt['languages_download_exists']), 'data' => array('function' => create_function('$rowData', ' global $txt; return $rowData[\'exists\'] ? ($rowData[\'exists\'] == \'same\' ? $txt[\'languages_download_exists_same\'] : $txt[\'languages_download_exists_different\']) : $txt[\'no\']; '))), 'copy' => array('header' => array('value' => $txt['languages_download_copy']), 'data' => array('function' => create_function('$rowData', ' return \'<input type="checkbox" name="copy_file[]" value="\' . $rowData[\'generaldest\'] . \'" \' . ($rowData[\'default_copy\'] ? \'checked="checked"\' : \'\') . \' class="input_check" />\'; '), 'style' => 'text-align: center; width: 4%;')))); // Kill the cache, as it is now invalid.. if (!empty($modSettings['cache_enable'])) { cache_put_data('known_languages', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600); cache_put_data('known_languages_all', null, !empty($modSettings['cache_enable']) && $modSettings['cache_enable'] < 1 ? 86400 : 3600); } require_once $sourcedir . '/Subs-List.php'; createList($listOptions); $context['default_list'] = 'lang_main_files_list'; }
function getPackageInfo($gzfilename) { global $boarddir; // Extract package-info.xml from downloaded file. (*/ is used because it could be in any directory.) if (strpos($gzfilename, 'http://') !== false) { $packageInfo = read_tgz_data(fetch_web_data($gzfilename, '', true), '*/package-info.xml', true); } else { if (!file_exists($boarddir . '/Packages/' . $gzfilename)) { return 'package_get_error_not_found'; } if (is_file($boarddir . '/Packages/' . $gzfilename)) { $packageInfo = read_tgz_file($boarddir . '/Packages/' . $gzfilename, '*/package-info.xml', true); } elseif (file_exists($boarddir . '/Packages/' . $gzfilename . '/package-info.xml')) { $packageInfo = file_get_contents($boarddir . '/Packages/' . $gzfilename . '/package-info.xml'); } else { return 'package_get_error_missing_xml'; } } // Nothing? if (empty($packageInfo)) { return 'package_get_error_is_zero'; } // Parse package-info.xml into an xmlArray. loadClassFile('Class-Package.php'); $packageInfo = new xmlArray($packageInfo); // !!! Error message of some sort? if (!$packageInfo->exists('package-info[0]')) { return 'package_get_error_packageinfo_corrupt'; } $packageInfo = $packageInfo->path('package-info[0]'); $package = $packageInfo->to_array(); $package['xml'] = $packageInfo; $package['filename'] = $gzfilename; if (!isset($package['type'])) { $package['type'] = 'modification'; } return $package; }
function ThemeInstall() { global $sourcedir, $boarddir, $boardurl, $txt, $context, $settings, $modSettings, $smcFunc; checkSession('request'); isAllowedTo('admin_forum'); checkSession('request'); require_once $sourcedir . '/Subs-Package.php'; loadTemplate('Themes'); if (isset($_GET['theme_id'])) { $result = $smcFunc['db_query']('', ' SELECT value FROM {db_prefix}themes WHERE id_theme = {int:current_theme} AND id_member = {int:no_member} AND variable = {string:name} LIMIT 1', array('current_theme' => (int) $_GET['theme_id'], 'no_member' => 0, 'name' => 'name')); list($theme_name) = $smcFunc['db_fetch_row']($result); $smcFunc['db_free_result']($result); $context['sub_template'] = 'installed'; $context['page_title'] = $txt['theme_installed']; $context['installed_theme'] = array('id' => (int) $_GET['theme_id'], 'name' => $theme_name); return; } if (!empty($_FILES['theme_gz']) && (!isset($_FILES['theme_gz']['error']) || $_FILES['theme_gz']['error'] != 4) || !empty($_REQUEST['theme_gz'])) { $method = 'upload'; } elseif (isset($_REQUEST['theme_dir']) && rtrim(realpath($_REQUEST['theme_dir']), '/\\') != realpath($boarddir . '/Themes') && file_exists($_REQUEST['theme_dir'])) { $method = 'path'; } else { $method = 'copy'; } if (!empty($_REQUEST['copy']) && $method == 'copy') { // Hopefully the themes directory is writable, or we might have a problem. if (!is_writable($boarddir . '/Themes')) { fatal_lang_error('theme_install_write_error', 'critical'); } $theme_dir = $boarddir . '/Themes/' . preg_replace('~[^A-Za-z0-9_\\- ]~', '', $_REQUEST['copy']); umask(0); mkdir($theme_dir, 0777); @set_time_limit(600); if (function_exists('apache_reset_timeout')) { @apache_reset_timeout(); } // Create subdirectories for css and javascript files. mkdir($theme_dir . '/css', 0777); mkdir($theme_dir . '/scripts', 0777); // Copy over the default non-theme files. $to_copy = array('/index.php', '/index.template.php', '/css/index.css', '/css/rtl.css', '/scripts/theme.js'); foreach ($to_copy as $file) { copy($settings['default_theme_dir'] . $file, $theme_dir . $file); @chmod($theme_dir . $file, 0777); } // And now the entire images directory! copytree($settings['default_theme_dir'] . '/images', $theme_dir . '/images'); package_flush_cache(); $theme_name = $_REQUEST['copy']; $images_url = $boardurl . '/Themes/' . basename($theme_dir) . '/images'; $theme_dir = realpath($theme_dir); // Lets get some data for the new theme. $request = $smcFunc['db_query']('', ' SELECT variable, value FROM {db_prefix}themes WHERE variable IN ({string:theme_templates}, {string:theme_layers}) AND id_member = {int:no_member} AND id_theme = {int:default_theme}', array('no_member' => 0, 'default_theme' => 1, 'theme_templates' => 'theme_templates', 'theme_layers' => 'theme_layers')); while ($row = $smcFunc['db_fetch_assoc']($request)) { if ($row['variable'] == 'theme_templates') { $theme_templates = $row['value']; } elseif ($row['variable'] == 'theme_layers') { $theme_layers = $row['value']; } else { continue; } } $smcFunc['db_free_result']($request); // Lets add a theme_info.xml to this theme. $xml_info = '<' . '?xml version="1.0"?' . '> <theme-info xmlns="http://www.simplemachines.org/xml/theme-info" xmlns:smf="http://www.simplemachines.org/"> <!-- For the id, always use something unique - put your name, a colon, and then the package name. --> <id>smf:' . $smcFunc['strtolower'](str_replace(array(' '), '_', $_REQUEST['copy'])) . '</id> <version>' . $modSettings['smfVersion'] . '</version> <!-- Theme name, used purely for aesthetics. --> <name>' . $_REQUEST['copy'] . '</name> <!-- Author: your email address or contact information. The name attribute is optional. --> <author name="Simple Machines">info@simplemachines.org</author> <!-- Website... where to get updates and more information. --> <website>http://www.simplemachines.org/</website> <!-- Template layers to use, defaults to "html,body". --> <layers>' . (empty($theme_layers) ? 'html,body' : $theme_layers) . '</layers> <!-- Templates to load on startup. Default is "index". --> <templates>' . (empty($theme_templates) ? 'index' : $theme_templates) . '</templates> <!-- Base this theme off another? Default is blank, or no. It could be "default". --> <based-on></based-on> </theme-info>'; // Now write it. $fp = @fopen($theme_dir . '/theme_info.xml', 'w+'); if ($fp) { fwrite($fp, $xml_info); fclose($fp); } } elseif (isset($_REQUEST['theme_dir']) && $method == 'path') { if (!is_dir($_REQUEST['theme_dir']) || !file_exists($_REQUEST['theme_dir'] . '/theme_info.xml')) { fatal_lang_error('theme_install_error', false); } $theme_name = basename($_REQUEST['theme_dir']); $theme_dir = $_REQUEST['theme_dir']; } elseif ($method = 'upload') { // Hopefully the themes directory is writable, or we might have a problem. if (!is_writable($boarddir . '/Themes')) { fatal_lang_error('theme_install_write_error', 'critical'); } require_once $sourcedir . '/Subs-Package.php'; // Set the default settings... $theme_name = strtok(basename(isset($_FILES['theme_gz']) ? $_FILES['theme_gz']['name'] : $_REQUEST['theme_gz']), '.'); $theme_name = preg_replace(array('/\\s/', '/\\.[\\.]+/', '/[^\\w_\\.\\-]/'), array('_', '.', ''), $theme_name); $theme_dir = $boarddir . '/Themes/' . $theme_name; if (isset($_FILES['theme_gz']) && is_uploaded_file($_FILES['theme_gz']['tmp_name']) && (@ini_get('open_basedir') != '' || file_exists($_FILES['theme_gz']['tmp_name']))) { $extracted = read_tgz_file($_FILES['theme_gz']['tmp_name'], $boarddir . '/Themes/' . $theme_name, false, true); } elseif (isset($_REQUEST['theme_gz'])) { // Check that the theme is from simplemachines.org, for now... maybe add mirroring later. if (preg_match('~^http://[\\w_\\-]+\\.simplemachines\\.org/~', $_REQUEST['theme_gz']) == 0 || strpos($_REQUEST['theme_gz'], 'dlattach') !== false) { fatal_lang_error('not_on_simplemachines'); } $extracted = read_tgz_file($_REQUEST['theme_gz'], $boarddir . '/Themes/' . $theme_name, false, true); } else { redirectexit('action=admin;area=theme;sa=admin;' . $context['session_var'] . '=' . $context['session_id']); } } // Something go wrong? if ($theme_dir != '' && basename($theme_dir) != 'Themes') { // Defaults. $install_info = array('theme_url' => $boardurl . '/Themes/' . basename($theme_dir), 'images_url' => isset($images_url) ? $images_url : $boardurl . '/Themes/' . basename($theme_dir) . '/images', 'theme_dir' => $theme_dir, 'name' => $theme_name); if (file_exists($theme_dir . '/theme_info.xml')) { $theme_info = file_get_contents($theme_dir . '/theme_info.xml'); $xml_elements = array('name' => 'name', 'theme_layers' => 'layers', 'theme_templates' => 'templates', 'based_on' => 'based-on'); foreach ($xml_elements as $var => $name) { if (preg_match('~<' . $name . '>(?:<!\\[CDATA\\[)?(.+?)(?:\\]\\]>)?</' . $name . '>~', $theme_info, $match) == 1) { $install_info[$var] = $match[1]; } } if (preg_match('~<images>(?:<!\\[CDATA\\[)?(.+?)(?:\\]\\]>)?</images>~', $theme_info, $match) == 1) { $install_info['images_url'] = $install_info['theme_url'] . '/' . $match[1]; $explicit_images = true; } if (preg_match('~<extra>(?:<!\\[CDATA\\[)?(.+?)(?:\\]\\]>)?</extra>~', $theme_info, $match) == 1) { $install_info += unserialize($match[1]); } } if (isset($install_info['based_on'])) { if ($install_info['based_on'] == 'default') { $install_info['theme_url'] = $settings['default_theme_url']; $install_info['images_url'] = $settings['default_images_url']; } elseif ($install_info['based_on'] != '') { $install_info['based_on'] = preg_replace('~[^A-Za-z0-9\\-_ ]~', '', $install_info['based_on']); $request = $smcFunc['db_query']('', ' SELECT th.value AS base_theme_dir, th2.value AS base_theme_url' . (!empty($explicit_images) ? '' : ', th3.value AS images_url') . ' FROM {db_prefix}themes AS th INNER JOIN {db_prefix}themes AS th2 ON (th2.id_theme = th.id_theme AND th2.id_member = {int:no_member} AND th2.variable = {string:theme_url})' . (!empty($explicit_images) ? '' : ' INNER JOIN {db_prefix}themes AS th3 ON (th3.id_theme = th.id_theme AND th3.id_member = {int:no_member} AND th3.variable = {string:images_url})') . ' WHERE th.id_member = {int:no_member} AND (th.value LIKE {string:based_on} OR th.value LIKE {string:based_on_path}) AND th.variable = {string:theme_dir} LIMIT 1', array('no_member' => 0, 'theme_url' => 'theme_url', 'images_url' => 'images_url', 'theme_dir' => 'theme_dir', 'based_on' => '%/' . $install_info['based_on'], 'based_on_path' => '%' . "\\" . $install_info['based_on'])); $temp = $smcFunc['db_fetch_assoc']($request); $smcFunc['db_free_result']($request); // !!! An error otherwise? if (is_array($temp)) { $install_info = $temp + $install_info; if (empty($explicit_images) && !empty($install_info['base_theme_url'])) { $install_info['theme_url'] = $install_info['base_theme_url']; } } } unset($install_info['based_on']); } // Find the newest id_theme. $result = $smcFunc['db_query']('', ' SELECT MAX(id_theme) FROM {db_prefix}themes', array()); list($id_theme) = $smcFunc['db_fetch_row']($result); $smcFunc['db_free_result']($result); // This will be theme number... $id_theme++; $inserts = array(); foreach ($install_info as $var => $val) { $inserts[] = array($id_theme, $var, $val); } if (!empty($inserts)) { $smcFunc['db_insert']('insert', '{db_prefix}themes', array('id_theme' => 'int', 'variable' => 'string-255', 'value' => 'string-65534'), $inserts, array('id_theme', 'variable')); } updateSettings(array('knownThemes' => strtr($modSettings['knownThemes'] . ',' . $id_theme, array(',,' => ',')))); } redirectexit('action=admin;area=theme;sa=install;theme_id=' . $id_theme . ';' . $context['session_var'] . '=' . $context['session_id']); }
/** * List operations */ public function action_showoperations() { global $context, $txt; // Can't be in here buddy. isAllowedTo('admin_forum'); // We need to know the operation key for the search and replace, mod file looking at, is it a board mod? if (!isset($_REQUEST['operation_key'], $_REQUEST['filename']) && !is_numeric($_REQUEST['operation_key'])) { fatal_lang_error('operation_invalid', 'general'); } // Load the required file. require_once SUBSDIR . '/Package.subs.php'; require_once SUBSDIR . '/Themes.subs.php'; // Uninstalling the mod? $reverse = isset($_REQUEST['reverse']) ? true : false; // Get the base name. $context['filename'] = preg_replace('~[\\.]+~', '.', $_REQUEST['package']); // We need to extract this again. if (is_file(BOARDDIR . '/packages/' . $context['filename'])) { $context['extracted_files'] = read_tgz_file(BOARDDIR . '/packages/' . $context['filename'], BOARDDIR . '/packages/temp'); if ($context['extracted_files'] && !file_exists(BOARDDIR . '/packages/temp/package-info.xml')) { foreach ($context['extracted_files'] as $file) { if (basename($file['filename']) == 'package-info.xml') { $context['base_path'] = dirname($file['filename']) . '/'; break; } } } if (!isset($context['base_path'])) { $context['base_path'] = ''; } } elseif (is_dir(BOARDDIR . '/packages/' . $context['filename'])) { copytree(BOARDDIR . '/packages/' . $context['filename'], BOARDDIR . '/packages/temp'); $context['extracted_files'] = listtree(BOARDDIR . '/packages/temp'); $context['base_path'] = ''; } // Load up any custom themes we may want to install into... $theme_paths = getThemesPathbyID(); // For uninstall operations we only consider the themes in which the package is installed. if (isset($_REQUEST['reverse']) && !empty($_REQUEST['install_id'])) { $install_id = (int) $_REQUEST['install_id']; if ($install_id > 0) { $old_themes = loadThemesAffected($install_id); foreach ($theme_paths as $id => $data) { if ($id != 1 && !in_array($id, $old_themes)) { unset($theme_paths[$id]); } } } } // Boardmod? if (isset($_REQUEST['boardmod'])) { $mod_actions = parseBoardMod(@file_get_contents(BOARDDIR . '/packages/temp/' . $context['base_path'] . $_REQUEST['filename']), true, $reverse, $theme_paths); } else { $mod_actions = parseModification(@file_get_contents(BOARDDIR . '/packages/temp/' . $context['base_path'] . $_REQUEST['filename']), true, $reverse, $theme_paths); } // Ok lets get the content of the file. $context['operations'] = array('search' => strtr(htmlspecialchars($mod_actions[$_REQUEST['operation_key']]['search_original'], ENT_COMPAT, 'UTF-8'), array('[' => '[', ']' => ']')), 'replace' => strtr(htmlspecialchars($mod_actions[$_REQUEST['operation_key']]['replace_original'], ENT_COMPAT, 'UTF-8'), array('[' => '[', ']' => ']')), 'position' => $mod_actions[$_REQUEST['operation_key']]['position']); // Let's do some formatting... $operation_text = $context['operations']['position'] == 'replace' ? 'operation_replace' : ($context['operations']['position'] == 'before' ? 'operation_after' : 'operation_before'); $context['operations']['search'] = parse_bbc('[code=' . $txt['operation_find'] . ']' . ($context['operations']['position'] == 'end' ? '?>' : $context['operations']['search']) . '[/code]'); $context['operations']['replace'] = parse_bbc('[code=' . $txt[$operation_text] . ']' . $context['operations']['replace'] . '[/code]'); // No layers Template_Layers::getInstance()->removeAll(); $context['sub_template'] = 'view_operations'; }
function ExamineFile() { global $txt, $scripturl, $boarddir, $context, $sourcedir; checkSession('get'); require_once $sourcedir . '/Subs-Package.php'; // No package? Show him or her the door. if (empty($_REQUEST['package']) || preg_match('~[^\\w0-9.\\-_]~', $_REQUEST['package']) === 1 || strpos($_REQUEST['package'], '..') !== false) { redirectexit('action=packages'); } // No file? Show him or her the door. if (!isset($_REQUEST['file']) || $_REQUEST['file'] == '') { redirectexit('action=packages'); } $_REQUEST['package'] = preg_replace('~[\\.]+~', '.', $_REQUEST['package']); $_REQUEST['file'] = preg_replace('~[\\.]+~', '.', $_REQUEST['file']); if (isset($_REQUEST['raw'])) { if (is_file($boarddir . '/Packages/' . $_REQUEST['package'])) { echo read_tgz_file($boarddir . '/Packages/' . $_REQUEST['package'], $_REQUEST['file'], true); } elseif (is_dir($boarddir . '/Packages/' . $_REQUEST['package'])) { echo file_get_contents($boarddir . '/Packages/' . $_REQUEST['package'] . '/' . $_REQUEST['file']); } obExit(false); } $context['linktree'][] = array('url' => $scripturl . '?action=packages;sa=list;package=' . $_REQUEST['package'], 'name' => &$txt['package_examine_file']); $context['page_title'] .= ' - ' . $txt['package_examine_file']; $context['sub_template'] = 'examine'; // The filename... $context['package'] = $_REQUEST['package']; $context['filename'] = $_REQUEST['file']; // Let the unpacker do the work.... but make sure we handle images properly. if (in_array(strtolower(strrchr($_REQUEST['file'], '.')), array('.bmp', '.gif', '.jpeg', '.jpg', '.png'))) { $context['filedata'] = '<img src="' . $scripturl . '?action=packages;sa=examine;package=' . $_REQUEST['package'] . ';file=' . $_REQUEST['file'] . ';raw;sesc=' . $context['session_id'] . '" alt="' . $_REQUEST['file'] . '" />'; } else { if (is_file($boarddir . '/Packages/' . $_REQUEST['package'])) { $context['filedata'] = htmlspecialchars(read_tgz_file($boarddir . '/Packages/' . $_REQUEST['package'], $_REQUEST['file'], true)); } elseif (is_dir($boarddir . '/Packages/' . $_REQUEST['package'])) { $context['filedata'] = htmlspecialchars(file_get_contents($boarddir . '/Packages/' . $_REQUEST['package'] . '/' . $_REQUEST['file'])); } if (strtolower(strrchr($_REQUEST['file'], '.')) == '.php') { $context['filedata'] = highlight_php_code($context['filedata']); } } }
function ViewOperations() { global $context, $txt, $boarddir, $sourcedir, $modSettings; // Can't be in here buddy. isAllowedTo('admin_forum'); // We need to know the operation key for the search and replace, mod file looking at, is it a board mod? if (!isset($_REQUEST['operation_key'], $_REQUEST['filename']) && !is_numeric($_REQUEST['operation_key'])) { fatal_lang_error('operation_invalid', 'general'); } // Load the required file. require_once $sourcedir . '/lib/Subs-Package.php'; // Uninstalling the mod? $reverse = isset($_REQUEST['reverse']) ? true : false; // Get the base name. $context['filename'] = preg_replace('~[\\.]+~', '.', $_REQUEST['package']); // We need to extract this again. if (is_file($boarddir . '/Packages/' . $context['filename'])) { $context['extracted_files'] = read_tgz_file($boarddir . '/Packages/' . $context['filename'], $boarddir . '/Packages/temp'); if ($context['extracted_files'] && !file_exists($boarddir . '/Packages/temp/package-info.xml')) { foreach ($context['extracted_files'] as $file) { if (basename($file['filename']) == 'package-info.xml') { $context['base_path'] = dirname($file['filename']) . '/'; break; } } } if (!isset($context['base_path'])) { $context['base_path'] = ''; } } elseif (is_dir($boarddir . '/Packages/' . $context['filename'])) { copytree($boarddir . '/Packages/' . $context['filename'], $boarddir . '/Packages/temp'); $context['extracted_files'] = listtree($boarddir . '/Packages/temp'); $context['base_path'] = ''; } // Load up any custom themes we may want to install into... $request = smf_db_query(' SELECT id_theme, variable, value FROM {db_prefix}themes WHERE (id_theme = {int:default_theme} OR id_theme IN ({array_int:known_theme_list})) AND variable IN ({string:name}, {string:theme_dir})', array('known_theme_list' => explode(',', $modSettings['knownThemes']), 'default_theme' => 1, 'name' => 'name', 'theme_dir' => 'theme_dir')); $theme_paths = array(); while ($row = mysql_fetch_assoc($request)) { $theme_paths[$row['id_theme']][$row['variable']] = $row['value']; } mysql_free_result($request); // Boardmod? if (isset($_REQUEST['boardmod'])) { $mod_actions = parseBoardMod(@file_get_contents($boarddir . '/Packages/temp/' . $context['base_path'] . $_REQUEST['filename']), true, $reverse, $theme_paths); } else { $mod_actions = parseModification(@file_get_contents($boarddir . '/Packages/temp/' . $context['base_path'] . $_REQUEST['filename']), true, $reverse, $theme_paths); } // Ok lets get the content of the file. $context['operations'] = array('search' => strtr(htmlspecialchars($mod_actions[$_REQUEST['operation_key']]['search_original']), array('[' => '[', ']' => ']')), 'replace' => strtr(htmlspecialchars($mod_actions[$_REQUEST['operation_key']]['replace_original']), array('[' => '[', ']' => ']')), 'position' => $mod_actions[$_REQUEST['operation_key']]['position']); // Let's do some formatting... $operation_text = $context['operations']['position'] == 'replace' ? 'operation_replace' : ($context['operations']['position'] == 'before' ? 'operation_after' : 'operation_before'); $context['operations']['search'] = parse_bbc('[code=' . $txt['operation_find'] . ']' . ($context['operations']['position'] == 'end' ? '?>' : $context['operations']['search']) . '[/code]'); $context['operations']['replace'] = parse_bbc('[code=' . $txt[$operation_text] . ']' . $context['operations']['replace'] . '[/code]'); // No layers $context['template_layers'] = array(); $context['sub_template'] = 'view_operations'; }
/** * Loads a package's information and returns a representative array. * * - Expects the file to be a package in packages/. * - Returns a error string if the package-info is invalid. * - Otherwise returns a basic array of id, version, filename, and similar information. * - An Xml_Array is available in 'xml'. * * @package Packages * @param string $gzfilename */ function getPackageInfo($gzfilename) { $gzfilename = trim($gzfilename); // Extract package-info.xml from downloaded file. (*/ is used because it could be in any directory.) if (preg_match('~^https?://~i', $gzfilename) === 1) { $packageInfo = read_tgz_data(fetch_web_data($gzfilename, '', true), '*/package-info.xml', true); } else { // It must be in the package directory then if (!file_exists(BOARDDIR . '/packages/' . $gzfilename)) { return 'package_get_error_not_found'; } // Make sure an package.xml file is available if (is_file(BOARDDIR . '/packages/' . $gzfilename)) { $packageInfo = read_tgz_file(BOARDDIR . '/packages/' . $gzfilename, '*/package-info.xml', true); } elseif (file_exists(BOARDDIR . '/packages/' . $gzfilename . '/package-info.xml')) { $packageInfo = file_get_contents(BOARDDIR . '/packages/' . $gzfilename . '/package-info.xml'); } else { return 'package_get_error_missing_xml'; } } // Nothing? if (empty($packageInfo)) { // Perhaps they are trying to install a theme, lets tell them nicely this is the wrong function $packageInfo = read_tgz_file(BOARDDIR . '/packages/' . $gzfilename, '*/theme_info.xml', true); if (!empty($packageInfo)) { return 'package_get_error_is_theme'; } else { return 'package_get_error_is_zero'; } } // Parse package-info.xml into an Xml_Array. require_once SUBSDIR . '/XmlArray.class.php'; $packageInfo = new Xml_Array($packageInfo); // @todo Error message of some sort? if (!$packageInfo->exists('package-info[0]')) { return 'package_get_error_packageinfo_corrupt'; } $packageInfo = $packageInfo->path('package-info[0]'); // Convert packageInfo to an array for use $package = htmlspecialchars__recursive($packageInfo->to_array()); $package['xml'] = $packageInfo; $package['filename'] = $gzfilename; // Set a default type if none was supplied in the package if (!isset($package['type'])) { $package['type'] = 'modification'; } return $package; }
function CleanupMods() { global $db_prefix, $modSettings, $upcontext, $boarddir, $sourcedir, $settings, $smcFunc, $command_line; // Sorry. Not supported for command line users. if ($command_line) { return true; } // Skipping first? if (!empty($_POST['skip'])) { unset($_POST['skip']); return true; } // If we get here withOUT SSI we need to redirect to ensure we get it! if (!isset($_GET['ssi']) || !function_exists('mktree')) { redirectLocation('&ssi=1'); } $upcontext['sub_template'] = 'clean_mods'; $upcontext['page_title'] = 'Cleanup Modifications'; // This can be skipped. $upcontext['skip'] = true; // If we're on the second redirect continue... if (isset($_POST['cleandone2'])) { return true; } // Do we already know about some writable files? if (isset($_POST['writable_files'])) { $writable_files = unserialize(base64_decode($_POST['writable_files'])); if (!makeFilesWritable($writable_files)) { // What have we left? $upcontext['writable_files'] = $writable_files; return false; } } // Load all theme paths.... $request = $smcFunc['db_query']('', ' SELECT id_theme, variable, value FROM {db_prefix}themes WHERE id_member = {int:id_member} AND variable IN ({string:theme_dir}, {string:images_url})', array('id_member' => 0, 'theme_dir' => 'theme_dir', 'images_url' => 'images_url', 'db_error_skip' => true)); $theme_paths = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { if ($row['id_theme'] == 1) { $settings['default_' . $row['variable']] = $row['value']; } elseif ($row['variable'] == 'theme_dir') { $theme_paths[$row['id_theme']][$row['variable']] = $row['value']; } } $smcFunc['db_free_result']($request); // Are there are mods installed that may need uninstalling? $request = $smcFunc['db_query']('', ' SELECT id_install, filename, name, themes_installed, version FROM {db_prefix}log_packages WHERE install_state = {int:installed} ORDER BY time_installed DESC', array('installed' => 1, 'db_error_skip' => true)); $upcontext['packages'] = array(); while ($row = $smcFunc['db_fetch_assoc']($request)) { // Work out the status. if (!file_exists($boarddir . '/Packages/' . $row['filename'])) { $status = 'Missing'; $status_color = 'red'; $result = 'Removed'; } else { $status = 'Installed'; $status_color = 'green'; $result = 'No Action Needed'; } $upcontext['packages'][$row['id_install']] = array('id' => $row['id_install'], 'themes' => explode(',', $row['themes_installed']), 'name' => $row['name'], 'filename' => $row['filename'], 'missing_file' => file_exists($boarddir . '/Packages/' . $row['filename']) ? 0 : 1, 'files' => array(), 'file_count' => 0, 'status' => $status, 'result' => $result, 'color' => $status_color, 'version' => $row['version'], 'needs_removing' => false); } $smcFunc['db_free_result']($request); // Don't carry on if there are none. if (empty($upcontext['packages'])) { return true; } // Setup some basics. if (!empty($upcontext['user']['version'])) { $_SESSION['version_emulate'] = $upcontext['user']['version']; } // Before we get started, don't report notice errors. $oldErrorReporting = error_reporting(E_ALL ^ E_NOTICE); if (!mktree($boarddir . '/Packages/temp', 0755)) { deltree($boarddir . '/Packages/temp', false); if (!mktree($boarddir . '/Packages/temp', 0777)) { deltree($boarddir . '/Packages/temp', false); //!!! Error here - plus chmod! } } // Anything which reinstalled should not have its entry removed. $reinstall_worked = array(); // We're gonna be doing some removin' $test = isset($_POST['cleandone']) ? false : true; foreach ($upcontext['packages'] as $id => $package) { // Can't do anything about this.... if ($package['missing_file']) { continue; } // Not testing *and* this wasn't checked? if (!$test && (!isset($_POST['remove']) || !isset($_POST['remove'][$id]))) { continue; } // What are the themes this was installed into? $cur_theme_paths = array(); foreach ($theme_paths as $tid => $data) { if ($tid != 1 && in_array($tid, $package['themes'])) { $cur_theme_paths[$tid] = $data; } } // Get the modifications data if applicable. $filename = $package['filename']; $packageInfo = getPackageInfo($filename); if (!is_array($packageInfo)) { continue; } $info = parsePackageInfo($packageInfo['xml'], $test, 'uninstall'); // Also get the reinstall details... if (isset($_POST['remove'])) { $infoInstall = parsePackageInfo($packageInfo['xml'], true); } if (is_file($boarddir . '/Packages/' . $filename)) { read_tgz_file($boarddir . '/Packages/' . $filename, $boarddir . '/Packages/temp'); } else { copytree($boarddir . '/Packages/' . $filename, $boarddir . '/Packages/temp'); } // Work out how we uninstall... $files = array(); foreach ($info as $change) { // Work out two things: // 1) Whether it's installed at the moment - and if so whether its fully installed, and: // 2) Whether it could be installed on the new version. if ($change['type'] == 'modification') { $contents = @file_get_contents($boarddir . '/Packages/temp/' . $upcontext['base_path'] . $change['filename']); if ($change['boardmod']) { $results = parseBoardMod($contents, $test, $change['reverse'], $cur_theme_paths); } else { $results = parseModification($contents, $test, $change['reverse'], $cur_theme_paths); } foreach ($results as $action) { // Something we can remove? Probably means it existed! if (($action['type'] == 'replace' || $action['type'] == 'append' || !empty($action['filename']) && $action['type'] == 'failure') && !in_array($action['filename'], $files)) { $files[] = $action['filename']; } if ($action['type'] == 'failure') { $upcontext['packages'][$id]['needs_removing'] = true; $upcontext['packages'][$id]['status'] = 'Reinstall Required'; $upcontext['packages'][$id]['color'] = '#FD6435'; } } } } // Store this info for the template as appropriate. $upcontext['packages'][$id]['files'] = $files; $upcontext['packages'][$id]['file_count'] = count($files); // If we've done something save the changes! if (!$test) { package_flush_cache(); } // Are we attempting to reinstall this thing? if (isset($_POST['remove']) && !$test && isset($infoInstall)) { // Need to extract again I'm afraid. if (is_file($boarddir . '/Packages/' . $filename)) { read_tgz_file($boarddir . '/Packages/' . $filename, $boarddir . '/Packages/temp'); } else { copytree($boarddir . '/Packages/' . $filename, $boarddir . '/Packages/temp'); } $errors = false; $upcontext['packages'][$id]['result'] = 'Removed'; foreach ($infoInstall as $change) { if ($change['type'] == 'modification') { $contents = @file_get_contents($boarddir . '/Packages/temp/' . $upcontext['base_path'] . $change['filename']); if ($change['boardmod']) { $results = parseBoardMod($contents, true, $change['reverse'], $cur_theme_paths); } else { $results = parseModification($contents, true, $change['reverse'], $cur_theme_paths); } // Are there any errors? foreach ($results as $action) { if ($action['type'] == 'failure') { $errors = true; } } } } if (!$errors) { $reinstall_worked[] = $id; $upcontext['packages'][$id]['result'] = 'Reinstalled'; $upcontext['packages'][$id]['color'] = 'green'; foreach ($infoInstall as $change) { if ($change['type'] == 'modification') { $contents = @file_get_contents($boarddir . '/Packages/temp/' . $upcontext['base_path'] . $change['filename']); if ($change['boardmod']) { $results = parseBoardMod($contents, false, $change['reverse'], $cur_theme_paths); } else { $results = parseModification($contents, false, $change['reverse'], $cur_theme_paths); } } } // Save the changes. package_flush_cache(); } } } // Put errors back on a sec. error_reporting($oldErrorReporting); // Check everything is writable. if ($test && !empty($upcontext['packages'])) { $writable_files = array(); foreach ($upcontext['packages'] as $package) { if (!empty($package['files'])) { foreach ($package['files'] as $file) { $writable_files[] = $file; } } } if (!empty($writable_files)) { $writable_files = array_unique($writable_files); $upcontext['writable_files'] = $writable_files; if (!makeFilesWritable($writable_files)) { return false; } } } if (file_exists($boarddir . '/Packages/temp')) { deltree($boarddir . '/Packages/temp'); } // Removing/Reinstalling any packages? if (isset($_POST['remove'])) { $deletes = array(); foreach ($_POST['remove'] as $id => $dummy) { if (!in_array((int) $id, $reinstall_worked)) { $deletes[] = (int) $id; } } if (!empty($deletes)) { upgrade_query(' UPDATE ' . $db_prefix . 'log_packages SET install_state = 0 WHERE id_install IN (' . implode(',', $deletes) . ')'); } // Ensure we don't lose our changes! package_put_contents($boarddir . '/Packages/installed.list', time()); $upcontext['sub_template'] = 'cleanup_done'; return false; } else { $allgood = true; // Is there actually anything that needs our attention? foreach ($upcontext['packages'] as $package) { if ($package['color'] != 'green') { $allgood = false; } } if ($allgood) { return true; } } $_GET['substep'] = 0; return isset($_POST['cleandone']) ? true : false; }
function unpackGames($games, $move_games = false) { global $scripturl, $txt, $db_prefix, $modSettings, $context, $sourcedir, $smcFunc, $boarddir; if (!is_writable($modSettings['gamesDirectory']) && !chmod($modSettings['gamesDirectory'], 0777)) { fatal_lang_error('arcade_not_writable', false, array($modSettings['gamesDirectory'])); } require_once $sourcedir . '/Subs-Package.php'; $request = $smcFunc['db_query']('', ' SELECT f.id_file, f.game_file, f.game_directory FROM {db_prefix}arcade_files AS f WHERE id_file IN ({array_int:games}) AND (f.status = 10)', array('games' => $games)); while ($row = $smcFunc['db_fetch_assoc']($request)) { $from = $modSettings['gamesDirectory'] . '/' . $row['game_directory'] . '/' . $row['game_file']; $target = substr($row['game_file'], 0, strpos($row['game_file'], '.')); $targetb = $target; if (substr($target, 0, 5) == 'game_') { $target = substr($target, 5); $target = trim($target); if ($target == '') { continue; } } $fromb = str_replace('game_', '', $from); $i = 1; while (@file_exists($modSettings['gamesDirectory'] . '/' . $target)) { @unlink($from); continue 2; } while (file_exists($modSettings['gamesDirectory'] . '/' . $fromb)) { @unlink($from); continue 2; } if (substr($row['game_file'], -3) == 'zip') { $files = read_tgz_file($from, $modSettings['gamesDirectory'] . '/' . $target); $data = gameCacheInsertGames(getAvailableGames($target, 'unpack'), true); } if (substr($row['game_file'], -3) == 'tar') { @(require_once $sourcedir . '/Tar.php'); $path = $modSettings['gamesDirectory']; $tar = new Archive_Tar($path . '/' . $row['game_file']); $data = $tar->listContent(); if ($data === false) { fatal_lang_error('arcade_file_non_read', false); } else { $folder = $modSettings['gamesDirectory'] . '/' . $target; if (!@is_dir($folder)) { @mkdir($folder, 0777); } $tar = new Archive_Tar($path . '/' . $row['game_file']); $tar->extract($folder); } } if (unlink($from)) { $smcFunc['db_query']('', ' DELETE FROM {db_prefix}arcade_files WHERE id_file = {int:file}', array('file' => $row['id_file'])); } } $smcFunc['db_free_result']($request); return true; }
/** * Installs new themes, either from a gzip or copy of the default. * * What it does: * - Puts themes in $boardurl/themes. * - Assumes the gzip has a root directory in it. (ie default.) * - Requires admin_forum. * - Accessed with ?action=admin;area=theme;sa=install. * * @uses ManageThemes template */ public function action_install() { global $boardurl, $txt, $context, $settings, $modSettings; checkSession('request'); require_once SUBSDIR . '/Themes.subs.php'; require_once SUBSDIR . '/Package.subs.php'; loadTemplate('ManageThemes'); // Passed an ID, then the install is complete, lets redirect and show them if (isset($_GET['theme_id'])) { $_GET['theme_id'] = (int) $_GET['theme_id']; $context['sub_template'] = 'installed'; $context['page_title'] = $txt['theme_installed']; $context['installed_theme'] = array('id' => $_GET['theme_id'], 'name' => getThemeName($_GET['theme_id'])); return; } // How are we going to install this theme, from a dir, zip, copy of default? if (!empty($_FILES['theme_gz']) && (!isset($_FILES['theme_gz']['error']) || $_FILES['theme_gz']['error'] != 4) || !empty($_REQUEST['theme_gz'])) { $method = 'upload'; } elseif (isset($_REQUEST['theme_dir']) && rtrim(realpath($_REQUEST['theme_dir']), '/\\') != realpath(BOARDDIR . '/themes') && file_exists($_REQUEST['theme_dir'])) { $method = 'path'; } else { $method = 'copy'; } // Copy the default theme? if (!empty($_REQUEST['copy']) && $method == 'copy') { // Hopefully the themes directory is writable, or we might have a problem. if (!is_writable(BOARDDIR . '/themes')) { fatal_lang_error('theme_install_write_error', 'critical'); } // Make the new directory, standard characters only $theme_dir = BOARDDIR . '/themes/' . preg_replace('~[^A-Za-z0-9_\\- ]~', '', $_REQUEST['copy']); umask(0); mkdir($theme_dir, 0777); // Get some more time if we can @set_time_limit(600); if (function_exists('apache_reset_timeout')) { @apache_reset_timeout(); } // Create the subdirectories for css, javascript and font files. mkdir($theme_dir . '/css', 0777); mkdir($theme_dir . '/scripts', 0777); mkdir($theme_dir . '/webfonts', 0777); // Copy over the default non-theme files. $to_copy = array('/index.php', '/index.template.php', '/scripts/theme.js'); foreach ($to_copy as $file) { copy($settings['default_theme_dir'] . $file, $theme_dir . $file); @chmod($theme_dir . $file, 0777); } // And now the entire css, images and webfonts directories! copytree($settings['default_theme_dir'] . '/css', $theme_dir . '/css'); copytree($settings['default_theme_dir'] . '/images', $theme_dir . '/images'); copytree($settings['default_theme_dir'] . '/webfonts', $theme_dir . '/webfonts'); package_flush_cache(); $theme_name = $_REQUEST['copy']; $images_url = $boardurl . '/themes/' . basename($theme_dir) . '/images'; $theme_dir = realpath($theme_dir); // Lets get some data for the new theme (default theme (1), default settings (0)). $theme_values = loadThemeOptionsInto(1, 0, array(), array('theme_templates', 'theme_layers')); // Lets add a theme_info.xml to this theme. write_theme_info($_REQUEST['copy'], $modSettings['elkVersion'], $theme_dir, $theme_values); } elseif (isset($_REQUEST['theme_dir']) && $method == 'path') { if (!is_dir($_REQUEST['theme_dir']) || !file_exists($_REQUEST['theme_dir'] . '/theme_info.xml')) { fatal_lang_error('theme_install_error', false); } $theme_name = basename($_REQUEST['theme_dir']); $theme_dir = $_REQUEST['theme_dir']; } elseif ($method == 'upload') { // Hopefully the themes directory is writable, or we might have a problem. if (!is_writable(BOARDDIR . '/themes')) { fatal_lang_error('theme_install_write_error', 'critical'); } // This happens when the admin session is gone and the user has to login again if (empty($_FILES['theme_gz']) && empty($_REQUEST['theme_gz'])) { redirectexit('action=admin;area=theme;sa=admin;' . $context['session_var'] . '=' . $context['session_id']); } // Set the default settings... $theme_name = strtok(basename(isset($_FILES['theme_gz']) ? $_FILES['theme_gz']['name'] : $_REQUEST['theme_gz']), '.'); $theme_name = preg_replace(array('/\\s/', '/\\.[\\.]+/', '/[^\\w_\\.\\-]/'), array('_', '.', ''), $theme_name); $theme_dir = BOARDDIR . '/themes/' . $theme_name; if (isset($_FILES['theme_gz']) && is_uploaded_file($_FILES['theme_gz']['tmp_name']) && (ini_get('open_basedir') != '' || file_exists($_FILES['theme_gz']['tmp_name']))) { read_tgz_file($_FILES['theme_gz']['tmp_name'], BOARDDIR . '/themes/' . $theme_name, false, true); } elseif (isset($_REQUEST['theme_gz'])) { if (!isAuthorizedServer($_REQUEST['theme_gz'])) { fatal_lang_error('not_valid_server'); } read_tgz_file($_REQUEST['theme_gz'], BOARDDIR . '/themes/' . $theme_name, false, true); } else { redirectexit('action=admin;area=theme;sa=admin;' . $context['session_var'] . '=' . $context['session_id']); } } else { fatal_lang_error('theme_install_general', false); } // Something go wrong? if ($theme_dir != '' && basename($theme_dir) != 'themes') { // Defaults. $install_info = array('theme_url' => $boardurl . '/themes/' . basename($theme_dir), 'images_url' => isset($images_url) ? $images_url : $boardurl . '/themes/' . basename($theme_dir) . '/images', 'theme_dir' => $theme_dir, 'name' => $theme_name); $explicit_images = false; if (file_exists($theme_dir . '/theme_info.xml')) { $theme_info = file_get_contents($theme_dir . '/theme_info.xml'); // Parse theme-info.xml into an Xml_Array. require_once SUBSDIR . '/XmlArray.class.php'; $theme_info_xml = new Xml_Array($theme_info); // @todo Error message of some sort? if (!$theme_info_xml->exists('theme-info[0]')) { return 'package_get_error_packageinfo_corrupt'; } $theme_info_xml = $theme_info_xml->path('theme-info[0]'); $theme_info_xml = $theme_info_xml->to_array(); $xml_elements = array('name' => 'name', 'theme_layers' => 'layers', 'theme_templates' => 'templates', 'based_on' => 'based-on'); foreach ($xml_elements as $var => $name) { if (!empty($theme_info_xml[$name])) { $install_info[$var] = $theme_info_xml[$name]; } } if (!empty($theme_info_xml['images'])) { $install_info['images_url'] = $install_info['theme_url'] . '/' . $theme_info_xml['images']; $explicit_images = true; } if (!empty($theme_info_xml['extra'])) { $install_info += unserialize($theme_info_xml['extra']); } } if (isset($install_info['based_on'])) { if ($install_info['based_on'] == 'default') { $install_info['theme_url'] = $settings['default_theme_url']; $install_info['images_url'] = $settings['default_images_url']; } elseif ($install_info['based_on'] != '') { $install_info['based_on'] = preg_replace('~[^A-Za-z0-9\\-_ ]~', '', $install_info['based_on']); $temp = loadBasedOnTheme($install_info['based_on'], $explicit_images); // @todo An error otherwise? if (is_array($temp)) { $install_info = $temp + $install_info; if (empty($explicit_images) && !empty($install_info['base_theme_url'])) { $install_info['theme_url'] = $install_info['base_theme_url']; } } } unset($install_info['based_on']); } // Find the newest id_theme. $id_theme = nextTheme(); $inserts = array(); foreach ($install_info as $var => $val) { $inserts[] = array($id_theme, $var, $val); } if (!empty($inserts)) { addTheme($inserts); } updateSettings(array('knownThemes' => strtr($modSettings['knownThemes'] . ',' . $id_theme, array(',,' => ',')))); } redirectexit('action=admin;area=theme;sa=install;theme_id=' . $id_theme . ';' . $context['session_var'] . '=' . $context['session_id']); }
/** * Install a smiley set. */ public function action_install() { global $modSettings, $scripturl, $context, $txt, $user_info; isAllowedTo('manage_smileys'); checkSession('request'); // One of these two may be necessary loadLanguage('Errors'); loadLanguage('Packages'); require_once SUBSDIR . '/Smileys.subs.php'; require_once SUBSDIR . '/Package.subs.php'; // Installing unless proven otherwise $testing = false; $destination = ''; $name = ''; if (isset($_REQUEST['set_gz'])) { $base_name = strtr(basename($_REQUEST['set_gz']), ':/', '-_'); $name = Util::htmlspecialchars(strtok(basename($_REQUEST['set_gz']), '.')); $name_pr = preg_replace(array('/\\s/', '/\\.[\\.]+/', '/[^\\w_\\.\\-]/'), array('_', '.', ''), $name); $context['filename'] = $base_name; // Check that the smiley is from simplemachines.org, for now... maybe add mirroring later. if (!isAuthorizedServer($_REQUEST['set_gz']) == 0) { fatal_lang_error('not_valid_server'); } $destination = BOARDDIR . '/packages/' . $base_name; if (file_exists($destination)) { fatal_lang_error('package_upload_error_exists'); } // Let's copy it to the packages directory file_put_contents($destination, fetch_web_data($_REQUEST['set_gz'])); $testing = true; } elseif (isset($_REQUEST['package'])) { $base_name = basename($_REQUEST['package']); $name = Util::htmlspecialchars(strtok(basename($_REQUEST['package']), '.')); $name_pr = preg_replace(array('/\\s/', '/\\.[\\.]+/', '/[^\\w_\\.\\-]/'), array('_', '.', ''), $name); $context['filename'] = $base_name; $destination = BOARDDIR . '/packages/' . basename($_REQUEST['package']); } if (!file_exists($destination)) { fatal_lang_error('package_no_file', false); } // Make sure temp directory exists and is empty. if (file_exists(BOARDDIR . '/packages/temp')) { deltree(BOARDDIR . '/packages/temp', false); } if (!mktree(BOARDDIR . '/packages/temp', 0755)) { deltree(BOARDDIR . '/packages/temp', false); if (!mktree(BOARDDIR . '/packages/temp', 0777)) { deltree(BOARDDIR . '/packages/temp', false); // @todo not sure about url in destination_url create_chmod_control(array(BOARDDIR . '/packages/temp/delme.tmp'), array('destination_url' => $scripturl . '?action=admin;area=smileys;sa=install;set_gz=' . $_REQUEST['set_gz'], 'crash_on_error' => true)); deltree(BOARDDIR . '/packages/temp', false); if (!mktree(BOARDDIR . '/packages/temp', 0777)) { fatal_lang_error('package_cant_download', false); } } } $extracted = read_tgz_file($destination, BOARDDIR . '/packages/temp'); // @todo needs to change the URL in the next line ;) if (!$extracted) { fatal_lang_error('packageget_unable', false, array('http://custom.elkarte.net/index.php?action=search;type=12;basic_search=' . $name)); } if ($extracted && !file_exists(BOARDDIR . '/packages/temp/package-info.xml')) { foreach ($extracted as $file) { if (basename($file['filename']) == 'package-info.xml') { $base_path = dirname($file['filename']) . '/'; break; } } } if (!isset($base_path)) { $base_path = ''; } if (!file_exists(BOARDDIR . '/packages/temp/' . $base_path . 'package-info.xml')) { fatal_lang_error('package_get_error_missing_xml', false); } $smileyInfo = getPackageInfo($context['filename']); if (!is_array($smileyInfo)) { fatal_lang_error($smileyInfo); } // See if it is installed? if (isSmileySetInstalled($smileyInfo['id'])) { fata_lang_error('package_installed_warning1'); } // Everything is fine, now it's time to do something, first we test $actions = parsePackageInfo($smileyInfo['xml'], true, 'install'); $context['post_url'] = $scripturl . '?action=admin;area=smileys;sa=install;package=' . $base_name; $context['has_failure'] = false; $context['actions'] = array(); $context['ftp_needed'] = false; foreach ($actions as $action) { if ($action['type'] == 'readme' || $action['type'] == 'license') { $type = 'package_' . $action['type']; if (file_exists(BOARDDIR . '/packages/temp/' . $base_path . $action['filename'])) { $context[$type] = htmlspecialchars(trim(file_get_contents(BOARDDIR . '/packages/temp/' . $base_path . $action['filename']), "\n\r"), ENT_COMPAT, 'UTF-8'); } elseif (file_exists($action['filename'])) { $context[$type] = htmlspecialchars(trim(file_get_contents($action['filename']), "\n\r"), ENT_COMPAT, 'UTF-8'); } if (!empty($action['parse_bbc'])) { require_once SUBSDIR . '/Post.subs.php'; preparsecode($context[$type]); $context[$type] = parse_bbc($context[$type]); } else { $context[$type] = nl2br($context[$type]); } continue; } elseif ($action['type'] == 'require-dir') { // Do this one... $thisAction = array('type' => $txt['package_extract'] . ' ' . ($action['type'] == 'require-dir' ? $txt['package_tree'] : $txt['package_file']), 'action' => Util::htmlspecialchars(strtr($action['destination'], array(BOARDDIR => '.')))); $file = BOARDDIR . '/packages/temp/' . $base_path . $action['filename']; if (isset($action['filename']) && (!file_exists($file) || !is_writable(dirname($action['destination'])))) { $context['has_failure'] = true; $thisAction += array('description' => $txt['package_action_error'], 'failed' => true); } // Show a description for the action if one is provided if (empty($thisAction['description'])) { $thisAction['description'] = isset($action['description']) ? $action['description'] : ''; } $context['actions'][] = $thisAction; } elseif ($action['type'] == 'credits') { // Time to build the billboard $credits_tag = array('url' => $action['url'], 'license' => $action['license'], 'copyright' => $action['copyright'], 'title' => $action['title']); } } if ($testing) { $context['sub_template'] = 'view_package'; $context['uninstalling'] = false; $context['is_installed'] = false; $context['package_name'] = $smileyInfo['name']; loadTemplate('Packages'); } else { $actions = parsePackageInfo($smileyInfo['xml'], false, 'install'); foreach ($context['actions'] as $action) { updateSettings(array('smiley_sets_known' => $modSettings['smiley_sets_known'] . ',' . basename($action['action']), 'smiley_sets_names' => $modSettings['smiley_sets_names'] . "\n" . $smileyInfo['name'] . (count($context['actions']) > 1 ? ' ' . (!empty($action['description']) ? Util::htmlspecialchars($action['description']) : basename($action['action'])) : ''))); } package_flush_cache(); // Time to tell pacman we have a new package installed! package_put_contents(BOARDDIR . '/packages/installed.list', time()); // Credits tag? $credits_tag = empty($credits_tag) ? '' : serialize($credits_tag); $installed = array('filename' => $smileyInfo['filename'], 'name' => $smileyInfo['name'], 'package_id' => $smileyInfo['id'], 'version' => $smileyInfo['filename'], 'id_member' => $user_info['id'], 'member_name' => $user_info['name'], 'credits_tag' => $credits_tag); logPackageInstall($installed); logAction('install_package', array('package' => Util::htmlspecialchars($smileyInfo['name']), 'version' => Util::htmlspecialchars($smileyInfo['version'])), 'admin'); cache_put_data('parsing_smileys', null, 480); cache_put_data('posting_smileys', null, 480); } if (file_exists(BOARDDIR . '/packages/temp')) { deltree(BOARDDIR . '/packages/temp'); } if (!$testing) { redirectexit('action=admin;area=smileys'); } }
function ThemeInstall() { global $sourcedir, $boarddir, $boardurl, $db_prefix, $txt, $context, $settings, $modSettings; checkSession('request'); isAllowedTo('admin_forum'); checkSession('request'); require_once $sourcedir . '/Subs-Package.php'; loadTemplate('Themes'); if (isset($_GET['theme_id'])) { adminIndex('manage_themes'); $result = db_query("\n\t\t\tSELECT value\n\t\t\tFROM {$db_prefix}themes\n\t\t\tWHERE ID_THEME = " . (int) $_GET['theme_id'] . "\n\t\t\t\tAND ID_MEMBER = 0\n\t\t\t\tAND variable = 'name'\n\t\t\tLIMIT 1", __FILE__, __LINE__); list($theme_name) = mysql_fetch_row($result); mysql_free_result($result); $context['sub_template'] = 'installed'; $context['page_title'] = $txt['theme_installed']; $context['installed_theme'] = array('id' => (int) $_GET['theme_id'], 'name' => $theme_name); return; } if (!empty($_FILES['theme_gz']) && (!isset($_FILES['theme_gz']['error']) || $_FILES['theme_gz']['error'] != 4) || !empty($_REQUEST['theme_gz'])) { $method = 'upload'; } elseif (isset($_REQUEST['theme_dir']) && realpath(stripslashes($_REQUEST['theme_dir'])) != realpath($boarddir . '/Themes') && file_exists(stripslashes($_REQUEST['theme_dir']))) { $method = 'path'; } else { $method = 'copy'; } if (!empty($_REQUEST['copy']) && $method == 'copy') { // Hopefully the themes directory is writable, or we might have a problem. if (!is_writable($boarddir . '/Themes')) { fatal_lang_error('theme_install_write_error'); } $theme_dir = $boarddir . '/Themes/' . preg_replace('~[^A-Za-z0-9_\\- ]~', '', $_REQUEST['copy']); umask(0); mkdir($theme_dir, 0777); // Copy over the default non-theme files. $to_copy = array('/style.css', '/index.php', '/index.template.php'); foreach ($to_copy as $file) { copy($settings['default_theme_dir'] . $file, $theme_dir . $file); @chmod($theme_dir . $file, 0777); } // And now the entire images directory! copytree($settings['default_theme_dir'] . '/images', $theme_dir . '/images'); package_flush_cache(); $theme_name = $_REQUEST['copy']; $images_url = $boardurl . '/Themes/' . basename($theme_dir) . '/images'; $theme_dir = realpath($theme_dir); } elseif (isset($_REQUEST['theme_dir']) && $method == 'path') { if (!is_dir(stripslashes($_REQUEST['theme_dir'])) || !file_exists(stripslashes($_REQUEST['theme_dir']) . '/theme_info.xml')) { fatal_lang_error('theme_install_error', false); } $theme_name = basename($_REQUEST['theme_dir']); $theme_dir = stripslashes($_REQUEST['theme_dir']); } elseif ($method = 'upload') { // Hopefully the themes directory is writable, or we might have a problem. if (!is_writable($boarddir . '/Themes')) { fatal_lang_error('theme_install_write_error'); } require_once $sourcedir . '/Subs-Package.php'; // Set the default settings... $theme_name = strtok(basename(isset($_FILES['theme_gz']) ? $_FILES['theme_gz']['name'] : $_REQUEST['theme_gz']), '.'); $theme_name = preg_replace(array('/\\s/', '/\\.[\\.]+/', '/[^\\w_\\.\\-]/'), array('_', '.', ''), $theme_name); $theme_dir = $boarddir . '/Themes/' . $theme_name; if (isset($_FILES['theme_gz']) && is_uploaded_file($_FILES['theme_gz']['tmp_name']) && (@ini_get('open_basedir') != '' || file_exists($_FILES['theme_gz']['tmp_name']))) { $extracted = read_tgz_file($_FILES['theme_gz']['tmp_name'], $boarddir . '/Themes/' . $theme_name, false, true); } elseif (isset($_REQUEST['theme_gz'])) { // Check that the theme is from simplemachines.org, for now... maybe add mirroring later. if (preg_match('~^http://[\\w_\\-]+\\.simplemachines\\.org/~', $_REQUEST['theme_gz']) == 0 || strpos($_REQUEST['theme_gz'], 'dlattach') !== false) { fatal_lang_error('not_on_simplemachines'); } $extracted = read_tgz_file($_REQUEST['theme_gz'], $boarddir . '/Themes/' . $theme_name, false, true); } else { redirectexit('action=theme;sa=admin;sesc=' . $context['session_id']); } } // Something go wrong? if ($theme_dir != '' && basename($theme_dir) != 'Themes') { // Defaults. $install_info = array('theme_url' => $boardurl . '/Themes/' . basename($theme_dir), 'images_url' => isset($images_url) ? $images_url : $boardurl . '/Themes/' . basename($theme_dir) . '/images', 'theme_dir' => $theme_dir, 'name' => $theme_name); if (file_exists($theme_dir . '/theme_info.xml')) { $theme_info = file_get_contents($theme_dir . '/theme_info.xml'); $xml_elements = array('name' => 'name', 'theme_layers' => 'layers', 'theme_templates' => 'templates', 'based_on' => 'based-on'); foreach ($xml_elements as $var => $name) { if (preg_match('~<' . $name . '>(?:<!\\[CDATA\\[)?(.+?)(?:\\]\\]>)?</' . $name . '>~', $theme_info, $match) == 1) { $install_info[$var] = $match[1]; } } if (preg_match('~<images>(?:<!\\[CDATA\\[)?(.+?)(?:\\]\\]>)?</images>~', $theme_info, $match) == 1) { $install_info['images_url'] = $install_info['theme_url'] . '/' . $match[1]; $explicit_images = true; } if (preg_match('~<extra>(?:<!\\[CDATA\\[)?(.+?)(?:\\]\\]>)?</extra>~', $theme_info, $match) == 1) { $install_info += unserialize($match[1]); } } if (isset($install_info['based_on'])) { if ($install_info['based_on'] == 'default') { $install_info['theme_url'] = $settings['default_theme_url']; $install_info['images_url'] = $settings['default_images_url']; } elseif ($install_info['based_on'] != '') { $install_info['based_on'] = preg_replace('~[^A-Za-z0-9\\-_ ]~', '', $install_info['based_on']); $request = db_query("\n\t\t\t\t\tSELECT th.value AS base_theme_dir, th2.value AS base_theme_url" . (!empty($explicit_images) ? '' : ", th3.value AS images_url") . "\n\t\t\t\t\tFROM ({$db_prefix}themes AS th, {$db_prefix}themes AS th2" . (!empty($explicit_images) ? '' : ", {$db_prefix}themes AS th3") . ")\n\t\t\t\t\tWHERE th.ID_MEMBER = 0\n\t\t\t\t\t\tAND (th.value LIKE '%/{$install_info['based_on']}' OR th.value LIKE '%\\{$install_info['based_on']}')\n\t\t\t\t\t\tAND th.variable = 'theme_dir'\n\t\t\t\t\t\tAND th.ID_THEME = th2.ID_THEME\n\t\t\t\t\t\tAND th2.ID_MEMBER = 0\n\t\t\t\t\t\tAND th2.variable = 'theme_url'" . (!empty($explicit_images) ? '' : "\n\t\t\t\t\t\tAND th.ID_THEME = th3.ID_THEME\n\t\t\t\t\t\tAND th3.ID_MEMBER = 0\n\t\t\t\t\t\tAND th3.variable = 'images_url'") . "\n\t\t\t\t\tLIMIT 1", __FILE__, __LINE__); $temp = mysql_fetch_assoc($request); mysql_free_result($request); // !!! An error otherwise? if (is_array($temp)) { $install_info = $temp + $install_info; if (empty($explicit_images) && !empty($install_info['base_theme_url'])) { $install_info['theme_url'] = $install_info['base_theme_url']; } } } unset($install_info['based_on']); } // Find the newest ID_THEME. $result = db_query("\n\t\t\tSELECT MAX(ID_THEME)\n\t\t\tFROM {$db_prefix}themes", __FILE__, __LINE__); list($ID_THEME) = mysql_fetch_row($result); mysql_free_result($result); // This will be theme number... $ID_THEME++; $setString = ''; foreach ($install_info as $var => $val) { $setString .= "\n\t\t\t\t({$ID_THEME}, SUBSTRING('" . addslashes($var) . "', 1, 255), SUBSTRING('" . addslashes($val) . "', 1, 65534)),"; } $setString = substr($setString, 0, -1); db_query("\n\t\t\tINSERT INTO {$db_prefix}themes\n\t\t\t\t(ID_THEME, variable, value)\n\t\t\tVALUES{$setString}", __FILE__, __LINE__); updateSettings(array('knownThemes' => strtr($modSettings['knownThemes'] . ',' . $ID_THEME, array(',,' => ',')))); } redirectexit('action=theme;sa=install;theme_id=' . $ID_THEME . ';sesc=' . $context['session_id']); }
/** * Loads a package's information and returns a representative array. * - expects the file to be a package in Packages/. * - returns a error string if the package-info is invalid. * - otherwise returns a basic array of id, version, filename, and similar information. * - an xmlArray is available in 'xml'. * * @param string $filename * @return array */ function getPackageInfo($gzfilename) { global $boarddir, $sourcedir, $smcFunc; // Extract package-info.xml from downloaded file. (*/ is used because it could be in any directory.) if (strpos($gzfilename, 'http://') !== false) { $packageInfo = read_tgz_data(fetch_web_data($gzfilename, '', true), '*/package-info.xml', true); } else { if (!file_exists($boarddir . '/Packages/' . $gzfilename)) { return 'package_get_error_not_found'; } if (is_file($boarddir . '/Packages/' . $gzfilename)) { $packageInfo = read_tgz_file($boarddir . '/Packages/' . $gzfilename, '*/package-info.xml', true); } elseif (file_exists($boarddir . '/Packages/' . $gzfilename . '/package-info.xml')) { $packageInfo = file_get_contents($boarddir . '/Packages/' . $gzfilename . '/package-info.xml'); } else { return 'package_get_error_missing_xml'; } } // Nothing? if (empty($packageInfo)) { // Perhaps they are trying to install a theme, lets tell them nicely this is the wrong function $packageInfo = read_tgz_file($boarddir . '/Packages/' . $gzfilename, '*/theme_info.xml', true); if (!empty($packageInfo)) { return 'package_get_error_is_theme'; } else { return 'package_get_error_is_zero'; } } // Parse package-info.xml into an xmlArray. require_once $sourcedir . '/Class-Package.php'; $packageInfo = new xmlArray($packageInfo); // @todo Error message of some sort? if (!$packageInfo->exists('package-info[0]')) { return 'package_get_error_packageinfo_corrupt'; } $packageInfo = $packageInfo->path('package-info[0]'); $package = $packageInfo->to_array(); $package['xml'] = $packageInfo; $package['filename'] = $gzfilename; $package['name'] = $smcFunc['htmlspecialchars']($package['name']); if (!isset($package['type'])) { $package['type'] = 'modification'; } return $package; }