Example #1
0
function EditTheme()
{
    global $context, $settings, $scripturl, $boarddir, $smcFunc;
    if (isset($_REQUEST['preview'])) {
        // !!! Should this be removed?
        die;
    }
    isAllowedTo('admin_forum');
    loadTemplate('Themes');
    $_GET['th'] = isset($_GET['th']) ? (int) $_GET['th'] : (int) @$_GET['id'];
    if (empty($_GET['th'])) {
        $request = $smcFunc['db_query']('', '
			SELECT id_theme, variable, value
			FROM {db_prefix}themes
			WHERE variable IN ({string:name}, {string:theme_dir}, {string:theme_templates}, {string:theme_layers})
				AND id_member = {int:no_member}', array('name' => 'name', 'theme_dir' => 'theme_dir', 'theme_templates' => 'theme_templates', 'theme_layers' => 'theme_layers', 'no_member' => 0));
        $context['themes'] = array();
        while ($row = $smcFunc['db_fetch_assoc']($request)) {
            if (!isset($context['themes'][$row['id_theme']])) {
                $context['themes'][$row['id_theme']] = array('id' => $row['id_theme'], 'num_default_options' => 0, 'num_members' => 0);
            }
            $context['themes'][$row['id_theme']][$row['variable']] = $row['value'];
        }
        $smcFunc['db_free_result']($request);
        foreach ($context['themes'] as $key => $theme) {
            // There has to be a Settings template!
            if (!file_exists($theme['theme_dir'] . '/index.template.php') && !file_exists($theme['theme_dir'] . '/css/index.css')) {
                unset($context['themes'][$key]);
            } else {
                if (!isset($theme['theme_templates'])) {
                    $templates = array('index');
                } else {
                    $templates = explode(',', $theme['theme_templates']);
                }
                foreach ($templates as $template) {
                    if (file_exists($theme['theme_dir'] . '/' . $template . '.template.php')) {
                        // Fetch the header... a good 256 bytes should be more than enough.
                        $fp = fopen($theme['theme_dir'] . '/' . $template . '.template.php', 'rb');
                        $header = fread($fp, 256);
                        fclose($fp);
                        // Can we find a version comment, at all?
                        if (preg_match('~(?://|/\\*)\\s*Version:\\s+(.+?);\\s*' . $template . '(?:[\\s]{2}|\\*/)~i', $header, $match) == 1) {
                            $ver = $match[1];
                            if (!isset($context['themes'][$key]['version']) || $context['themes'][$key]['version'] > $ver) {
                                $context['themes'][$key]['version'] = $ver;
                            }
                        }
                    }
                }
                $context['themes'][$key]['can_edit_style'] = file_exists($theme['theme_dir'] . '/css/index.css');
            }
        }
        $context['sub_template'] = 'edit_list';
        return 'no_themes';
    }
    $context['session_error'] = false;
    // Get the directory of the theme we are editing.
    $request = $smcFunc['db_query']('', '
		SELECT value, id_theme
		FROM {db_prefix}themes
		WHERE variable = {string:theme_dir}
			AND id_theme = {int:current_theme}
		LIMIT 1', array('current_theme' => $_GET['th'], 'theme_dir' => 'theme_dir'));
    list($theme_dir, $context['theme_id']) = $smcFunc['db_fetch_row']($request);
    $smcFunc['db_free_result']($request);
    if (!isset($_REQUEST['filename'])) {
        if (isset($_GET['directory'])) {
            if (substr($_GET['directory'], 0, 1) == '.') {
                $_GET['directory'] = '';
            } else {
                $_GET['directory'] = preg_replace(array('~^[\\./\\:\\0\\n\\r]+~', '~[\\\\]~', '~/[\\./]+~'), array('', '/', '/'), $_GET['directory']);
                $temp = realpath($theme_dir . '/' . $_GET['directory']);
                if (empty($temp) || substr($temp, 0, strlen(realpath($theme_dir))) != realpath($theme_dir)) {
                    $_GET['directory'] = '';
                }
            }
        }
        if (isset($_GET['directory']) && $_GET['directory'] != '') {
            $context['theme_files'] = get_file_listing($theme_dir . '/' . $_GET['directory'], $_GET['directory'] . '/');
            $temp = dirname($_GET['directory']);
            array_unshift($context['theme_files'], array('filename' => $temp == '.' || $temp == '' ? '/ (..)' : $temp . ' (..)', 'is_writable' => is_writable($theme_dir . '/' . $temp), 'is_directory' => true, 'is_template' => false, 'is_image' => false, 'is_editable' => false, 'href' => $scripturl . '?action=admin;area=theme;th=' . $_GET['th'] . ';' . $context['session_var'] . '=' . $context['session_id'] . ';sa=edit;directory=' . $temp, 'size' => ''));
        } else {
            $context['theme_files'] = get_file_listing($theme_dir, '');
        }
        $context['sub_template'] = 'edit_browse';
        return;
    } else {
        if (substr($_REQUEST['filename'], 0, 1) == '.') {
            $_REQUEST['filename'] = '';
        } else {
            $_REQUEST['filename'] = preg_replace(array('~^[\\./\\:\\0\\n\\r]+~', '~[\\\\]~', '~/[\\./]+~'), array('', '/', '/'), $_REQUEST['filename']);
            $temp = realpath($theme_dir . '/' . $_REQUEST['filename']);
            if (empty($temp) || substr($temp, 0, strlen(realpath($theme_dir))) != realpath($theme_dir)) {
                $_REQUEST['filename'] = '';
            }
        }
        if (empty($_REQUEST['filename'])) {
            fatal_lang_error('theme_edit_missing', false);
        }
    }
    if (isset($_POST['submit'])) {
        if (checkSession('post', '', false) == '') {
            if (is_array($_POST['entire_file'])) {
                $_POST['entire_file'] = implode("\n", $_POST['entire_file']);
            }
            $_POST['entire_file'] = rtrim(strtr($_POST['entire_file'], array("\r" => '', '   ' => "\t")));
            // Check for a parse error!
            if (substr($_REQUEST['filename'], -13) == '.template.php' && is_writable($theme_dir) && @ini_get('display_errors')) {
                $request = $smcFunc['db_query']('', '
					SELECT value
					FROM {db_prefix}themes
					WHERE variable = {string:theme_url}
						AND id_theme = {int:current_theme}
					LIMIT 1', array('current_theme' => $_GET['th'], 'theme_url' => 'theme_url'));
                list($theme_url) = $smcFunc['db_fetch_row']($request);
                $smcFunc['db_free_result']($request);
                $fp = fopen($theme_dir . '/tmp_' . session_id() . '.php', 'w');
                fwrite($fp, $_POST['entire_file']);
                fclose($fp);
                // !!! Use fetch_web_data()?
                $error = @file_get_contents($theme_url . '/tmp_' . session_id() . '.php');
                if (preg_match('~ <b>(\\d+)</b><br( /)?' . '>$~i', $error) != 0) {
                    $error_file = $theme_dir . '/tmp_' . session_id() . '.php';
                } else {
                    unlink($theme_dir . '/tmp_' . session_id() . '.php');
                }
            }
            if (!isset($error_file)) {
                $fp = fopen($theme_dir . '/' . $_REQUEST['filename'], 'w');
                fwrite($fp, $_POST['entire_file']);
                fclose($fp);
                redirectexit('action=admin;area=theme;th=' . $_GET['th'] . ';' . $context['session_var'] . '=' . $context['session_id'] . ';sa=edit;directory=' . dirname($_REQUEST['filename']));
            }
        } else {
            loadLanguage('Errors');
            $context['session_error'] = true;
            $context['sub_template'] = 'edit_file';
            // Recycle the submitted data.
            $context['entire_file'] = htmlspecialchars($_POST['entire_file']);
            // You were able to submit it, so it's reasonable to assume you are allowed to save.
            $context['allow_save'] = true;
            return;
        }
    }
    $context['allow_save'] = is_writable($theme_dir . '/' . $_REQUEST['filename']);
    $context['allow_save_filename'] = strtr($theme_dir . '/' . $_REQUEST['filename'], array($boarddir => '...'));
    $context['edit_filename'] = htmlspecialchars($_REQUEST['filename']);
    if (substr($_REQUEST['filename'], -4) == '.css') {
        $context['sub_template'] = 'edit_style';
        $context['entire_file'] = htmlspecialchars(strtr(file_get_contents($theme_dir . '/' . $_REQUEST['filename']), array("\t" => '   ')));
    } elseif (substr($_REQUEST['filename'], -13) == '.template.php') {
        $context['sub_template'] = 'edit_template';
        if (!isset($error_file)) {
            $file_data = file($theme_dir . '/' . $_REQUEST['filename']);
        } else {
            if (preg_match('~(<b>.+?</b>:.+?<b>).+?(</b>.+?<b>\\d+</b>)<br( /)?' . '>$~i', $error, $match) != 0) {
                $context['parse_error'] = $match[1] . $_REQUEST['filename'] . $match[2];
            }
            $file_data = file($error_file);
            unlink($error_file);
        }
        $j = 0;
        $context['file_parts'] = array(array('lines' => 0, 'line' => 1, 'data' => ''));
        for ($i = 0, $n = count($file_data); $i < $n; $i++) {
            if (isset($file_data[$i + 1]) && substr($file_data[$i + 1], 0, 9) == 'function ') {
                // Try to format the functions a little nicer...
                $context['file_parts'][$j]['data'] = trim($context['file_parts'][$j]['data']) . "\n";
                if (empty($context['file_parts'][$j]['lines'])) {
                    unset($context['file_parts'][$j]);
                }
                $context['file_parts'][++$j] = array('lines' => 0, 'line' => $i + 1, 'data' => '');
            }
            $context['file_parts'][$j]['lines']++;
            $context['file_parts'][$j]['data'] .= htmlspecialchars(strtr($file_data[$i], array("\t" => '   ')));
        }
        $context['entire_file'] = htmlspecialchars(strtr(implode('', $file_data), array("\t" => '   ')));
    } else {
        $context['sub_template'] = 'edit_file';
        $context['entire_file'] = htmlspecialchars(strtr(file_get_contents($theme_dir . '/' . $_REQUEST['filename']), array("\t" => '   ')));
    }
}
 /**
  * Handles user browsing in theme directories.
  *
  * What it does:
  * - The display will allow to choose a file for editing,
  * if it is writable.
  * - accessed with ?action=admin;area=theme;sa=browse
  */
 public function action_browse()
 {
     global $context, $scripturl;
     loadTemplate('ManageThemes');
     // We'll work hard with them themes!
     require_once SUBSDIR . '/Themes.subs.php';
     $selectedTheme = isset($_GET['th']) ? (int) $_GET['th'] : (isset($_GET['id']) ? (int) $_GET['id'] : 0);
     if (empty($selectedTheme)) {
         redirectexit('action=admin;area=theme;sa=themelist');
     }
     // Get first the directory of the theme we are editing.
     $context['theme_id'] = isset($_GET['th']) ? (int) $_GET['th'] : (isset($_GET['id']) ? (int) $_GET['id'] : 0);
     $theme_dir = themeDirectory($context['theme_id']);
     // Eh? not trying to sneak a peek outside the theme directory are we
     if (!file_exists($theme_dir . '/index.template.php') && !file_exists($theme_dir . '/css/index.css')) {
         fatal_lang_error('theme_edit_missing', false);
     }
     // Now, where exactly are you?
     if (isset($_GET['directory'])) {
         if (substr($_GET['directory'], 0, 1) === '.') {
             $_GET['directory'] = '';
         } else {
             $_GET['directory'] = preg_replace(array('~^[\\./\\:\\0\\n\\r]+~', '~[\\\\]~', '~/[\\./]+~'), array('', '/', '/'), $_GET['directory']);
             $temp = realpath($theme_dir . '/' . $_GET['directory']);
             if (empty($temp) || substr($temp, 0, strlen(realpath($theme_dir))) != realpath($theme_dir)) {
                 $_GET['directory'] = '';
             }
         }
     }
     if (isset($_GET['directory']) && $_GET['directory'] != '') {
         $context['theme_files'] = get_file_listing($theme_dir . '/' . $_GET['directory'], $_GET['directory'] . '/');
         $temp = dirname($_GET['directory']);
         array_unshift($context['theme_files'], array('filename' => $temp == '.' || $temp == '' ? '/ (..)' : $temp . ' (..)', 'is_writable' => is_writable($theme_dir . '/' . $temp), 'is_directory' => true, 'is_template' => false, 'is_image' => false, 'is_editable' => false, 'href' => $scripturl . '?action=admin;area=theme;th=' . $context['theme_id'] . ';' . $context['session_var'] . '=' . $context['session_id'] . ';sa=browse;directory=' . $temp, 'size' => ''));
     } else {
         $context['theme_files'] = get_file_listing($theme_dir, '');
     }
     // finally, load the sub-template
     $context['sub_template'] = 'browse';
 }