Beispiel #1
0
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'];
}
Beispiel #2
0
function parseBoardMod($file, $testing = true, $undo = false, $theme_paths = array())
{
    global $boarddir, $sourcedir, $settings, $txt, $modSettings;
    @set_time_limit(600);
    $file = strtr($file, array("\r" => ''));
    $working_file = null;
    $working_search = null;
    $working_data = '';
    $replace_with = null;
    $actions = array();
    $everything_found = true;
    // This holds all the template changes in the standard mod file.
    $template_changes = array();
    // This is just the temporary file.
    $temp_file = $file;
    // This holds the actual changes on a step counter basis.
    $temp_changes = array();
    $counter = 0;
    $step_counter = 0;
    // Before we do *anything*, let's build a list of what we're editing, as it's going to be used for other theme edits.
    while (preg_match('~<(edit file|file|search|search for|add|add after|replace|add before|add above|above|before)>\\n(.*?)\\n</\\1>~is', $temp_file, $code_match) != 0) {
        $counter++;
        // Get rid of the old stuff.
        $temp_file = substr_replace($temp_file, '', strpos($temp_file, $code_match[0]), strlen($code_match[0]));
        // No interest to us?
        if ($code_match[1] != 'edit file' && $code_match[1] != 'file') {
            // It's a step, let's add that to the current steps.
            if (isset($temp_changes[$step_counter])) {
                $temp_changes[$step_counter]['changes'][] = $code_match[0];
            }
            continue;
        }
        // We've found a new edit - let's make ourself heard, kind of.
        $step_counter = $counter;
        $temp_changes[$step_counter] = array('title' => $code_match[0], 'changes' => array());
        $filename = parse_path($code_match[2]);
        // Now, is this a template file, and if so, which?
        foreach ($theme_paths as $id => $theme) {
            // If this filename is relative, if so take a guess at what it should be.
            if (strpos($filename, 'Themes') === 0) {
                $filename = $boarddir . '/' . $filename;
            }
            if (strpos($filename, $theme['theme_dir']) === 0) {
                $template_changes[$id][$counter] = substr($filename, strlen($theme['theme_dir']) + 1);
            }
        }
    }
    // Anything above $counter must be for custom themes.
    $custom_template_begin = $counter;
    // Reference for what theme ID this action belongs to.
    $theme_id_ref = array();
    // Now we know what templates we need to touch, cycle through each theme and work out what we need to edit.
    if (!empty($template_changes[1])) {
        foreach ($theme_paths as $id => $theme) {
            // Don't do default, it means nothing to me.
            if ($id == 1) {
                continue;
            }
            // Now, for each file do we need to edit it?
            foreach ($template_changes[1] as $pos => $template_file) {
                // It does? Add it to the list darlin'.
                if (file_exists($theme['theme_dir'] . '/' . $template_file) && (!isset($template_changes[$id][$pos]) || !in_array($template_file, $template_changes[$id][$pos]))) {
                    // Actually add it to the mod file too, so we can see that it will work ;)
                    if (!empty($temp_changes[$pos]['changes'])) {
                        $file .= "\n\n" . '<edit file>' . "\n" . $theme['theme_dir'] . '/' . $template_file . "\n" . '</edit file>' . "\n\n" . implode("\n\n", $temp_changes[$pos]['changes']);
                        $theme_id_ref[$counter] = $id;
                        $counter += 1 + count($temp_changes[$pos]['changes']);
                    }
                }
            }
        }
    }
    $counter = 0;
    $is_custom = 0;
    while (preg_match('~<(edit file|file|search|search for|add|add after|replace|add before|add above|above|before)>\\n(.*?)\\n</\\1>~is', $file, $code_match) != 0) {
        // This is for working out what we should be editing.
        $counter++;
        // Edit a specific file.
        if ($code_match[1] == 'file' || $code_match[1] == 'edit file') {
            // Backup the old file.
            if ($working_file !== null) {
                package_chmod($working_file);
                // Don't even dare.
                if (basename($working_file) == 'Settings_bak.php') {
                    continue;
                }
                if (!is_writable($working_file)) {
                    $actions[] = array('type' => 'chmod', 'filename' => $working_file);
                }
                if (!$testing && !empty($modSettings['package_make_backups']) && file_exists($working_file)) {
                    if (basename($working_file) == 'Settings.php') {
                        @copy($working_file, dirname($working_file) . '/Settings_bak.php');
                    } else {
                        @copy($working_file, $working_file . '~');
                    }
                }
                package_put_contents($working_file, $working_data, $testing);
            }
            if ($working_file !== null) {
                $actions[] = array('type' => 'saved', 'filename' => $working_file, 'is_custom' => $is_custom);
            }
            // Is this "now working on" file a theme specific one?
            $is_custom = isset($theme_id_ref[$counter - 1]) ? $theme_id_ref[$counter - 1] : 0;
            // Make sure the file exists!
            $working_file = parse_path($code_match[2]);
            if ($working_file[0] != '/' && $working_file[1] != ':') {
                trigger_error('parseBoardMod(): The filename \'' . $working_file . '\' is not a full path!', E_USER_WARNING);
                $working_file = $boarddir . '/' . $working_file;
            }
            if (!file_exists($working_file)) {
                $places_to_check = array($boarddir, $sourcedir, $settings['default_theme_dir'], $settings['default_theme_dir'] . '/languages');
                foreach ($places_to_check as $place) {
                    if (file_exists($place . '/' . $working_file)) {
                        $working_file = $place . '/' . $working_file;
                        break;
                    }
                }
            }
            if (file_exists($working_file)) {
                // Load the new file.
                $working_data = str_replace("\r", '', package_get_contents($working_file));
                $actions[] = array('type' => 'opened', 'filename' => $working_file);
            } else {
                $actions[] = array('type' => 'missing', 'filename' => $working_file);
                $working_file = null;
                $everything_found = false;
            }
            // Can't be searching for something...
            $working_search = null;
        } elseif (($code_match[1] == 'search' || $code_match[1] == 'search for') && $working_file !== null) {
            if ($working_search !== null) {
                $actions[] = array('type' => 'error', 'filename' => $working_file);
                $everything_found = false;
            }
            $working_search = $code_match[2];
        } elseif ($working_search !== null) {
            // This is the base string....
            $replace_with = $code_match[2];
            // Add this afterward...
            if ($code_match[1] == 'add' || $code_match[1] == 'add after') {
                $replace_with = $working_search . "\n" . $replace_with;
            } elseif ($code_match[1] == 'before' || $code_match[1] == 'add before' || $code_match[1] == 'above' || $code_match[1] == 'add above') {
                $replace_with .= "\n" . $working_search;
            }
            // Otherwise.. replace with $replace_with ;).
        }
        // If we have a search string, replace string, and open file..
        if ($working_search !== null && $replace_with !== null && $working_file !== null) {
            // Make sure it's somewhere in the string.
            if ($undo) {
                $temp = $replace_with;
                $replace_with = $working_search;
                $working_search = $temp;
            }
            if (strpos($working_data, $working_search) !== false) {
                $working_data = str_replace($working_search, $replace_with, $working_data);
                $actions[] = array('type' => 'replace', 'filename' => $working_file, 'search' => $working_search, 'replace' => $replace_with, 'search_original' => $working_search, 'replace_original' => $replace_with, 'position' => $code_match[1] == 'replace' ? 'replace' : ($code_match[1] == 'add' || $code_match[1] == 'add after' ? 'before' : 'after'), 'is_custom' => $is_custom, 'failed' => false);
            } else {
                $actions[] = array('type' => 'failure', 'filename' => $working_file, 'search' => $working_search, 'is_custom' => $is_custom, 'search_original' => $working_search, 'replace_original' => $replace_with, 'position' => $code_match[1] == 'replace' ? 'replace' : ($code_match[1] == 'add' || $code_match[1] == 'add after' ? 'before' : 'after'), 'is_custom' => $is_custom, 'failed' => true);
                $everything_found = false;
            }
            // These don't hold any meaning now.
            $working_search = null;
            $replace_with = null;
        }
        // Get rid of the old tag.
        $file = substr_replace($file, '', strpos($file, $code_match[0]), strlen($code_match[0]));
    }
    // Backup the old file.
    if ($working_file !== null) {
        package_chmod($working_file);
        if (!is_writable($working_file)) {
            $actions[] = array('type' => 'chmod', 'filename' => $working_file);
        }
        if (!$testing && !empty($modSettings['package_make_backups']) && file_exists($working_file)) {
            if (basename($working_file) == 'Settings.php') {
                @copy($working_file, dirname($working_file) . '/Settings_bak.php');
            } else {
                @copy($working_file, $working_file . '~');
            }
        }
        package_put_contents($working_file, $working_data, $testing);
    }
    if ($working_file !== null) {
        $actions[] = array('type' => 'saved', 'filename' => $working_file, 'is_custom' => $is_custom);
    }
    $actions[] = array('type' => 'result', 'status' => $everything_found);
    return $actions;
}
Beispiel #3
0
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'];
}
Beispiel #4
0
function FlushInstall()
{
    global $boarddir, $sourcedir;
    // Always check the session.
    checkSession('get');
    include_once $sourcedir . '/lib/Subs-Package.php';
    // Record when we last did this.
    package_put_contents($boarddir . '/Packages/installed.list', time());
    // Set everything as uninstalled.
    smf_db_query('
		UPDATE {db_prefix}log_packages
		SET install_state = {int:not_installed}', array('not_installed' => 0));
    redirectexit('action=admin;area=packages;sa=installed');
}
 /**
  * Empty out the installed list.
  */
 public function action_flush()
 {
     // Always check the session.
     checkSession('get');
     include_once SUBSDIR . '/Package.subs.php';
     // Record when we last did this.
     package_put_contents(BOARDDIR . '/packages/installed.list', time());
     // Set everything as uninstalled.
     setPackagesAsUninstalled();
     redirectexit('action=admin;area=packages;sa=installed');
 }
Beispiel #6
0
function CleanupMods()
{
    global $db_prefix, $modSettings, $upcontext, $boarddir, $sourcedir, $settings, $smcFunc, $command_line;
    // Sorry. Not supported for command line users.
    if ($command_line) {
        return true;
    }
    // Skipping first?
    if (!empty($_POST['skip'])) {
        unset($_POST['skip']);
        return true;
    }
    // If we get here withOUT SSI we need to redirect to ensure we get it!
    if (!isset($_GET['ssi']) || !function_exists('mktree')) {
        redirectLocation('&ssi=1');
    }
    $upcontext['sub_template'] = 'clean_mods';
    $upcontext['page_title'] = 'Cleanup Modifications';
    // This can be skipped.
    $upcontext['skip'] = true;
    // If we're on the second redirect continue...
    if (isset($_POST['cleandone2'])) {
        return true;
    }
    // Do we already know about some writable files?
    if (isset($_POST['writable_files'])) {
        $writable_files = unserialize(base64_decode($_POST['writable_files']));
        if (!makeFilesWritable($writable_files)) {
            // What have we left?
            $upcontext['writable_files'] = $writable_files;
            return false;
        }
    }
    // Load all theme paths....
    $request = $smcFunc['db_query']('', '
		SELECT id_theme, variable, value
		FROM {db_prefix}themes
		WHERE id_member = {int:id_member}
			AND variable IN ({string:theme_dir}, {string:images_url})', array('id_member' => 0, 'theme_dir' => 'theme_dir', 'images_url' => 'images_url', 'db_error_skip' => true));
    $theme_paths = array();
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        if ($row['id_theme'] == 1) {
            $settings['default_' . $row['variable']] = $row['value'];
        } elseif ($row['variable'] == 'theme_dir') {
            $theme_paths[$row['id_theme']][$row['variable']] = $row['value'];
        }
    }
    $smcFunc['db_free_result']($request);
    // Are there are mods installed that may need uninstalling?
    $request = $smcFunc['db_query']('', '
		SELECT id_install, filename, name, themes_installed, version
		FROM {db_prefix}log_packages
		WHERE install_state = {int:installed}
		ORDER BY time_installed DESC', array('installed' => 1, 'db_error_skip' => true));
    $upcontext['packages'] = array();
    while ($row = $smcFunc['db_fetch_assoc']($request)) {
        // Work out the status.
        if (!file_exists($boarddir . '/Packages/' . $row['filename'])) {
            $status = 'Missing';
            $status_color = 'red';
            $result = 'Removed';
        } else {
            $status = 'Installed';
            $status_color = 'green';
            $result = 'No Action Needed';
        }
        $upcontext['packages'][$row['id_install']] = array('id' => $row['id_install'], 'themes' => explode(',', $row['themes_installed']), 'name' => $row['name'], 'filename' => $row['filename'], 'missing_file' => file_exists($boarddir . '/Packages/' . $row['filename']) ? 0 : 1, 'files' => array(), 'file_count' => 0, 'status' => $status, 'result' => $result, 'color' => $status_color, 'version' => $row['version'], 'needs_removing' => false);
    }
    $smcFunc['db_free_result']($request);
    // Don't carry on if there are none.
    if (empty($upcontext['packages'])) {
        return true;
    }
    // Setup some basics.
    if (!empty($upcontext['user']['version'])) {
        $_SESSION['version_emulate'] = $upcontext['user']['version'];
    }
    // Before we get started, don't report notice errors.
    $oldErrorReporting = error_reporting(E_ALL ^ E_NOTICE);
    if (!mktree($boarddir . '/Packages/temp', 0755)) {
        deltree($boarddir . '/Packages/temp', false);
        if (!mktree($boarddir . '/Packages/temp', 0777)) {
            deltree($boarddir . '/Packages/temp', false);
            //!!! Error here - plus chmod!
        }
    }
    // Anything which reinstalled should not have its entry removed.
    $reinstall_worked = array();
    // We're gonna be doing some removin'
    $test = isset($_POST['cleandone']) ? false : true;
    foreach ($upcontext['packages'] as $id => $package) {
        // Can't do anything about this....
        if ($package['missing_file']) {
            continue;
        }
        // Not testing *and* this wasn't checked?
        if (!$test && (!isset($_POST['remove']) || !isset($_POST['remove'][$id]))) {
            continue;
        }
        // What are the themes this was installed into?
        $cur_theme_paths = array();
        foreach ($theme_paths as $tid => $data) {
            if ($tid != 1 && in_array($tid, $package['themes'])) {
                $cur_theme_paths[$tid] = $data;
            }
        }
        // Get the modifications data if applicable.
        $filename = $package['filename'];
        $packageInfo = getPackageInfo($filename);
        if (!is_array($packageInfo)) {
            continue;
        }
        $info = parsePackageInfo($packageInfo['xml'], $test, 'uninstall');
        // Also get the reinstall details...
        if (isset($_POST['remove'])) {
            $infoInstall = parsePackageInfo($packageInfo['xml'], true);
        }
        if (is_file($boarddir . '/Packages/' . $filename)) {
            read_tgz_file($boarddir . '/Packages/' . $filename, $boarddir . '/Packages/temp');
        } else {
            copytree($boarddir . '/Packages/' . $filename, $boarddir . '/Packages/temp');
        }
        // Work out how we uninstall...
        $files = array();
        foreach ($info as $change) {
            // Work out two things:
            // 1) Whether it's installed at the moment - and if so whether its fully installed, and:
            // 2) Whether it could be installed on the new version.
            if ($change['type'] == 'modification') {
                $contents = @file_get_contents($boarddir . '/Packages/temp/' . $upcontext['base_path'] . $change['filename']);
                if ($change['boardmod']) {
                    $results = parseBoardMod($contents, $test, $change['reverse'], $cur_theme_paths);
                } else {
                    $results = parseModification($contents, $test, $change['reverse'], $cur_theme_paths);
                }
                foreach ($results as $action) {
                    // Something we can remove? Probably means it existed!
                    if (($action['type'] == 'replace' || $action['type'] == 'append' || !empty($action['filename']) && $action['type'] == 'failure') && !in_array($action['filename'], $files)) {
                        $files[] = $action['filename'];
                    }
                    if ($action['type'] == 'failure') {
                        $upcontext['packages'][$id]['needs_removing'] = true;
                        $upcontext['packages'][$id]['status'] = 'Reinstall Required';
                        $upcontext['packages'][$id]['color'] = '#FD6435';
                    }
                }
            }
        }
        // Store this info for the template as appropriate.
        $upcontext['packages'][$id]['files'] = $files;
        $upcontext['packages'][$id]['file_count'] = count($files);
        // If we've done something save the changes!
        if (!$test) {
            package_flush_cache();
        }
        // Are we attempting to reinstall this thing?
        if (isset($_POST['remove']) && !$test && isset($infoInstall)) {
            // Need to extract again I'm afraid.
            if (is_file($boarddir . '/Packages/' . $filename)) {
                read_tgz_file($boarddir . '/Packages/' . $filename, $boarddir . '/Packages/temp');
            } else {
                copytree($boarddir . '/Packages/' . $filename, $boarddir . '/Packages/temp');
            }
            $errors = false;
            $upcontext['packages'][$id]['result'] = 'Removed';
            foreach ($infoInstall as $change) {
                if ($change['type'] == 'modification') {
                    $contents = @file_get_contents($boarddir . '/Packages/temp/' . $upcontext['base_path'] . $change['filename']);
                    if ($change['boardmod']) {
                        $results = parseBoardMod($contents, true, $change['reverse'], $cur_theme_paths);
                    } else {
                        $results = parseModification($contents, true, $change['reverse'], $cur_theme_paths);
                    }
                    // Are there any errors?
                    foreach ($results as $action) {
                        if ($action['type'] == 'failure') {
                            $errors = true;
                        }
                    }
                }
            }
            if (!$errors) {
                $reinstall_worked[] = $id;
                $upcontext['packages'][$id]['result'] = 'Reinstalled';
                $upcontext['packages'][$id]['color'] = 'green';
                foreach ($infoInstall as $change) {
                    if ($change['type'] == 'modification') {
                        $contents = @file_get_contents($boarddir . '/Packages/temp/' . $upcontext['base_path'] . $change['filename']);
                        if ($change['boardmod']) {
                            $results = parseBoardMod($contents, false, $change['reverse'], $cur_theme_paths);
                        } else {
                            $results = parseModification($contents, false, $change['reverse'], $cur_theme_paths);
                        }
                    }
                }
                // Save the changes.
                package_flush_cache();
            }
        }
    }
    // Put errors back on a sec.
    error_reporting($oldErrorReporting);
    // Check everything is writable.
    if ($test && !empty($upcontext['packages'])) {
        $writable_files = array();
        foreach ($upcontext['packages'] as $package) {
            if (!empty($package['files'])) {
                foreach ($package['files'] as $file) {
                    $writable_files[] = $file;
                }
            }
        }
        if (!empty($writable_files)) {
            $writable_files = array_unique($writable_files);
            $upcontext['writable_files'] = $writable_files;
            if (!makeFilesWritable($writable_files)) {
                return false;
            }
        }
    }
    if (file_exists($boarddir . '/Packages/temp')) {
        deltree($boarddir . '/Packages/temp');
    }
    // Removing/Reinstalling any packages?
    if (isset($_POST['remove'])) {
        $deletes = array();
        foreach ($_POST['remove'] as $id => $dummy) {
            if (!in_array((int) $id, $reinstall_worked)) {
                $deletes[] = (int) $id;
            }
        }
        if (!empty($deletes)) {
            upgrade_query('
				UPDATE ' . $db_prefix . 'log_packages
				SET install_state = 0
				WHERE id_install IN (' . implode(',', $deletes) . ')');
        }
        // Ensure we don't lose our changes!
        package_put_contents($boarddir . '/Packages/installed.list', time());
        $upcontext['sub_template'] = 'cleanup_done';
        return false;
    } else {
        $allgood = true;
        // Is there actually anything that needs our attention?
        foreach ($upcontext['packages'] as $package) {
            if ($package['color'] != 'green') {
                $allgood = false;
            }
        }
        if ($allgood) {
            return true;
        }
    }
    $_GET['substep'] = 0;
    return isset($_POST['cleandone']) ? true : false;
}
Beispiel #7
0
function FlushInstall()
{
    global $boarddir, $sourcedir;
    checkSession('get');
    include_once $sourcedir . '/Subs-Package.php';
    // Open the file and write nothing to it.
    package_put_contents($boarddir . '/Packages/installed.list', '');
    redirectexit('action=packages;sa=installed');
}
Beispiel #8
0
 /**
  * Does the actual writing of the file
  *
  * - Writes the extracted file to disk or if we are extracting a single file
  * - it returns the extracted data
  */
 private function _write_this_file()
 {
     $this->_skip = false;
     $this->_found = false;
     // A directory may need to be created
     if (strpos($this->_filename, '/') !== false && !$this->single_file || !$this->single_file && !is_dir($this->_file_info['dir'])) {
         mktree($this->_file_info['dir'], 0777);
     }
     // If we're looking for a **specific file**, and this is it... ka-bam, baby.
     if ($this->single_file && ($this->destination === $this->_filename || $this->destination === '*/' . basename($this->_filename))) {
         $this->_found = $this->_file_info['data'];
     } elseif ($this->single_file) {
         $this->_skip = true;
     } elseif ($this->files_to_extract !== null && !in_array($this->_filename, $this->files_to_extract)) {
         $this->_skip = true;
     }
     // Write it out then
     if ($this->_skip === true) {
         return;
     } elseif (!empty($this->_found)) {
         $this->_check_crc();
     } elseif ($this->_skip === false && $this->_found === false && $this->_check_crc()) {
         package_put_contents($this->destination . '/' . $this->_filename, $this->_file_info['data']);
     }
 }
Beispiel #9
0
function parseBoardMod($file, $testing = true, $undo = false)
{
    global $boarddir, $sourcedir, $settings, $txt, $modSettings;
    @set_time_limit(600);
    $file = strtr($file, array("\r" => ''));
    $working_file = null;
    $working_search = null;
    $working_data = '';
    $replace_with = null;
    $actions = array();
    $everything_found = true;
    while (preg_match('~<(edit file|file|search|search for|add|add after|replace|add before|add above|above|before)>\\n(.*?)\\n</\\1>~is', $file, $code_match) != 0) {
        // Edit a specific file.
        if ($code_match[1] == 'file' || $code_match[1] == 'edit file') {
            // Backup the old file.
            if ($working_file !== null) {
                package_chmod($working_file);
                // Don't even dare.
                if (basename($working_file) == 'Settings_bak.php') {
                    continue;
                }
                if (!is_writable($working_file)) {
                    $actions[] = array('type' => 'chmod', 'filename' => $working_file);
                }
                if (!$testing && !empty($modSettings['package_make_backups']) && file_exists($working_file)) {
                    if (basename($working_file) == 'Settings.php') {
                        @copy($working_file, dirname($working_file) . '/Settings_bak.php');
                    } else {
                        @copy($working_file, $working_file . '~');
                    }
                }
                package_put_contents($working_file, $working_data, $testing);
            }
            if ($working_file !== null) {
                $actions[] = array('type' => 'saved', 'filename' => $working_file);
            }
            // Make sure the file exists!
            $working_file = parse_path($code_match[2]);
            if ($working_file[0] != '/' && $working_file[1] != ':') {
                trigger_error('parseBoardMod(): The filename \'' . $working_file . '\' is not a full path!', E_USER_WARNING);
                $working_file = $boarddir . '/' . $working_file;
            }
            if (!file_exists($working_file)) {
                $places_to_check = array($boarddir, $sourcedir, $settings['default_theme_dir'], $settings['default_theme_dir'] . '/languages');
                foreach ($places_to_check as $place) {
                    if (file_exists($place . '/' . $working_file)) {
                        $working_file = $place . '/' . $working_file;
                        break;
                    }
                }
            }
            if (file_exists($working_file)) {
                // Load the new file.
                $working_data = str_replace("\r", '', package_get_contents($working_file));
                $actions[] = array('type' => 'opened', 'filename' => $working_file);
            } else {
                $actions[] = array('type' => 'missing', 'filename' => $working_file);
                $working_file = null;
                $everything_found = false;
            }
            // Can't be searching for something...
            $working_search = null;
        } elseif (($code_match[1] == 'search' || $code_match[1] == 'search for') && $working_file !== null) {
            if ($working_search !== null) {
                $actions[] = array('type' => 'error', 'filename' => $working_file);
                $everything_found = false;
            }
            $working_search = $code_match[2];
        } elseif ($working_search !== null) {
            // This is the base string....
            $replace_with = $code_match[2];
            // Add this afterward...
            if ($code_match[1] == 'add' || $code_match[1] == 'add after') {
                $replace_with = $working_search . "\n" . $replace_with;
            } elseif ($code_match[1] == 'before' || $code_match[1] == 'add before' || $code_match[1] == 'above' || $code_match[1] == 'add above') {
                $replace_with .= "\n" . $working_search;
            }
            // Otherwise.. replace with $replace_with ;).
        }
        // If we have a search string, replace string, and open file..
        if ($working_search !== null && $replace_with !== null && $working_file !== null) {
            // Make sure it's somewhere in the string.
            if ($undo) {
                $temp = $replace_with;
                $replace_with = $working_search;
                $working_search = $temp;
            }
            if (strpos($working_data, $working_search) !== false) {
                $working_data = str_replace($working_search, $replace_with, $working_data);
                $actions[] = array('type' => 'replace', 'filename' => $working_file, 'search' => $working_search, 'replace' => $replace_with);
            } else {
                $actions[] = array('type' => 'failure', 'filename' => $working_file, 'search' => $working_search);
                $everything_found = false;
            }
            // These don't hold any meaning now.
            $working_search = null;
            $replace_with = null;
        }
        // Get rid of the old tag.
        $file = substr_replace($file, '', strpos($file, $code_match[0]), strlen($code_match[0]));
    }
    // Backup the old file.
    if ($working_file !== null) {
        package_chmod($working_file);
        if (!is_writable($working_file)) {
            $actions[] = array('type' => 'chmod', 'filename' => $working_file);
        }
        if (!$testing && !empty($modSettings['package_make_backups']) && file_exists($working_file)) {
            if (basename($working_file) == 'Settings.php') {
                @copy($working_file, dirname($working_file) . '/Settings_bak.php');
            } else {
                @copy($working_file, $working_file . '~');
            }
        }
        package_put_contents($working_file, $working_data, $testing);
    }
    if ($working_file !== null) {
        $actions[] = array('type' => 'saved', 'filename' => $working_file);
    }
    $actions[] = array('type' => 'result', 'status' => $everything_found);
    return $actions;
}
 /**
  * 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');
     }
 }
Beispiel #11
0
 /**
  * Does the actual writing of the file
  *
  * - Writes the extracted file to disk or if we are extracting a single file
  * - it returns the extracted data
  */
 private function _write_this_file()
 {
     $this->_skip = false;
     $this->_found = false;
     // A directory may need to be created
     if (strpos($this->_current['filename'], '/') !== false && !$this->single_file) {
         mktree($this->destination . '/' . dirname($this->_current['filename']), 0777);
     }
     // Is this the file we're looking for?
     if ($this->single_file && ($this->destination === $this->_current['filename'] || $this->destination === '*/' . basename($this->_current['filename']))) {
         $this->_found = $this->_current['data'];
     } elseif ($this->single_file) {
         $this->_skip = true;
     } elseif ($this->files_to_extract !== null && !in_array($this->_current['filename'], $this->files_to_extract)) {
         $this->_skip = true;
     }
     // Write it out then
     if ($this->_check_header_crc() && $this->_skip === false && $this->_found === false) {
         package_put_contents($this->destination . '/' . $this->_current['filename'], $this->_current['data']);
     }
 }
Beispiel #12
0
function fixp_main()
{
    global $txt, $sourcedir, $boarddir, $boardurl, $context, $user_info, $smcFunc;
    loadLanguage('Admin');
    loadLanguage('Packages');
    loadTemplate('Admin');
    fixp_loadLanguage();
    // Sorry, only logged in admins...unless you want so.
    if (empty($context['override_security'])) {
        isAllowedTo('admin_forum');
    }
    $context['install'] = isset($_GET['uninstall']) ? 0 : 1;
    if (!empty($_POST['remove']) && is_array($_POST['remove'])) {
        checkSession();
        foreach ($_POST['remove'] as $id) {
            if (isset($id) && is_numeric($id)) {
                if (!empty($context['install'])) {
                    $smcFunc['db_query']('', '
						UPDATE {db_prefix}log_packages
						SET
							id_member_removed = {int:id_member},
							member_removed = {string:member_name},
							time_removed = {int:time_removed},
							install_state = 0
						WHERE id_install = {int:inst_package_id}', array('id_member' => $user_info['id'], 'member_name' => $user_info['name'], 'time_removed' => time(), 'inst_package_id' => $id));
                } else {
                    $smcFunc['db_query']('', '
						UPDATE {db_prefix}log_packages
						SET
							id_member_removed = 0,
							member_removed = 0,
							time_removed = 0,
							install_state = 1
						WHERE id_install = {int:inst_package_id}', array('inst_package_id' => $id));
                }
            }
        }
        require_once $sourcedir . '/Subs-Package.php';
        package_put_contents($boarddir . '/Packages/installed.list', time());
    }
    if (isset($_POST['remove_hooks'])) {
        remove_hooks();
    }
    $context['sub_template'] = 'admin';
    $context['page_title'] = $txt['log_packages_title_' . (!empty($context['install']) ? 'installed' : 'removed')];
    // Making a list is not hard with this beauty.
    require_once $sourcedir . '/Subs-List.php';
    // Use the standard templates for showing this.
    $listOptions = array('id' => 'log_packages', 'title' => $context['page_title'], 'get_items' => array('function' => 'list_getPacks'), 'get_count' => array('function' => 'list_getNumPacks'), 'columns' => array('name' => array('header' => array('value' => $txt['mod_name']), 'data' => array('db' => 'name')), 'version' => array('header' => array('value' => $txt['mod_version']), 'data' => array('db' => 'version')), 'install_date' => array('header' => array('value' => $txt['mod_' . (!empty($context['install']) ? 'installed' : 'removed')]), 'data' => array('function' => create_function('&$data', '
						return timeformat($data[\'time_' . (!empty($context['install']) ? 'installed' : 'removed') . '\']);
					'))), 'check' => array('header' => array('value' => '<input type="checkbox" onclick="invertAll(this, this.form);" class="input_check" />'), 'data' => array('function' => create_function('$data', '
						return \'<input type="checkbox" name="remove[]" value="\' . $data[\'id_install\'] . \'"  class="input_check" />\';
					'), 'class' => 'centertext'))), 'form' => array('href' => $boardurl . '/fix_packages.php?' . $context['session_var'] . '=' . $context['session_id'] . (!empty($context['install']) ? '' : ';uninstall')), 'additional_rows' => array(array('position' => 'below_table_data', 'value' => '
				<a href="' . $boardurl . '/fix_packages.php' . (!empty($context['install']) ? '?uninstall' : '') . '">[ ' . (!empty($context['install']) ? $txt['uninstall'] : $txt['install']) . ' ]</a>
				<input type="submit" name="remove_packages" value="' . $txt['pack_button_' . (!empty($context['install']) ? 'remove' : 'install')] . '" class="button_submit" />
				<input type="submit" name="remove_hooks" value="' . $txt['remove_hooks'] . '" class="button_submit" />', 'class' => 'righttext')));
    $context['sub_template'] = 'show_list';
    $context['default_list'] = 'log_packages';
    // Create the request list.
    createList($listOptions);
}
 /**
  * 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'];
 }