function PackageDownload() { global $txt, $scripturl, $boarddir, $context, $sourcedir, $db_prefix; // Use the downloaded sub template. $context['sub_template'] = 'downloaded'; // Security is good... checkSession('get'); if (isset($_GET['server'])) { $server = (int) $_GET['server']; // Query the server table to find the requested server. $request = db_query("\n\t\t\tSELECT name, url\n\t\t\tFROM {$db_prefix}package_servers\n\t\t\tWHERE ID_SERVER = {$server}\n\t\t\tLIMIT 1", __FILE__, __LINE__); list($name, $url) = mysql_fetch_row($request); mysql_free_result($request); // If server does not exist then dump out. if (empty($url)) { fatal_lang_error('smf191', false); } $url = $url . '/'; } else { // Initialize the requried variables. $server = ''; $url = ''; } $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. if (getPackageInfo($url . $_REQUEST['package']) == false) { fatal_lang_error('package45', false); } // Use FTP if necessary. packageRequireFTP($scripturl . '?action=packageget;sa=download' . (isset($_GET['server']) ? ';server=' . $_GET['server'] : '') . (isset($_REQUEST['auto']) ? ';auto' : '') . ';package=' . $_REQUEST['package'] . (isset($_REQUEST['conflict']) ? ';conflict' : '') . ';sesc=' . $context['session_id'], array($boarddir . '/Packages/' . $package_name)); 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=packages;sa=install;package=' . $package_name . ';sesc=' . $context['session_id']); } // You just downloaded a mod from SERVER_NAME_GOES_HERE. $context['package_server'] = $server; $context['package'] = getPackageInfo($package_name); if (empty($context['package'])) { fatal_lang_error('package_cant_download', false); } if ($context['package']['type'] == 'modification') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=packages;sa=install;package=' . $context['package']['filename'] . ';sesc=' . $context['session_id'] . '">[ ' . $txt['package11'] . ' ]</a>'; } elseif ($context['package']['type'] == 'avatar') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=packages;sa=install;package=' . $context['package']['filename'] . ';sesc=' . $context['session_id'] . '">[ ' . $txt['package12'] . ' ]</a>'; } elseif ($context['package']['type'] == 'language') { $context['package']['install']['link'] = '<a href="' . $scripturl . '?action=packages;sa=install;package=' . $context['package']['filename'] . ';sesc=' . $context['session_id'] . '">[ ' . $txt['package13'] . ' ]</a>'; } else { $context['package']['install']['link'] = ''; } $context['package']['list_files']['link'] = '<a href="' . $scripturl . '?action=packages;sa=list;package=' . $context['package']['filename'] . '">[ ' . $txt['package14'] . ' ]</a>'; // Free a little bit of memory... unset($context['package']['xml']); $context['page_title'] = $txt['smf192']; }
function PackageRemove() { global $scripturl, $boarddir; checkSession('get'); // Ack, don't allow deletion of arbitrary files here, could become a security hole somehow! if (!isset($_GET['package']) || $_GET['package'] == 'index.php' || $_GET['package'] == 'installed.list') { redirectexit('action=packages;sa=browse'); } $_GET['package'] = preg_replace('~[\\.]+~', '.', strtr($_GET['package'], array('/' => '_', '\\' => '_'))); // Can't delete what's not there. if (file_exists($boarddir . '/Packages/' . $_GET['package']) && (substr($_GET['package'], -4) == '.zip' || substr($_GET['package'], -4) == '.tgz' || substr($_GET['package'], -7) == '.tar.gz' || is_dir($boarddir . '/Packages/' . $_GET['package'])) && $_GET['package'] != 'backups' && substr($_GET['package'], 0, 1) != '.') { packageRequireFTP($scripturl . '?action=packages;sa=remove;package=' . $_GET['package'], array($boarddir . '/Packages/' . $_GET['package'])); if (is_dir($boarddir . '/Packages/' . $_GET['package'])) { deltree($boarddir . '/Packages/' . $_GET['package']); } else { @chmod($boarddir . '/Packages/' . $_GET['package'], 0777); unlink($boarddir . '/Packages/' . $_GET['package']); } } redirectexit('action=packages;sa=browse'); }
function packageRequireFTP($destination_url, $files = null, $return = false) { global $context, $modSettings, $package_ftp, $boarddir, $txt; // Try to make them writable the manual way. if ($files !== null) { foreach ($files as $k => $file) { // If this file doesn't exist, then we actually want to look at the directory, no? if (!file_exists($file)) { $file = dirname($file); } // This looks odd, but it's an attempt to work around PHP suExec. if (!@is_writable($file)) { @chmod($file, 0755); } if (!@is_writable($file)) { @chmod($file, 0777); } if (!@is_writable(dirname($file))) { @chmod($file, 0755); } if (!@is_writable(dirname($file))) { @chmod($file, 0777); } $fp = is_dir($file) ? @opendir($file) : @fopen($file, 'rb'); if (@is_writable($file) && $fp) { unset($files[$k]); if (!is_dir($file)) { fclose($fp); } else { closedir($fp); } } } // No FTP required! if (empty($files)) { return array(); } } // They've opted to not use FTP, and try anyway. if (isset($_SESSION['pack_ftp']) && $_SESSION['pack_ftp'] == false) { if ($files === null) { return array(); } foreach ($files as $k => $file) { // This looks odd, but it's an attempt to work around PHP suExec. if (!file_exists($file)) { mktree(dirname($file), 0755); @touch($file); @chmod($file, 0755); } if (!@is_writable($file)) { @chmod($file, 0777); } if (!@is_writable(dirname($file))) { @chmod(dirname($file), 0777); } if (@is_writable($file)) { unset($files[$k]); } } return $files; } elseif (isset($_SESSION['pack_ftp'])) { // Load the file containing the ftp_connection class. loadClassFile('Class-Package.php'); $package_ftp = new ftp_connection($_SESSION['pack_ftp']['server'], $_SESSION['pack_ftp']['port'], $_SESSION['pack_ftp']['username'], package_crypt($_SESSION['pack_ftp']['password'])); if ($files === null) { return array(); } foreach ($files as $k => $file) { $ftp_file = strtr($file, array($_SESSION['pack_ftp']['root'] => '')); // This looks odd, but it's an attempt to work around PHP suExec. if (!file_exists($file)) { mktree(dirname($file), 0755); $package_ftp->create_file($ftp_file); $package_ftp->chmod($ftp_file, 0755); } if (!@is_writable($file)) { $package_ftp->chmod($ftp_file, 0777); } if (!@is_writable(dirname($file))) { $package_ftp->chmod(dirname($ftp_file), 0777); } if (@is_writable($file)) { unset($files[$k]); } } return $files; } if (isset($_POST['ftp_none'])) { $_SESSION['pack_ftp'] = false; $files = packageRequireFTP($destination_url, $files, $return); return $files; } elseif (isset($_POST['ftp_username'])) { loadClassFile('Class-Package.php'); $ftp = new ftp_connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']); if ($ftp->error === false) { // Common mistake, so let's try to remedy it... if (!$ftp->chdir($_POST['ftp_path'])) { $ftp_error = $ftp->last_message; $ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $_POST['ftp_path'])); } } } if (!isset($ftp) || $ftp->error !== false) { if (!isset($ftp)) { loadClassFile('Class-Package.php'); $ftp = new ftp_connection(null); } elseif ($ftp->error !== false && !isset($ftp_error)) { $ftp_error = $ftp->last_message === null ? '' : $ftp->last_message; } list($username, $detect_path, $found_path) = $ftp->detect_path($boarddir); if ($found_path) { $_POST['ftp_path'] = $detect_path; } elseif (!isset($_POST['ftp_path'])) { $_POST['ftp_path'] = isset($modSettings['package_path']) ? $modSettings['package_path'] : $detect_path; } if (!isset($_POST['ftp_username'])) { $_POST['ftp_username'] = $username; } $context['package_ftp'] = array('server' => isset($_POST['ftp_server']) ? $_POST['ftp_server'] : (isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost'), 'port' => isset($_POST['ftp_port']) ? $_POST['ftp_port'] : (isset($modSettings['package_port']) ? $modSettings['package_port'] : '21'), 'username' => isset($_POST['ftp_username']) ? $_POST['ftp_username'] : (isset($modSettings['package_username']) ? $modSettings['package_username'] : ''), 'path' => $_POST['ftp_path'], 'error' => empty($ftp_error) ? null : $ftp_error, 'destination' => $destination_url); // If we're returning dump out here. if ($return) { return $files; } $context['page_title'] = $txt['package_ftp_necessary']; $context['sub_template'] = 'ftp_required'; obExit(); } else { if (!in_array($_POST['ftp_path'], array('', '/'))) { $ftp_root = strtr($boarddir, array($_POST['ftp_path'] => '')); if (substr($ftp_root, -1) == '/' && ($_POST['ftp_path'] == '' || substr($_POST['ftp_path'], 0, 1) == '/')) { $ftp_root = substr($ftp_root, 0, -1); } } else { $ftp_root = $boarddir; } $_SESSION['pack_ftp'] = array('server' => $_POST['ftp_server'], 'port' => $_POST['ftp_port'], 'username' => $_POST['ftp_username'], 'password' => package_crypt($_POST['ftp_password']), 'path' => $_POST['ftp_path'], 'root' => $ftp_root); if (!isset($modSettings['package_path']) || $modSettings['package_path'] != $_POST['ftp_path']) { updateSettings(array('package_path' => $_POST['ftp_path'])); } $files = packageRequireFTP($destination_url, $files, $return); } return $files; }
function CleanupPermissions() { global $boarddir, $sourcedir, $scripturl, $package_ftp, $modSettings; isAllowedTo('admin_forum'); umask(0); loadTemplate('Packages'); loadLanguage('Packages'); if (!isset($_REQUEST['perm_type']) || !in_array($_REQUEST['perm_type'], array('free', 'restrictive', 'standard'))) { $_REQUEST['perm_type'] = 'free'; } checkSession(); // FTP to the rescue! require_once $sourcedir . '/Subs-Package.php'; packageRequireFTP($scripturl . '?action=cleanperms;perm_type=' . $_REQUEST['perm_type']); // The files that should be chmod'd are here - add any if you add any files with a modification. $special_files = array(); $special_files['restrictive'] = array('/attachments', '/custom_avatar_dir', '/Settings.php', '/Settings_bak.php'); $special_files['standard'] = array('/attachments', '/avatars', '/custom_avatar_dir', '/Packages', '/Packages/installed.list', '/Smileys', '/Themes', '/agreement.txt', '/Settings.php', '/Settings_bak.php'); @chmod($boarddir . '/Settings.php', 0755); if (isset($package_ftp)) { $package_ftp->chmod(strtr($boarddir . '/Settings.php', array($_SESSION['pack_ftp']['root'] => '')), 0755); } // If the owner of PHP is not nobody, this should probably pass through - in which case 755 is better than 777. if ((!function_exists('is_executable') || is_executable($boarddir . '/Settings.php')) && is_writable($boarddir . '/Settings.php')) { $suexec_fix = 0755; } else { $suexec_fix = 0777; } @chmod($boarddir, $_REQUEST['perm_type'] == 'free' ? $suexec_fix : 0755); if (isset($package_ftp)) { $package_ftp->chmod(strtr($boarddir . '/.', array($_SESSION['pack_ftp']['root'] => '')), $_REQUEST['perm_type'] == 'free' ? $suexec_fix : 0755); } $dirs = array('' => $boarddir); if (substr($sourcedir, 0, strlen($boarddir)) != $boarddir) { $dirs['/Sources'] = $sourcedir; } if (substr($modSettings['attachmentUploadDir'], 0, strlen($boarddir)) != $boarddir) { $dirs['/attachments'] = $modSettings['attachmentUploadDir']; } if (substr($modSettings['smileys_dir'], 0, strlen($boarddir)) != $boarddir) { $dirs['/Smileys'] = $modSettings['smileys_dir']; } if (substr($modSettings['avatar_directory'], 0, strlen($boarddir)) != $boarddir) { $dirs['/avatars'] = $modSettings['avatar_directory']; } if (isset($modSettings['custom_avatar_dir']) && substr($modSettings['custom_avatar_dir'], 0, strlen($boarddir)) != $boarddir) { $dirs['/custom_avatar_dir'] = $modSettings['custom_avatar_dir']; } $done_dirs = array(); while (count($dirs) > 0) { // The alias is what we know it as. The attachments directory *could* be named "uploads". $temp = array_keys($dirs); $alias = $temp[0]; // The actual full filename... $dirname = $dirs[$alias]; unset($dirs[$alias]); $dir = dir($dirname); if (!$dir) { continue; } while ($entry = $dir->read()) { if ($entry == '.' || $entry == '..') { continue; } // Figure out the filenames to chmod with... $filename = $dirname . '/' . $entry; $ftp_file = strtr($filename, array($_SESSION['pack_ftp']['root'] => '')); // Is this one we want writable? if ($_REQUEST['perm_type'] == 'free' || in_array($alias . '/' . $entry, $special_files[$_REQUEST['perm_type']])) { @chmod($filename, $suexec_fix); if (isset($package_ftp)) { $package_ftp->chmod($ftp_file, $suexec_fix); } } else { @chmod($filename, 0755); if (isset($package_ftp)) { $package_ftp->chmod($ftp_file, 0755); } } // Directories get added to the todo list. if (@is_dir($filename) && !in_array($filename, $done_dirs)) { $dirs[$alias . '/' . $entry] = $filename; } } $done_dirs[] = $dirname; } redirectexit('action=packages;sa=options'); }