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 PackageDownload() { global $txt, $scripturl, $boarddir, $context, $sourcedir, $smcFunc; // Use the downloaded sub template. $context['sub_template'] = 'downloaded'; // Security is good... checkSession('get'); // To download something, we need a valid server or url. if (empty($_GET['server']) && (!empty($_GET['get']) && !empty($_REQUEST['package']))) { fatal_lang_error('package_get_error_is_zero', false); } if (isset($_GET['server'])) { $server = (int) $_GET['server']; // Query the server table to find the requested server. $request = $smcFunc['db_query']('', ' SELECT name, url FROM {db_prefix}package_servers WHERE id_server = {int:current_server} LIMIT 1', array('current_server' => $server)); list($name, $url) = $smcFunc['db_fetch_row']($request); $smcFunc['db_free_result']($request); // If server does not exist then dump out. if (empty($url)) { fatal_lang_error('couldnt_connect', false); } $url = $url . '/'; } else { // Initialize the requried variables. $server = ''; $url = ''; } if (isset($_REQUEST['byurl']) && !empty($_POST['filename'])) { $package_name = basename($_REQUEST['filename']); } else { $package_name = basename($_REQUEST['package']); } if (isset($_REQUEST['conflict']) || isset($_REQUEST['auto']) && file_exists($boarddir . '/Packages/' . $package_name)) { // Find the extension, change abc.tar.gz to abc_1.tar.gz... if (strrpos(substr($package_name, 0, -3), '.') !== false) { $ext = substr($package_name, strrpos(substr($package_name, 0, -3), '.')); $package_name = substr($package_name, 0, strrpos(substr($package_name, 0, -3), '.')) . '_'; } else { $ext = ''; } // Find the first available. $i = 1; while (file_exists($boarddir . '/Packages/' . $package_name . $i . $ext)) { $i++; } $package_name = $package_name . $i . $ext; } // First make sure it's a package. $packageInfo = getPackageInfo($url . $_REQUEST['package']); if (!is_array($packageInfo)) { fatal_lang_error($packageInfo); } // Use FTP if necessary. create_chmod_control(array($boarddir . '/Packages/' . $package_name), array('destination_url' => $scripturl . '?action=admin;area=packages;get;sa=download' . (isset($_GET['server']) ? ';server=' . $_GET['server'] : '') . (isset($_REQUEST['auto']) ? ';auto' : '') . ';package=' . $_REQUEST['package'] . (isset($_REQUEST['conflict']) ? ';conflict' : '') . ';' . $context['session_var'] . '=' . $context['session_id'], 'crash_on_error' => true)); package_put_contents($boarddir . '/Packages/' . $package_name, fetch_web_data($url . $_REQUEST['package'])); // Done! Did we get this package automatically? if (preg_match('~^http://[\\w_\\-]+\\.simplemachines\\.org/~', $_REQUEST['package']) == 1 && strpos($_REQUEST['package'], 'dlattach') === false && isset($_REQUEST['auto'])) { redirectexit('action=admin;area=packages;sa=install;package=' . $package_name); } // You just downloaded a mod from SERVER_NAME_GOES_HERE. $context['package_server'] = $server; $context['package'] = getPackageInfo($package_name); if (!is_array($context['package'])) { fatal_lang_error('package_cant_download', false); } if ($context['package']['type'] == 'modification') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['install_mod'] . ' ]</a>'; } elseif ($context['package']['type'] == 'avatar') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['use_avatars'] . ' ]</a>'; } elseif ($context['package']['type'] == 'language') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['add_languages'] . ' ]</a>'; } else { $context['package']['install']['link'] = ''; } $context['package']['list_files']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=list;package=' . $context['package']['filename'] . '">[ ' . $txt['list_files'] . ' ]</a>'; // Free a little bit of memory... unset($context['package']['xml']); $context['page_title'] = $txt['download_success']; }
/** * Get a listing of all the packages * * - Determines if the package is a mod, avatar, language package * - Determines if the package has been installed or not * * @param int $start * @param int $items_per_page * @param string $sort * @param string $params 'type' type of package * @param bool $installed */ public function list_packages($start, $items_per_page, $sort, $params, $installed) { global $scripturl, $context, $forum_version; static $instadds, $packages; // Start things up if (!isset($packages[$params])) { $packages[$params] = array(); } // We need the packages directory to be writable for this. if (!@is_writable(BOARDDIR . '/packages')) { create_chmod_control(array(BOARDDIR . '/packages'), array('destination_url' => $scripturl . '?action=admin;area=packages', 'crash_on_error' => true)); } list($the_brand, $the_version) = explode(' ', $forum_version, 2); // Here we have a little code to help those who class themselves as something of gods, version emulation ;) if (isset($_GET['version_emulate']) && strtr($_GET['version_emulate'], array($the_brand => '')) == $the_version) { unset($_SESSION['version_emulate']); } elseif (isset($_GET['version_emulate'])) { if (($_GET['version_emulate'] === 0 || $_GET['version_emulate'] === $forum_version) && isset($_SESSION['version_emulate'])) { unset($_SESSION['version_emulate']); } elseif ($_GET['version_emulate'] !== 0) { $_SESSION['version_emulate'] = strtr($_GET['version_emulate'], array('-' => ' ', '+' => ' ', $the_brand . ' ' => '')); } } if (!empty($_SESSION['version_emulate'])) { $context['forum_version'] = $the_brand . ' ' . $_SESSION['version_emulate']; $the_version = $_SESSION['version_emulate']; } if (isset($_SESSION['single_version_emulate'])) { unset($_SESSION['single_version_emulate']); } if (empty($instadds)) { $instadds = loadInstalledPackages(); $installed_adds = array(); // Look through the list of installed mods... foreach ($instadds as $installed_add) { $installed_adds[$installed_add['package_id']] = array('id' => $installed_add['id'], 'version' => $installed_add['version']); } // Get a list of all the ids installed, so the latest packages won't include already installed ones. $context['installed_adds'] = array_keys($installed_adds); } if ($installed) { $sort_id = 1; foreach ($instadds as $installed_add) { $context['available_modification'][$installed_add['package_id']] = array('sort_id' => $sort_id++, 'can_uninstall' => true, 'name' => $installed_add['name'], 'filename' => $installed_add['filename'], 'installed_id' => $installed_add['id'], 'version' => $installed_add['version'], 'is_installed' => true, 'is_current' => true); } } if (empty($packages)) { foreach ($context['package_types'] as $type) { $packages[$type] = array(); } } if ($dir = @opendir(BOARDDIR . '/packages')) { $dirs = array(); $sort_id = array('mod' => 1, 'modification' => 1, 'addon' => 1, 'avatar' => 1, 'language' => 1, 'smiley' => 1, 'unknown' => 1); while ($package = readdir($dir)) { if ($package == '.' || $package == '..' || $package == 'temp' || !(is_dir(BOARDDIR . '/packages/' . $package) && file_exists(BOARDDIR . '/packages/' . $package . '/package-info.xml')) && substr(strtolower($package), -7) != '.tar.gz' && substr(strtolower($package), -4) != '.tgz' && substr(strtolower($package), -4) != '.zip') { continue; } $skip = false; foreach ($context['package_types'] as $type) { if (isset($context['available_' . $type][md5($package)])) { $skip = true; } } if ($skip) { continue; } // Skip directories or files that are named the same. if (is_dir(BOARDDIR . '/packages/' . $package)) { if (in_array($package, $dirs)) { continue; } $dirs[] = $package; } elseif (substr(strtolower($package), -7) == '.tar.gz') { if (in_array(substr($package, 0, -7), $dirs)) { continue; } $dirs[] = substr($package, 0, -7); } elseif (substr(strtolower($package), -4) == '.zip' || substr(strtolower($package), -4) == '.tgz') { if (in_array(substr($package, 0, -4), $dirs)) { continue; } $dirs[] = substr($package, 0, -4); } $packageInfo = getPackageInfo($package); if (!is_array($packageInfo)) { continue; } if (!empty($packageInfo)) { $packageInfo['installed_id'] = isset($installed_adds[$packageInfo['id']]) ? $installed_adds[$packageInfo['id']]['id'] : 0; $packageInfo['sort_id'] = isset($sort_id[$packageInfo['type']]) ? $sort_id[$packageInfo['type']] : $sort_id['unknown']; $packageInfo['is_installed'] = isset($installed_adds[$packageInfo['id']]); $packageInfo['is_current'] = $packageInfo['is_installed'] && $installed_adds[$packageInfo['id']]['version'] == $packageInfo['version']; $packageInfo['is_newer'] = $packageInfo['is_installed'] && $installed_adds[$packageInfo['id']]['version'] > $packageInfo['version']; $packageInfo['can_install'] = false; $packageInfo['can_uninstall'] = false; $packageInfo['can_upgrade'] = false; $packageInfo['can_emulate_install'] = false; $packageInfo['can_emulate_uninstall'] = false; // This package is currently NOT installed. Check if it can be. if (!$packageInfo['is_installed'] && $packageInfo['xml']->exists('install')) { // Check if there's an install for *THIS* version $installs = $packageInfo['xml']->set('install'); foreach ($installs as $install) { if (!$install->exists('@for') || matchPackageVersion($the_version, $install->fetch('@for'))) { // Okay, this one is good to go. $packageInfo['can_install'] = true; break; } } // no install found for our version, lets see if one exists for another if ($packageInfo['can_install'] === false && $install->exists('@for') && empty($_SESSION['version_emulate'])) { $reset = true; // Get the highest install version that is available from the package foreach ($installs as $install) { $packageInfo['can_emulate_install'] = matchHighestPackageVersion($install->fetch('@for'), $reset, $the_version); $reset = false; } } } elseif ($packageInfo['is_installed'] && !$packageInfo['is_current'] && $packageInfo['xml']->exists('upgrade')) { $upgrades = $packageInfo['xml']->set('upgrade'); // First go through, and check against the current version of ElkArte. foreach ($upgrades as $upgrade) { // Even if it is for this ElkArte, is it for the installed version of the mod? if (!$upgrade->exists('@for') || matchPackageVersion($the_version, $upgrade->fetch('@for'))) { if (!$upgrade->exists('@from') || matchPackageVersion($installed_adds[$packageInfo['id']]['version'], $upgrade->fetch('@from'))) { $packageInfo['can_upgrade'] = true; break; } } } } elseif ($packageInfo['is_installed'] && $packageInfo['is_current'] && $packageInfo['xml']->exists('uninstall')) { $uninstalls = $packageInfo['xml']->set('uninstall'); // Can we find any uninstallation methods that work for this ElkArte version? foreach ($uninstalls as $uninstall) { if (!$uninstall->exists('@for') || matchPackageVersion($the_version, $uninstall->fetch('@for'))) { $packageInfo['can_uninstall'] = true; break; } } // No uninstall found for this version, lets see if one exists for another if ($packageInfo['can_uninstall'] === false && $uninstall->exists('@for') && empty($_SESSION['version_emulate'])) { $reset = true; // Get the highest install version that is available from the package foreach ($uninstalls as $uninstall) { $packageInfo['can_emulate_uninstall'] = matchHighestPackageVersion($uninstall->fetch('@for'), $reset, $the_version); $reset = false; } } } // Add-on / Modification if ($packageInfo['type'] == 'addon' || $packageInfo['type'] == 'modification' || $packageInfo['type'] == 'mod') { $sort_id['modification']++; $sort_id['mod']++; $sort_id['addon']++; if ($installed) { if (!empty($context['available_modification'][$packageInfo['id']])) { $packages['modification'][strtolower($packageInfo[$sort]) . '_' . $sort_id['mod']] = $packageInfo['id']; $context['available_modification'][$packageInfo['id']] = array_merge($context['available_modification'][$packageInfo['id']], $packageInfo); } } else { $packages['modification'][strtolower($packageInfo[$sort]) . '_' . $sort_id['mod']] = md5($package); $context['available_modification'][md5($package)] = $packageInfo; } } elseif ($packageInfo['type'] == 'avatar') { $sort_id[$packageInfo['type']]++; $packages['avatar'][strtolower($packageInfo[$sort])] = md5($package); $context['available_avatar'][md5($package)] = $packageInfo; } elseif ($packageInfo['type'] == 'smiley') { $sort_id[$packageInfo['type']]++; $packages['smiley'][strtolower($packageInfo[$sort])] = md5($package); $context['available_smiley'][md5($package)] = $packageInfo; } elseif ($packageInfo['type'] == 'language') { $sort_id[$packageInfo['type']]++; $packages['language'][strtolower($packageInfo[$sort])] = md5($package); $context['available_language'][md5($package)] = $packageInfo; } else { $sort_id['unknown']++; $packages['unknown'][strtolower($packageInfo[$sort])] = md5($package); $context['available_unknown'][md5($package)] = $packageInfo; } } } closedir($dir); } if (isset($_GET['type']) && $_GET['type'] == $params) { if (isset($_GET['desc'])) { krsort($packages[$params]); } else { ksort($packages[$params]); } } return $packages[$params]; }
function PackageFTPTest() { global $context, $txt, $package_ftp; checkSession('get'); // Try to make the FTP connection. create_chmod_control(array(), array('force_find_error' => true)); // Deal with the template stuff. loadTemplate('Xml'); $context['sub_template'] = 'generic_xml'; $context['template_layers'] = array(); // Define the return data, this is simple. $context['xml_data'] = array('results' => array('identifier' => 'result', 'children' => array(array('attributes' => array('success' => !empty($package_ftp) ? 1 : 0), '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']))))); }
/** * 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'); } }
/** * Download a package. * * - Accessed by action=admin;area=packageservers;sa=download */ public function action_download() { global $txt, $scripturl, $context; require_once SUBSDIR . '/PackageServers.subs.php'; // Use the downloaded sub template. $context['sub_template'] = 'downloaded'; // Security is good... checkSession('get'); // To download something, we need a valid server or url. if (empty($_GET['server']) && (!empty($_GET['get']) && !empty($_REQUEST['package']))) { fatal_lang_error('package_get_error_is_zero', false); } if (isset($_GET['server'])) { $server = (int) $_GET['server']; // Query the server table to find the requested server. $packageserver = fetchPackageServers($server); $url = $packageserver[0]['url']; // If server does not exist then dump out. if (empty($url)) { fatal_lang_error('couldnt_connect', false); } $url = $url . '/'; } else { // Initialize the required variables. $server = ''; $url = ''; } // Entered a url and name to download? if (isset($_REQUEST['byurl']) && !empty($_POST['filename'])) { $package_name = basename($_REQUEST['filename']); } else { $package_name = basename($_REQUEST['package']); } // Is this a "master" package from github or bitbucket? if (preg_match('~^http(s)?://(www.)?(bitbucket\\.org|github\\.com)/(.+?(master(\\.zip|\\.tar\\.gz)))$~', $_REQUEST['package'], $matches) == 1) { // @todo maybe use the name/version in the package instead, although the link will be cleaner // Name this master.zip based on repo name in the link $path_parts = pathinfo($matches[4]); list(, $newname, ) = explode('/', $path_parts['dirname']); // Just to be safe, no invalid file characters $invalid = array_merge(array_map('chr', range(0, 31)), array('<', '>', ':', '"', '/', '\\', '|', '?', '*')); $package_name = str_replace($invalid, '_', $newname) . $matches[6]; // We could read the package info and see if we have a duplicate id & version, however that is // not always accurate, especially when dealing with repos. So for now just put in in no conflict mode // and do the save. $_REQUEST['auto'] = true; } if (isset($_REQUEST['conflict']) || isset($_REQUEST['auto']) && file_exists(BOARDDIR . '/packages/' . $package_name)) { // Find the extension, change abc.tar.gz to abc_1.tar.gz... if (strrpos(substr($package_name, 0, -3), '.') !== false) { $ext = substr($package_name, strrpos(substr($package_name, 0, -3), '.')); $package_name = substr($package_name, 0, strrpos(substr($package_name, 0, -3), '.')) . '_'; } else { $ext = ''; } // Find the first available. $i = 1; while (file_exists(BOARDDIR . '/packages/' . $package_name . $i . $ext)) { $i++; } $package_name = $package_name . $i . $ext; } // First make sure it's a package. $packageInfo = getPackageInfo($url . $_REQUEST['package']); if (!is_array($packageInfo)) { fatal_lang_error($packageInfo); } // Save the package to disk, use FTP if necessary create_chmod_control(array(BOARDDIR . '/packages/' . $package_name), array('destination_url' => $scripturl . '?action=admin;area=packageservers;sa=download' . (isset($_GET['server']) ? ';server=' . $_GET['server'] : '') . (isset($_REQUEST['auto']) ? ';auto' : '') . ';package=' . $_REQUEST['package'] . (isset($_REQUEST['conflict']) ? ';conflict' : '') . ';' . $context['session_var'] . '=' . $context['session_id'], 'crash_on_error' => true)); package_put_contents(BOARDDIR . '/packages/' . $package_name, fetch_web_data($url . $_REQUEST['package'])); // Done! Did we get this package automatically? if (preg_match('~^http://[\\w_\\-]+\\.elkarte\\.net/~', $_REQUEST['package']) == 1 && strpos($_REQUEST['package'], 'dlattach') === false && isset($_REQUEST['auto'])) { redirectexit('action=admin;area=packages;sa=install;package=' . $package_name); } // You just downloaded a addon from SERVER_NAME_GOES_HERE. $context['package_server'] = $server; // Read in the newly saved package information $context['package'] = getPackageInfo($package_name); if (!is_array($context['package'])) { fatal_lang_error('package_cant_download', false); } if ($context['package']['type'] == 'modification') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['install_mod'] . ' ]</a>'; } elseif ($context['package']['type'] == 'avatar') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['use_avatars'] . ' ]</a>'; } elseif ($context['package']['type'] == 'language') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['add_languages'] . ' ]</a>'; } else { $context['package']['install']['link'] = ''; } $context['package']['list_files']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=list;package=' . $context['package']['filename'] . '">[ ' . $txt['list_files'] . ' ]</a>'; // Free a little bit of memory... unset($context['package']['xml']); $context['page_title'] = $txt['download_success']; }
/** * Download a package. * * What it does: * - Accessed by action=admin;area=packageservers;sa=download * - If server is set, loads json file from package server * - requires both section and num values to validate the file to download from the json file * - If $_POST['byurl']) $_POST['filename'])) are set, will download a file from the url and save it as filename * - If just $_POST['byurl']) is set will fetch that file and save it * - github and bitbucket master files are renamed to repo name to avoid collisions * - Files are saved to the package directory and validate to be ElkArte packages */ public function action_download() { global $txt, $scripturl, $context; require_once SUBSDIR . '/PackageServers.subs.php'; // Use the downloaded sub template. $context['sub_template'] = 'downloaded'; // Security is good... if (isset($_GET['server'])) { checkSession('get'); } else { checkSession(); } // To download something, we need either a valid server or url. if (empty($_GET['server']) && (!empty($_GET['get']) && !empty($_POST['package']))) { fatal_lang_error('package_get_error_is_zero', false); } // Start off with nothing $package_name = ''; $server = ''; $url = ''; // Download from a package server? if (!empty($_GET['server'])) { list(, $url, $server) = $this->_package_server(); // Fetch the package listing from the package server $listing = json_decode(fetch_web_data($url)); // Find the requested package by section and number, make sure it matches $section = $listing->{$_GET}['section']; // This is what they requested, yes? if (basename($section[$_GET['num']]->server[0]->download) === $_GET['package']) { // Where to download it from $package_name = $this->_rename_master($section[$_GET['num']]->server[0]->download); $path_url = pathinfo($section[$_GET['num']]->server[0]->download); $url = isset($path_url['dirname']) ? $path_url['dirname'] . '/' : ''; } else { fatal_lang_error('package_cant_download', false); } } elseif (isset($_POST['byurl']) && !empty($_POST['filename'])) { $package_name = basename($_POST['filename']); } else { $package_name = $this->_rename_master($_POST['package']); } // Avoid over writing any existing package files of the same name if (isset($_REQUEST['conflict']) || isset($_REQUEST['auto']) && file_exists(BOARDDIR . '/packages/' . $package_name)) { // Find the extension, change abc.tar.gz to abc_1.tar.gz... if (strrpos(substr($package_name, 0, -3), '.') !== false) { $ext = substr($package_name, strrpos(substr($package_name, 0, -3), '.')); $package_name = substr($package_name, 0, strrpos(substr($package_name, 0, -3), '.')) . '_'; } else { $ext = ''; } // Find the first available free name $i = 1; while (file_exists(BOARDDIR . '/packages/' . $package_name . $i . $ext)) { $i++; } $package_name = $package_name . $i . $ext; } // First make sure it's a package. $packageInfo = getPackageInfo($url . $_REQUEST['package']); if (!is_array($packageInfo)) { fatal_lang_error($packageInfo); } // Save the package to disk as $package_name, use FTP if necessary create_chmod_control(array(BOARDDIR . '/packages/' . $package_name), array('destination_url' => $scripturl . '?action=admin;area=packageservers;sa=download' . (isset($_GET['server']) ? ';server=' . $_GET['server'] : '') . (isset($_REQUEST['auto']) ? ';auto' : '') . ';package=' . $_REQUEST['package'] . (isset($_REQUEST['conflict']) ? ';conflict' : '') . ';' . $context['session_var'] . '=' . $context['session_id'], 'crash_on_error' => true)); package_put_contents(BOARDDIR . '/packages/' . $package_name, fetch_web_data($url . $_REQUEST['package'])); // Done! Did we get this package automatically? if (preg_match('~^http://[\\w_\\-]+\\.elkarte\\.net/~', $_REQUEST['package']) == 1 && strpos($_REQUEST['package'], 'dlattach') === false && isset($_REQUEST['auto'])) { redirectexit('action=admin;area=packages;sa=install;package=' . $package_name); } // You just downloaded a addon from SERVER_NAME_GOES_HERE. $context['package_server'] = $server; // Read in the newly saved package information $context['package'] = getPackageInfo($package_name); if (!is_array($context['package'])) { fatal_lang_error('package_cant_download', false); } if ($context['package']['type'] == 'modification') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['install_mod'] . ' ]</a>'; } elseif ($context['package']['type'] == 'avatar') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['use_avatars'] . ' ]</a>'; } elseif ($context['package']['type'] == 'language') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=install;package=' . $context['package']['filename'] . '">[ ' . $txt['add_languages'] . ' ]</a>'; } else { $context['package']['install']['link'] = ''; } $context['package']['list_files']['link'] = '<a href="' . $scripturl . '?action=admin;area=packages;sa=list;package=' . $context['package']['filename'] . '">[ ' . $txt['list_files'] . ' ]</a>'; // Free a little bit of memory... unset($context['package']['xml']); $context['page_title'] = $txt['download_success']; }