function CheckFilesWritable() { global $txt, $incontext; $incontext['page_title'] = $txt['ftp_checking_writable']; $incontext['sub_template'] = 'chmod_files'; $writable_files = array('attachments', 'avatars', 'cache', 'template_cache', 'Packages', 'Packages/installed.list', 'Smileys', 'Themes', 'agreement.txt', 'Settings.php', 'Settings_bak.php'); $extra_files = array('Themes/classic/index.template.php', 'Themes/classic/style.css'); foreach ($incontext['detected_languages'] as $lang => $temp) { $extra_files[] = 'Themes/default/languages/' . $lang; } // With mod_security installed, we could attempt to fix it with .htaccess. if (function_exists('apache_get_modules') && in_array('mod_security', apache_get_modules())) { $writable_files[] = file_exists(dirname(__FILE__) . '/.htaccess') ? '.htaccess' : '.'; } $failed_files = array(); // On linux, it's easy - just use is_writable! if (substr(__FILE__, 1, 2) != ':\\') { foreach ($writable_files as $file) { if (!is_writable(dirname(__FILE__) . '/' . $file)) { @chmod(dirname(__FILE__) . '/' . $file, 0755); // Well, 755 hopefully worked... if not, try 777. if (!is_writable(dirname(__FILE__) . '/' . $file) && !@chmod(dirname(__FILE__) . '/' . $file, 0777)) { $failed_files[] = $file; } } } foreach ($extra_files as $file) { @chmod(dirname(__FILE__) . (empty($file) ? '' : '/' . $file), 0777); } } else { foreach ($writable_files as $file) { // Folders can't be opened for write... but the index.php in them can ;) if (is_dir(dirname(__FILE__) . '/' . $file)) { $file .= '/index.php'; } // Funny enough, chmod actually does do something on windows - it removes the read only attribute. @chmod(dirname(__FILE__) . '/' . $file, 0777); $fp = @fopen(dirname(__FILE__) . '/' . $file, 'r+'); // Hmm, okay, try just for write in that case... if (!is_resource($fp)) { $fp = @fopen(dirname(__FILE__) . '/' . $file, 'w'); } if (!is_resource($fp)) { $failed_files[] = $file; } @fclose($fp); } foreach ($extra_files as $file) { @chmod(dirname(__FILE__) . (empty($file) ? '' : '/' . $file), 0777); } } $failure = count($failed_files) >= 1; if (!isset($_SERVER)) { return !$failure; } // Put the list into context. $incontext['failed_files'] = $failed_files; // It's not going to be possible to use FTP on windows to solve the problem... if ($failure && substr(__FILE__, 1, 2) == ':\\') { $incontext['error'] = $txt['error_windows_chmod'] . ' <ul style="margin: 2.5ex; font-family: monospace;"> <li>' . implode('</li> <li>', $failed_files) . '</li> </ul>'; return false; } elseif ($failure) { // Load any session data we might have... if (!isset($_POST['ftp_username']) && isset($_SESSION['installer_temp_ftp'])) { $_POST['ftp_server'] = $_SESSION['installer_temp_ftp']['server']; $_POST['ftp_port'] = $_SESSION['installer_temp_ftp']['port']; $_POST['ftp_username'] = $_SESSION['installer_temp_ftp']['username']; $_POST['ftp_password'] = $_SESSION['installer_temp_ftp']['password']; $_POST['ftp_path'] = $_SESSION['installer_temp_ftp']['path']; } $incontext['ftp_errors'] = array(); if (isset($_POST['ftp_username'])) { $ftp = new ftp_connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']); if ($ftp->error === false) { // Try it without /home/abc just in case they messed up. if (!$ftp->chdir($_POST['ftp_path'])) { $incontext['ftp_errors'][] = $ftp->last_message; $ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $_POST['ftp_path'])); } } } if (!isset($ftp) || $ftp->error !== false) { if (!isset($ftp)) { $ftp = new ftp_connection(null); } elseif ($ftp->error !== false && empty($incontext['ftp_errors']) && !empty($ftp->last_message)) { $incontext['ftp_errors'][] = $ftp->last_message; } list($username, $detect_path, $found_path) = $ftp->detect_path(dirname(__FILE__)); if (empty($_POST['ftp_path']) && $found_path) { $_POST['ftp_path'] = $detect_path; } if (!isset($_POST['ftp_username'])) { $_POST['ftp_username'] = $username; } // Set the username etc, into context. $incontext['ftp'] = array('server' => isset($_POST['ftp_server']) ? $_POST['ftp_server'] : 'localhost', 'port' => isset($_POST['ftp_port']) ? $_POST['ftp_port'] : '21', 'username' => isset($_POST['ftp_username']) ? $_POST['ftp_username'] : '', 'path' => isset($_POST['ftp_path']) ? $_POST['ftp_path'] : '/', 'path_msg' => !empty($found_path) ? $txt['ftp_path_found_info'] : $txt['ftp_path_info']); return false; } else { $_SESSION['installer_temp_ftp'] = array('server' => $_POST['ftp_server'], 'port' => $_POST['ftp_port'], 'username' => $_POST['ftp_username'], 'password' => $_POST['ftp_password'], 'path' => $_POST['ftp_path']); $failed_files_updated = array(); foreach ($failed_files as $file) { if (!is_writable(dirname(__FILE__) . '/' . $file)) { $ftp->chmod($file, 0755); } if (!is_writable(dirname(__FILE__) . '/' . $file)) { $ftp->chmod($file, 0777); } if (!is_writable(dirname(__FILE__) . '/' . $file)) { $failed_files_updated[] = $file; $incontext['ftp_errors'][] = rtrim($ftp->last_message) . ' -> ' . $file . "\n"; } } $ftp->close(); // Are there any errors left? if (count($failed_files_updated) >= 1) { // Guess there are... $incontext['failed_files'] = $failed_files_updated; // Set the username etc, into context. $incontext['ftp'] = $_SESSION['installer_temp_ftp'] += array('path_msg' => $txt['ftp_path_info']); return false; } } } return true; }
function PackageServers() { global $txt, $scripturl, $context, $boarddir, $sourcedir, $modSettings, $db_prefix; // Ensure we use the correct template, and page title. $context['sub_template'] = 'servers'; $context['page_title'] .= ' - ' . $txt['download_packages']; // Load the list of servers. $request = db_query("\n\t\tSELECT ID_SERVER, name, url\n\t\tFROM {$db_prefix}package_servers", __FILE__, __LINE__); $context['servers'] = array(); while ($row = mysql_fetch_assoc($request)) { $context['servers'][] = array('name' => $row['name'], 'url' => $row['url'], 'id' => $row['ID_SERVER']); } mysql_free_result($request); $context['package_download_broken'] = !is_writable($boarddir . '/Packages') || !is_writable($boarddir . '/Packages/installed.list'); if ($context['package_download_broken']) { @chmod($boarddir . '/Packages', 0777); @chmod($boarddir . '/Packages/installed.list', 0777); } $context['package_download_broken'] = !is_writable($boarddir . '/Packages') || !is_writable($boarddir . '/Packages/installed.list'); if ($context['package_download_broken']) { if (isset($_POST['ftp_username'])) { $ftp = new ftp_connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']); if ($ftp->error === false) { // I know, I know... but a lot of people want to type /home/xyz/... which is wrong, but logical. if (!$ftp->chdir($_POST['ftp_path'])) { $ftp_error = $ftp->error; $ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $_POST['ftp_path'])); } } } if (!isset($ftp) || $ftp->error !== false) { if (!isset($ftp)) { $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 || !isset($_POST['ftp_path'])) { $_POST['ftp_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); } else { $context['package_download_broken'] = false; $ftp->chmod('Packages', 0777); $ftp->chmod('Packages/installed.list', 0777); $ftp->close(); } } }
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 PackagePermissions() { global $context, $txt, $modSettings, $boarddir, $sourcedir, $cachedir, $package_ftp; // Let's try and be good, yes? checkSession('get'); // If we're restoring permissions this is just a pass through really. if (isset($_GET['restore'])) { create_chmod_control(array(), array(), true); fatal_lang_error('no_access', false); } // This is a memory eat. @ini_set('memory_limit', '128M'); @set_time_limit(600); // Load up some FTP stuff. create_chmod_control(); if (empty($package_ftp) && !isset($_POST['skip_ftp'])) { loadClassFile('Class-Package.php'); $ftp = new ftp_connection(null); list($username, $detect_path, $found_path) = $ftp->detect_path($boarddir); $context['package_ftp'] = array('server' => isset($modSettings['package_server']) ? $modSettings['package_server'] : 'localhost', 'port' => isset($modSettings['package_port']) ? $modSettings['package_port'] : '21', 'username' => empty($username) ? isset($modSettings['package_username']) ? $modSettings['package_username'] : '' : $username, 'path' => $detect_path, 'form_elements_only' => true); } else { $context['ftp_connected'] = true; } // Define the template. $context['page_title'] = $txt['package_file_perms']; $context['sub_template'] = 'file_permissions'; // Define what files we're interested in, as a tree. $context['file_tree'] = array(strtr($boarddir, array('\\' => '/')) => array('type' => 'dir', 'contents' => array('agreement.txt' => array('type' => 'file', 'writable_on' => 'standard'), 'Settings.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'Settings_bak.php' => array('type' => 'file', 'writable_on' => 'restrictive'), 'attachments' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'avatars' => array('type' => 'dir', 'writable_on' => 'standard'), 'cache' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'custom_avatar_dir' => array('type' => 'dir', 'writable_on' => 'restrictive'), 'Smileys' => array('type' => 'dir_recursive', 'writable_on' => 'standard'), 'Sources' => array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard'), 'Themes' => array('type' => 'dir_recursive', 'writable_on' => 'standard', 'contents' => array('default' => array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))))), 'Packages' => array('type' => 'dir', 'writable_on' => 'standard', 'contents' => array('temp' => array('type' => 'dir'), 'backup' => array('type' => 'dir'), 'installed.list' => array('type' => 'file', 'writable_on' => 'standard')))))); // Directories that can move. if (substr($sourcedir, 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Sources']); $context['file_tree'][strtr($sourcedir, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => true, 'writable_on' => 'standard'); } // Moved the cache? if (substr($cachedir, 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['cache']); $context['file_tree'][strtr($cachedir, array('\\' => '/'))] = array('type' => 'dir', 'list_contents' => false, 'writable_on' => 'restrictive'); } // Are we using multiple attachment directories? if (!empty($modSettings['currentAttachmentUploadDir'])) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['attachments']); if (!is_array($modSettings['attachmentUploadDir'])) { $modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']); } // !!! Should we suggest non-current directories be read only? foreach ($modSettings['attachmentUploadDir'] as $dir) { $context['file_tree'][strtr($dir, array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } } elseif (substr($modSettings['attachmentUploadDir'], 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['attachments']); $context['file_tree'][strtr($modSettings['attachmentUploadDir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } if (substr($modSettings['smileys_dir'], 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Smileys']); $context['file_tree'][strtr($modSettings['smileys_dir'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'writable_on' => 'standard'); } if (substr($modSettings['avatar_directory'], 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['avatars']); $context['file_tree'][strtr($modSettings['avatar_directory'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'standard'); } if (isset($modSettings['custom_avatar_dir']) && substr($modSettings['custom_avatar_dir'], 0, strlen($boarddir)) != $boarddir) { unset($context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['custom_avatar_dir']); $context['file_tree'][strtr($modSettings['custom_avatar_dir'], array('\\' => '/'))] = array('type' => 'dir', 'writable_on' => 'restrictive'); } // Load up any custom themes. $request = smf_db_query(' SELECT value FROM {db_prefix}themes WHERE id_theme > {int:default_theme_id} AND id_member = {int:guest_id} AND variable = {string:theme_dir} ORDER BY value ASC', array('default_theme_id' => 1, 'guest_id' => 0, 'theme_dir' => 'theme_dir')); while ($row = mysql_fetch_assoc($request)) { if (substr(strtolower(strtr($row['value'], array('\\' => '/'))), 0, strlen($boarddir) + 7) == strtolower(strtr($boarddir, array('\\' => '/')) . '/Themes')) { $context['file_tree'][strtr($boarddir, array('\\' => '/'))]['contents']['Themes']['contents'][substr($row['value'], strlen($boarddir) + 8)] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))); } else { $context['file_tree'][strtr($row['value'], array('\\' => '/'))] = array('type' => 'dir_recursive', 'list_contents' => true, 'contents' => array('languages' => array('type' => 'dir', 'list_contents' => true))); } } mysql_free_result($request); // If we're submitting then let's move on to another function to keep things cleaner.. if (isset($_POST['action_changes'])) { return PackagePermissionsAction(); } $context['look_for'] = array(); // Are we looking for a particular tree - normally an expansion? if (!empty($_REQUEST['find'])) { $context['look_for'][] = base64_decode($_REQUEST['find']); } // Only that tree? $context['only_find'] = isset($_GET['xml']) && !empty($_REQUEST['onlyfind']) ? $_REQUEST['onlyfind'] : ''; if ($context['only_find']) { $context['look_for'][] = $context['only_find']; } // Have we got a load of back-catalogue trees to expand from a submit etc? if (!empty($_GET['back_look'])) { $potententialTrees = unserialize(base64_decode($_GET['back_look'])); foreach ($potententialTrees as $tree) { $context['look_for'][] = $tree; } } // ... maybe posted? if (!empty($_POST['back_look'])) { $context['only_find'] = array_merge($context['only_find'], $_POST['back_look']); } $context['back_look_data'] = base64_encode(serialize(array_slice($context['look_for'], 0, 15))); // Are we finding more files than first thought? $context['file_offset'] = !empty($_REQUEST['fileoffset']) ? (int) $_REQUEST['fileoffset'] : 0; // Don't list more than this many files in a directory. $context['file_limit'] = 150; // How many levels shall we show? $context['default_level'] = empty($context['only_find']) ? 2 : 25; // This will be used if we end up catching XML data. $context['xml_data'] = array('roots' => array('identifier' => 'root', 'children' => array(array('value' => preg_replace('~[^A-Za-z0-9_\\-=:]~', ':-:', $context['only_find'])))), 'folders' => array('identifier' => 'folder', 'children' => array())); foreach ($context['file_tree'] as $path => $data) { // Run this directory. if (file_exists($path) && (empty($context['only_find']) || substr($context['only_find'], 0, strlen($path)) == $path)) { // Get the first level down only. fetchPerms__recursive($path, $context['file_tree'][$path], 1); $context['file_tree'][$path]['perms'] = array('chmod' => @is_writable($path), 'perms' => @fileperms($path)); } else { unset($context['file_tree'][$path]); } } // Is this actually xml? if (isset($_GET['xml'])) { loadTemplate('Xml'); $context['sub_template'] = 'generic_xml'; $context['template_layers'] = array(); } }
function doStep1() { global $txt, $ftp; // Remember if they agreed (even if they are only verifying.) if (isset($_POST['agree'])) { $_SESSION['webinstall_state']['agree'] = true; } if (!empty($_POST['verify']) || !empty($_POST['member_username']) && !empty($_POST['member_password'])) { $pass_data = 'web_user='******'member_username']) . '&check&web_pass='******'member_username']) . $_POST['member_password']) . 'w$--IN5~2a'); $data = (int) fetch_web_data('http://download.simplemachines.org/index.php', $pass_data . '&verify=1'); $_SESSION['webinstall_state']['is_logged_in'] = !empty($data); $_SESSION['webinstall_state']['is_charter'] = $data === 2; $_SESSION['webinstall_state']['is_beta_tester'] = $data === 3; $_SESSION['webinstall_state']['is_team'] = $data === 4; if ($_SESSION['webinstall_state']['is_team']) { $_SESSION['webinstall_state']['access'] = array(0, 1, 2); } elseif ($_SESSION['webinstall_state']['is_charter'] || $_SESSION['webinstall_state']['is_beta_tester']) { $_SESSION['webinstall_state']['access'] = array(0, 2); } else { $_SESSION['webinstall_state']['access'] = array(0); } $_SESSION['webinstall_state']['can_svn'] = $_SESSION['webinstall_state']['is_team'] || $_SESSION['webinstall_state']['is_beta_tester']; $_SESSION['webinstall_state']['user_data'] = $_SESSION['webinstall_state']['is_logged_in'] ? '?' . $pass_data : ''; $_SESSION['webinstall_state']['member_info'] = $_SESSION['webinstall_state']['can_svn'] ? array($_POST['member_username'], $_POST['member_password']) : array(); if (empty($data)) { echo ' <br /> <div class="error_message" style="margin: 0 1ex 2ex 1ex;"> <div style="float: left; width: 2ex; font-size: 2em; color: red;">X</div> ', $txt['error_not_member'], ' </div>'; } return doStep0(); } elseif (isset($_GET['logout'])) { $_SESSION['webinstall_state']['is_logged_in'] = false; $_SESSION['webinstall_state']['is_charter'] = false; $_SESSION['webinstall_state']['is_beta_tester'] = false; $_SESSION['webinstall_state']['is_team'] = false; $_SESSION['webinstall_state']['access'] = array(0); $_SESSION['webinstall_state']['can_svn'] = false; $_SESSION['webinstall_state']['user_data'] = ''; return doStep0(); } // Perhaps they don't want to use a chmod of 777. if (isset($_REQUEST['chmod']) && is_numeric($_REQUEST['chmod'])) { // Make sure they passed us a valid mode. if (preg_match('~^([0]?[0-7]{3})$~', $_REQUEST['chmod']) !== 0) { $_SESSION['webinstall_state']['chmod'] = octdec($_REQUEST['chmod']); } } if (!isset($_SESSION['webinstall_state']['chmod'])) { $_SESSION['webinstall_state']['chmod'] = 0777; } if (empty($_SESSION['webinstall_state']['agree'])) { echo ' <br /> <div style="margin: 0 1ex 2ex 1ex; padding: 1.5ex; border: 2px dashed #cc5566; background-color: #ffd9df;"> <div style="float: left; width: 2ex; font-size: 2em; color: red;">X</div> <div style="padding: 1ex;">', $txt['error_read_the_license'], '</div> </div>'; return doStep0(); } if (!empty($_POST['mirror'])) { // Verify mirror. $install_info = fetch_install_info(); if (!isset($install_info['mirrors'][$_POST['mirror']])) { die('Security error.'); } // Build file list ;). $files_to_download = array(); if (function_exists('gzinflate')) { $ext = '.tar.gz'; } else { $ext = '.tar'; } if (file_exists(dirname(__FILE__) . '/Settings.php') && !file_exists(dirname(__FILE__) . '/install.php')) { $type = 'upgrade'; } else { $type = 'install'; } if (!empty($_SESSION['webinstall_state']['can_svn']) && !empty($_POST['use_svn'])) { // SVN files only have the branch numbers on them and not the actual version. preg_match('~(smf_[\\d]-[\\d])(.*)~', $_POST['filename'], $match); $_POST['filename_unmodified'] = $_POST['filename']; $_POST['filename'] = $match[1] . '-dev' . strftime('%Y%m%d') . '_'; $_POST['mirror'] = 'https://devel.simplemachines.org/mkbuild/release/'; } $files_to_download[] = $_POST['mirror'] . $_POST['filename'] . $type . $ext; if (isset($_POST['languages'])) { $version_selected = str_replace('SMF ', '', $_SESSION['webinstall_state']['install_info']['install'][isset($_POST['filename_unmodified']) ? $_POST['filename_unmodified'] : $_POST['filename']]); foreach ($_POST['languages'] as $lang) { if (isset($_SESSION['webinstall_state']['install_info']['languages'][$lang]) && in_array($version_selected, $_SESSION['webinstall_state']['install_info']['languages'][$lang]['versions'])) { $files_to_download[] = $_POST['mirror'] . $_POST['filename'] . $lang . $ext; } } } $_SESSION['webinstall_state']['files_to_download'] = $files_to_download; $_SESSION['webinstall_state']['files_to_download_total'] = count($files_to_download); } // Windows isn't helped by chmod settings and FTP. if (strpos(__FILE__, ':\\') === 1) { return doStep2(); } if (!isset($ftp)) { $ftp = new ftp_connection(null); } elseif ($ftp->error !== false) { $ftp_error = $ftp->last_message === null ? '' : $ftp->last_message; } list($username, $detect_path, $found_path) = $ftp->detect_path(dirname(__FILE__)); if ($found_path || !isset($_POST['ftp_path'])) { $_POST['ftp_path'] = $detect_path; } if (!isset($_POST['ftp_username'])) { $_POST['ftp_username'] = $username; } echo ' <form action="', $_SERVER['PHP_SELF'], '?step=2" method="post"> <div class="panel"> <h2>', $txt['ftp_login'], '</h2> <h3>', $txt['ftp_login_info'], '</h3>'; if (isset($ftp_error)) { echo ' <div class="error_message"> <div> ', $txt['error_ftp_no_connect'], '<br /> <br /> <code>', $ftp_error, '</code> </div> </div> <br />'; } echo ' <div style="margin: 0 1ex 2ex 1ex; padding: 1.5ex; border: 2px dashed #33cc44; background-color: #dfffe9;"> <div style="float: left; width: 1.5ex; font-size: 2em; color: #33cc44;">!</div> ', $txt['ftp_please_note'], ' </div> <table width="520" cellspacing="0" cellpadding="0" border="0" align="center" style="margin-bottom: 1ex;"> <tr> <td width="26%" valign="top" class="textbox"><label for="ftp_server">', $txt['ftp_server'], ':</label></td> <td> <div style="float: right; margin-right: 1px;"><label for="ftp_port" class="textbox"><strong>', $txt['ftp_port'], ': </strong></label> <input type="text" size="3" name="ftp_port" id="ftp_port" value="', isset($_POST['ftp_port']) ? $_POST['ftp_port'] : '21', '" /></div> <input type="text" size="30" name="ftp_server" id="ftp_server" value="', isset($_POST['ftp_server']) ? $_POST['ftp_server'] : 'localhost', '" style="width: 70%;" /> <div style="font-size: smaller; margin-bottom: 2ex;">', $txt['ftp_server_info'], '</div> </td> </tr><tr> <td width="26%" valign="top" class="textbox"><label for="ftp_username">', $txt['ftp_username'], ':</label></td> <td> <input type="text" size="50" name="ftp_username" id="ftp_username" value="', isset($_POST['ftp_username']) ? $_POST['ftp_username'] : '', '" style="width: 99%;" /> <div style="font-size: smaller; margin-bottom: 2ex;">', $txt['ftp_username_info'], '</div> </td> </tr><tr> <td width="26%" valign="top" class="textbox"><label for="ftp_password">', $txt['ftp_password'], ':</label></td> <td> <input type="password" size="50" name="ftp_password" id="ftp_password" style="width: 99%;" /> <div style="font-size: smaller; margin-bottom: 3ex;">', $txt['ftp_password_info'], '</div> </td> </tr><tr> <td width="26%" valign="top" class="textbox"><label for="ftp_path">', $txt['ftp_path'], ':</label></td> <td style="padding-bottom: 1ex;"> <input type="text" size="50" name="ftp_path" id="ftp_path" value="', $_POST['ftp_path'], '" style="width: 99%;" /> <div style="font-size: smaller; margin-bottom: 2ex;">', !empty($found_path) ? $txt['ftp_path_found_info'] : $txt['ftp_path_info'], '</div> </td> </tr> </table> <div class="righttext" style="margin: 1ex;"><input type="submit" value="', $txt['ftp_connect'], '" /></div> </div>'; }
function make_files_writable() { global $txt; $writable_files = array('attachments', 'avatars', 'Packages', 'Packages/installed.list', 'Smileys', 'Themes', 'agreement.txt', 'Settings.php', 'Settings_bak.php'); $extra_files = array('Themes/classic/index.template.php', 'Themes/classic/style.css'); foreach ($GLOBALS['detected_languages'] as $lang => $temp) { $extra_files[] = 'Themes/default/languages/' . $lang; } $failure = false; // With mod_security installed, we could attempt to fix it with .htaccess. if (function_exists('apache_get_modules') && in_array('mod_security', apache_get_modules())) { $writable_files[] = file_exists(dirname(__FILE__) . '/.htaccess') ? '.htaccess' : '.'; } // On linux, it's easy - just use is_writable! if (substr(__FILE__, 1, 2) != ':\\') { foreach ($writable_files as $file) { if (!is_writable(dirname(__FILE__) . '/' . $file)) { @chmod(dirname(__FILE__) . '/' . $file, 0755); // Well, 755 hopefully worked... if not, try 777. $failure |= !is_writable(dirname(__FILE__) . '/' . $file) && !@chmod(dirname(__FILE__) . '/' . $file, 0777); } } foreach ($extra_files as $file) { @chmod(dirname(__FILE__) . (empty($file) ? '' : '/' . $file), 0777); } } else { foreach ($writable_files as $file) { // Folders can't be opened for write... but the index.php in them can ;). if (is_dir(dirname(__FILE__) . '/' . $file)) { $file .= '/index.php'; } // Funny enough, chmod actually does do something on windows - it removes the read only attribute. @chmod(dirname(__FILE__) . '/' . $file, 0777); $fp = @fopen(dirname(__FILE__) . '/' . $file, 'r+'); // Hmm, okay, try just for write in that case... if (!$fp) { $fp = @fopen(dirname(__FILE__) . '/' . $file, 'w'); } $failure |= !$fp; @fclose($fp); } foreach ($extra_files as $file) { @chmod(dirname(__FILE__) . (empty($file) ? '' : '/' . $file), 0777); } } if (!isset($_SERVER)) { return !$failure; } // It's not going to be possible to use FTP on windows to solve the problem... if ($failure && substr(__FILE__, 1, 2) == ':\\') { echo ' <div class="error_message"> <div style="color: red;">', $txt['error_windows_chmod'], '</div> <ul style="margin: 2.5ex; font-family: monospace;"> <li>', implode('</li> <li>', $writable_files), '</li> </ul> <a href="', $_SERVER['PHP_SELF'], '?step=0&overphp=true">', $txt['error_message_click'], '</a> ', $txt['error_message_try_again'], ' </div>'; return false; } elseif ($failure) { // Load any session data we might have... if (!isset($_POST['ftp_username']) && isset($_SESSION['installer_temp_ftp'])) { $_POST['ftp_server'] = $_SESSION['installer_temp_ftp']['server']; $_POST['ftp_port'] = $_SESSION['installer_temp_ftp']['port']; $_POST['ftp_username'] = $_SESSION['installer_temp_ftp']['username']; $_POST['ftp_password'] = $_SESSION['installer_temp_ftp']['password']; $_POST['ftp_path'] = $_SESSION['installer_temp_ftp']['path']; } if (isset($_POST['ftp_username'])) { $ftp = new ftp_connection($_POST['ftp_server'], $_POST['ftp_port'], $_POST['ftp_username'], $_POST['ftp_password']); if ($ftp->error === false) { // Try it without /home/abc just in case they messed up. 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)) { $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(dirname(__FILE__)); if ($found_path || !isset($_POST['ftp_path'])) { $_POST['ftp_path'] = $detect_path; } if (!isset($_POST['ftp_username'])) { $_POST['ftp_username'] = $username; } echo ' <div class="panel"> <h2>', $txt['ftp_setup'], '</h2> <h3>', $txt['ftp_setup_info'], '</h3>'; if (isset($ftp_error)) { echo ' <div class="error_message"> <div style="color: red;"> ', $txt['error_ftp_no_connect'], '<br /> <br /> <code>', $ftp_error, '</code> </div> </div> <br />'; } echo ' <form action="', $_SERVER['PHP_SELF'], '?step=0&overphp=true" method="post"> <table width="520" cellspacing="0" cellpadding="0" border="0" align="center" style="margin-bottom: 1ex;"> <tr> <td width="26%" valign="top" class="textbox"><label for="ftp_server">', $txt['ftp_server'], ':</label></td> <td> <div style="float: ', empty($txt['lang_rtl']) ? 'right' : 'left', '; margin-', empty($txt['lang_rtl']) ? 'right' : 'left', ': 1px;"><label for="ftp_port" class="textbox"><b>', $txt['ftp_port'], ': </b></label> <input type="text" size="3" name="ftp_port" id="ftp_port" value="', isset($_POST['ftp_port']) ? $_POST['ftp_port'] : '21', '" /></div> <input type="text" size="30" name="ftp_server" id="ftp_server" value="', isset($_POST['ftp_server']) ? $_POST['ftp_server'] : 'localhost', '" style="width: 70%;" /> <div style="font-size: smaller; margin-bottom: 2ex;">', $txt['ftp_server_info'], '</div> </td> </tr><tr> <td width="26%" valign="top" class="textbox"><label for="ftp_username">', $txt['ftp_username'], ':</label></td> <td> <input type="text" size="50" name="ftp_username" id="ftp_username" value="', isset($_POST['ftp_username']) ? $_POST['ftp_username'] : '', '" style="width: 99%;" /> <div style="font-size: smaller; margin-bottom: 2ex;">', $txt['ftp_username_info'], '</div> </td> </tr><tr> <td width="26%" valign="top" class="textbox"><label for="ftp_password">', $txt['ftp_password'], ':</label></td> <td> <input type="password" size="50" name="ftp_password" id="ftp_password" style="width: 99%;" /> <div style="font-size: smaller; margin-bottom: 3ex;">', $txt['ftp_password_info'], '</div> </td> </tr><tr> <td width="26%" valign="top" class="textbox"><label for="ftp_path">', $txt['ftp_path'], ':</label></td> <td style="padding-bottom: 1ex;"> <input type="text" size="50" name="ftp_path" id="ftp_path" value="', $_POST['ftp_path'], '" style="width: 99%;" /> <div style="font-size: smaller; margin-bottom: 2ex;">', !empty($found_path) ? $txt['ftp_path_found_info'] : $txt['ftp_path_info'], '</div> </td> </tr> </table> <div style="margin: 1ex; margin-top: 2ex; text-align: ', empty($txt['lang_rtl']) ? 'right' : 'left', ';"><input type="submit" value="', $txt['ftp_connect'], '" /></div> </form> <h2>', $txt['ftp_setup_why'], '</h2> <h3>', $txt['ftp_setup_why_info'], '</h3> <ul style="margin: 2.5ex; font-family: monospace;"> <li>', implode('</li> <li>', $writable_files), '</li> </ul> <a href="', $_SERVER['PHP_SELF'], '?step=0&overphp=true">', $txt['error_message_click'], '</a> ', $txt['ftp_setup_again'], ' </div>'; return false; } else { $_SESSION['installer_temp_ftp'] = array('server' => $_POST['ftp_server'], 'port' => $_POST['ftp_port'], 'username' => $_POST['ftp_username'], 'password' => $_POST['ftp_password'], 'path' => $_POST['ftp_path']); foreach ($writable_files as $file) { if (!is_writable(dirname(__FILE__) . '/' . $file)) { $ftp->chmod($file, 0755); } if (!is_writable(dirname(__FILE__) . '/' . $file)) { $ftp->chmod($file, 0777); } } $ftp->close(); } } return true; }
function makeFilesWritable(&$files) { global $upcontext, $boarddir; if (empty($files)) { return true; } $failure = false; // On linux, it's easy - just use is_writable! if (substr(__FILE__, 1, 2) != ':\\') { foreach ($files as $k => $file) { if (!is_writable($file)) { @chmod($file, 0755); // Well, 755 hopefully worked... if not, try 777. if (!is_writable($file) && !@chmod($file, 0777)) { $failure = true; } else { unset($files[$k]); } } else { unset($files[$k]); } } } else { foreach ($files as $k => $file) { // Folders can't be opened for write... but the index.php in them can ;). if (is_dir($file)) { $file .= '/index.php'; } // Funny enough, chmod actually does do something on windows - it removes the read only attribute. @chmod($file, 0777); $fp = @fopen($file, 'r+'); // Hmm, okay, try just for write in that case... if (!$fp) { $fp = @fopen($file, 'w'); } if (!$fp) { $failure = true; } else { unset($files[$k]); } @fclose($fp); } } if (empty($files)) { return true; } if (!isset($_SERVER)) { return !$failure; } // What still needs to be done? $upcontext['chmod']['files'] = $files; // If it's windows it's a mess... if ($failure && substr(__FILE__, 1, 2) == ':\\') { $upcontext['chmod']['ftp_error'] = 'total_mess'; return false; } elseif ($failure) { // Load any session data we might have... if (!isset($_POST['ftp_username']) && isset($_SESSION['installer_temp_ftp'])) { $upcontext['chmod']['server'] = $_SESSION['installer_temp_ftp']['server']; $upcontext['chmod']['port'] = $_SESSION['installer_temp_ftp']['port']; $upcontext['chmod']['username'] = $_SESSION['installer_temp_ftp']['username']; $upcontext['chmod']['password'] = $_SESSION['installer_temp_ftp']['password']; $upcontext['chmod']['path'] = $_SESSION['installer_temp_ftp']['path']; } elseif (isset($_POST['ftp_username'])) { $upcontext['chmod']['server'] = $_POST['ftp_server']; $upcontext['chmod']['port'] = $_POST['ftp_port']; $upcontext['chmod']['username'] = $_POST['ftp_username']; $upcontext['chmod']['password'] = $_POST['ftp_password']; $upcontext['chmod']['path'] = $_POST['ftp_path']; } if (isset($upcontext['chmod']['username'])) { $ftp = new ftp_connection($upcontext['chmod']['server'], $upcontext['chmod']['port'], $upcontext['chmod']['username'], $upcontext['chmod']['password']); if ($ftp->error === false) { // Try it without /home/abc just in case they messed up. if (!$ftp->chdir($upcontext['chmod']['path'])) { $upcontext['chmod']['ftp_error'] = $ftp->last_message; $ftp->chdir(preg_replace('~^/home[2]?/[^/]+?~', '', $upcontext['chmod']['path'])); } } } if (!isset($ftp) || $ftp->error !== false) { if (!isset($ftp)) { $ftp = new ftp_connection(null); } elseif ($ftp->error !== false && !isset($upcontext['chmod']['ftp_error'])) { $upcontext['chmod']['ftp_error'] = $ftp->last_message === null ? '' : $ftp->last_message; } list($username, $detect_path, $found_path) = $ftp->detect_path(dirname(__FILE__)); if ($found_path || !isset($upcontext['chmod']['path'])) { $upcontext['chmod']['path'] = $detect_path; } if (!isset($upcontext['chmod']['username'])) { $upcontext['chmod']['username'] = $username; } return false; } else { // We want to do a relative path for FTP. if (!in_array($upcontext['chmod']['path'], array('', '/'))) { $ftp_root = strtr($boarddir, array($upcontext['chmod']['path'] => '')); if (substr($ftp_root, -1) == '/' && ($upcontext['chmod']['path'] == '' || substr($upcontext['chmod']['path'], 0, 1) == '/')) { $ftp_root = substr($ftp_root, 0, -1); } } else { $ftp_root = $boarddir; } // Save the info for next time! $_SESSION['installer_temp_ftp'] = array('server' => $upcontext['chmod']['server'], 'port' => $upcontext['chmod']['port'], 'username' => $upcontext['chmod']['username'], 'password' => $upcontext['chmod']['password'], 'path' => $upcontext['chmod']['path'], 'root' => $ftp_root); foreach ($files as $k => $file) { if (!is_writable($file)) { $ftp->chmod($file, 0755); } if (!is_writable($file)) { $ftp->chmod($file, 0777); } // Assuming that didn't work calculate the path without the boarddir. if (!is_writable($file)) { if (strpos($file, $boarddir) === 0) { $ftp_file = strtr($file, array($_SESSION['installer_temp_ftp']['root'] => '')); $ftp->chmod($ftp_file, 0755); if (!is_writable($file)) { $ftp->chmod($ftp_file, 0777); } // Sometimes an extra slash can help... $ftp_file = '/' . $ftp_file; if (!is_writable($file)) { $ftp->chmod($ftp_file, 0755); } if (!is_writable($file)) { $ftp->chmod($ftp_file, 0777); } } } if (is_writable($file)) { unset($files[$k]); } } $ftp->close(); } } // What remains? $upcontext['chmod']['files'] = $files; if (empty($files)) { return true; } return false; }