diff --git a/phpBB/adm/style/acp_styles.html b/phpBB/adm/style/acp_styles.html index 37a878c240..47efd249ec 100644 --- a/phpBB/adm/style/acp_styles.html +++ b/phpBB/adm/style/acp_styles.html @@ -141,249 +141,90 @@ //--> - + « {L_BACK} - « {L_BACK} +
{L_EDIT_EXPLAIN}
-{L_EDIT_TEMPLATE_EXPLAIN}
+{L_SELECTED}: {SELECTED_TEMPLATE}
-{L_SELECTED_TEMPLATE}: {SELECTED_TEMPLATE}
+ - - - - - - - - - - - - « {L_BACK} - -{L_EDIT_THEME_EXPLAIN}
- -{L_SELECTED_THEME}: {SELECTED_THEME}
- - -{L_SHOW_CSS_EXPLAIN}
- - - - - - - - -{L_CUSTOM_CLASS_EXPLAIN}
- - - diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php index 61d7d51efc..4f61027a09 100644 --- a/phpBB/includes/acp/acp_styles.php +++ b/phpBB/includes/acp/acp_styles.php @@ -820,7 +820,7 @@ parse_css_file = {PARSE_CSS_FILE} // we don't need any single element categories so put them into the misc '' category for ($i = 0, $n = sizeof($cats); $i < $n; $i++) { - if (sizeof($filelist_cats[$cats[$i]]) == 1) + if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '') { $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]); unset($filelist_cats[$cats[$i]]); @@ -858,6 +858,15 @@ parse_css_file = {PARSE_CSS_FILE} 'U_ACTION' => $this->u_action . "&action=edit&id=$template_id&text_rows=$text_rows", 'U_BACK' => $this->u_action, + 'L_EDIT' => $user->lang['EDIT_TEMPLATE'], + 'L_EDIT_EXPLAIN' => $user->lang['EDIT_TEMPLATE_EXPLAIN'], + 'L_EDITOR' => $user->lang['TEMPLATE_EDITOR'], + 'L_EDITOR_HEIGHT' => $user->lang['TEMPLATE_EDITOR_HEIGHT'], + 'L_FILE' => $user->lang['TEMPLATE_FILE'], + 'L_SELECT' => $user->lang['SELECT_TEMPLATE'], + 'L_SELECTED' => $user->lang['SELECTED_TEMPLATE'], + 'L_SELECTED_FILE' => $user->lang['SELECTED_TEMPLATE_FILE'], + 'SELECTED_TEMPLATE' => $template_info['template_name'], 'TEMPLATE_FILE' => $template_file, 'TEMPLATE_DATA' => htmlspecialchars($template_data), @@ -998,27 +1007,23 @@ parse_css_file = {PARSE_CSS_FILE} */ function edit_theme($theme_id) { - global $phpbb_root_path, $phpbb_admin_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; + global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode; $this->page_title = 'EDIT_THEME'; + $filelist = $filelist_cats = array(); + // we want newlines no carriage returns! - $_POST['css_data'] = (isset($_POST['css_data']) && !empty($_POST['css_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['css_data']) : ''; + $_POST['template_data'] = (isset($_POST['template_data']) && !empty($_POST['template_data'])) ? str_replace(array("\r\n", "\r"), array("\n", "\n"), $_POST['template_data']) : ''; - // get user input + $theme_data = (STRIP) ? stripslashes($_POST['template_data']) : $_POST['template_data']; + $theme_file = request_var('template_file', ''); $text_rows = max(5, min(999, request_var('text_rows', 20))); - $hide_css = request_var('hidecss', false); - $show_css = !$hide_css && request_var('showcss', false); - $edit_class = request_var('css_class', ''); - $custom_class = request_var('custom_class', ''); - $css_data = (STRIP) ? stripslashes($_POST['css_data']) : $_POST['css_data']; - $submit = isset($_POST['submit']) ? true : false; - $add_custom = isset($_POST['add_custom']) ? true : false; - $matches = array(); - - // no curly brackets inside a CSS block please - $css_data = str_replace(array('{', '}'), '', $css_data); + $save_changes = (isset($_POST['save'])) ? true : false; + // make sure theme_file path doesn't go upwards + $theme_file = str_replace('..', '.', $theme_file); + // Retrieve some information about the theme $sql = 'SELECT theme_storedb, theme_path, theme_name, theme_data FROM ' . STYLES_THEME_TABLE . " @@ -1031,342 +1036,22 @@ parse_css_file = {PARSE_CSS_FILE} } $db->sql_freeresult($result); - $stylesheet_path = $phpbb_root_path . 'styles/' . $theme_info['theme_path'] . '/theme/stylesheet.css'; - // Get the CSS data from either database or filesystem - if (!$theme_info['theme_storedb']) + // save changes to the theme if the user submitted any + if ($save_changes) { - if (!file_exists($stylesheet_path) || !($stylesheet = file_get_contents($stylesheet_path))) + // Get the filesystem location of the current file + $file = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/$theme_file"; + $additional = ''; + $message = $user->lang['THEME_UPDATED']; + + // If the theme is stored on the filesystem try to write the file else store it in the database + if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($file) && @is_writable($file)) { - trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); - } - } - else - { - $stylesheet = &$theme_info['theme_data']; - } - - // Pull out a list of classes - $classes = array(); - if (preg_match_all('/^([a-z0-9\.,:#_\->* \t]+?)[ \t\n]*?\{.*?\}/msi', $stylesheet, $matches)) - { - $classes = $matches[1]; - } - - // Generate html for the list of classes - $s_hidden_fields = array(); - $s_classes = ''; - sort($classes); - foreach ($classes as $class) - { - $selected = ($class == $edit_class) ? ' selected="selected"' : ''; - $s_classes .= ''; - } - - $template->assign_vars(array( - 'S_EDIT_THEME' => true, - 'S_SHOWCSS' => $show_css, - 'S_CLASSES' => $s_classes, - 'S_CLASS' => $edit_class, - - 'U_ACTION' => $this->u_action . "&action=edit&id=$theme_id&showcss=$show_css&text_rows=$text_rows", - 'U_BACK' => $this->u_action, - - 'SELECTED_THEME' => $theme_info['theme_name'], - 'TEXT_ROWS' => $text_rows) - ); - - // only continue if we are really editing anything - if (!$edit_class && !$add_custom) - { - return; - } - - // These are the elements for the simple view - $match_elements = array( - 'colors' => array('background-color', 'color',), - 'sizes' => array('font-size', 'line-height',), - 'images' => array('background-image',), - 'repeat' => array('background-repeat',), - 'other' => array('font-weight', 'font-family', 'font-style', 'text-decoration',), - ); - - // Used in an sprintf statement to generate appropriate output for rawcss mode - $map_elements = array( - 'colors' => '%s', - 'sizes' => '%1.10f', - 'images' => 'url(\'./%s\')', - 'repeat' => '%s', - 'other' => '%s', - ); - - $units = array('px', '%', 'em', 'pt'); - $repeat_types = array( - '' => $user->lang['UNSET'], - 'none' => $user->lang['REPEAT_NO'], - 'repeat-x' => $user->lang['REPEAT_X'], - 'repeat-y' => $user->lang['REPEAT_Y'], - 'both' => $user->lang['REPEAT_ALL'], - ); - - // Fill css_data with the class contents from the stylesheet - // in case we just selected a class and it's not filled yet - if (!$css_data && !$submit && !isset($_POST['hidecss']) && !isset($_POST['showcss']) && !$add_custom) - { - preg_match('#^[ \t]*?' . preg_quote($edit_class, '#') . '[ \t\n]*?\{(.*?)\}#ms', $stylesheet, $matches); - - if (!isset($matches[1])) - { - trigger_error($user->lang['NO_CLASS'] . adm_back_link($this->u_action), E_USER_WARNING); - } - - $css_data = implode(";\n", array_diff(array_map('trim', explode("\n", preg_replace("#;[\n]*#s", "\n", $matches[1]))), array(''))); - if ($css_data) - { - $css_data .= ';'; - } - } - - // If we don't show raw css and the user did not submit any modification - // then generate a list of css elements and output them via the template - if (!$show_css && !$submit && !$add_custom) - { - $css_elements = array_diff(array_map('trim', explode("\n", preg_replace("#;[\n]*#s", "\n", $css_data))), array('')); - - // Grab list of potential images for the "images" type - $img_filelist = filelist($phpbb_root_path . 'styles/' . $theme_info['theme_name'] . '/theme'); - - foreach ($match_elements as $type => $match_ary) - { - foreach ($match_ary as $match) - { - $var = str_replace('-', '_', $match); - $value = ''; - $unit = ''; - - if (sizeof($css_elements)) - { - // first read in the setting - foreach ($css_elements as $key => $element) - { - if (preg_match('#^' . preg_quote($match, '#') . ':[ \t\n]*?(.*?)$#', $element, $matches)) - { - switch ($type) - { - case 'sizes': - $value = trim($matches[1]); - - if (preg_match('#(.*?)(px|%|em|pt)#', $matches[1], $matches)) - { - $unit = trim($matches[2]); - $value = trim($matches[1]); - } - break; - - case 'images': - if (preg_match('#url\(\'(.*?)\'\)#', $matches[1], $matches)) - { - $value = trim($matches[1]); - } - break; - - case 'colors': - $value = trim($matches[1]); - if ($value[0] == '#') - { - $value = substr($value, 1); - } - break; - - default: - $value = trim($matches[1]); - } - - // Remove this element from array - unset($css_elements[$key]); - break; - } - } - } - - // then display it in the template - switch ($type) - { - case 'sizes': - // generate a list of units - $s_units = ''; - foreach ($units as $unit_option) - { - $selected = ($unit_option == $unit) ? ' selected="selected"' : ''; - $s_units .= ""; - } - $s_units = '' . $s_units; - - $template->assign_vars(array( - strtoupper($var) => htmlspecialchars($value), - 'S_' . strtoupper($var) . '_UNITS' => $s_units) - ); - break; - - case 'images': - // generate a list of images for this setting - $s_imglist = ''; - foreach ($img_filelist as $path => $img_ary) - { - foreach ($img_ary as $img) - { - $img = htmlspecialchars(((substr($path, 0, 1) == '/') ? substr($path, 1) : $path) . $img); - - $selected = (preg_match('#' . preg_quote($img) . '$#', $value)) ? ' selected="selected"' : ''; - $s_imglist .= ""; - } - } - $s_imglist = '' . $s_imglist; - - $template->assign_vars(array( - 'S_' . strtoupper($var) => $s_imglist) - ); - unset($s_imglist); - break; - - case 'repeat': - // generate a list of repeat options - $s_repeat_types = ''; - foreach ($repeat_types as $repeat_type => $repeat_lang) - { - $selected = ($value == $repeat_type) ? ' selected="selected"' : ''; - $s_repeat_types .= ""; - } - - $template->assign_vars(array( - 'S_' . strtoupper($var) => $s_repeat_types) - ); - - default: - $template->assign_vars(array( - strtoupper($var) => htmlspecialchars($value)) - ); - } - } - } - - // Any remaining elements must be custom data so we save that in a hidden field - if (sizeof($css_elements)) - { - $s_hidden_fields['cssother'] = implode(' ;; ', $css_elements); - } - - unset($img_filelist, $css_elements); - } - // else if we are showing raw css or the user submitted data from the simple view - // then we need to turn the given information into raw css - else if (!$css_data && !$add_custom) - { - foreach ($match_elements as $type => $match_ary) - { - foreach ($match_ary as $match) - { - $var = str_replace('-', '_', $match); - $value = ''; - $unit = ''; - - // retrieve and validate data for this setting - switch ($type) - { - case 'sizes': - $value = request_var($var, 0.0); - $unit = request_var($var . '_unit', ''); - - if ((request_var($var, '') === '') || !in_array($unit, $units)) - { - $value = ''; - } - break; - - case 'images': - $value = str_replace('..', '.', request_var($var, '')); - if (!file_exists("{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme/" . $value)) - { - $value = ''; - } - break; - - case 'colors': - $value = request_var($var, ''); - if (preg_match('#^(?:[A-F0-9]{6}|[A-F0-9]{3})$#', $value)) - { - $value = '#' . $value; - } - break; - - case 'repeat': - $value = request_var($var, ''); - if (!isset($repeat_types[$value])) - { - $value = ''; - } - break; - - default: - $value = htmlspecialchars_decode(request_var($var, '')); - } - - // use the element mapping to create raw css code - if ($value !== '') - { - $css_data .= $match . ': ' . ($type == 'sizes' ? rtrim(sprintf($map_elements[$type], $value), '0') : sprintf($map_elements[$type], $value)) . $unit . ";\n"; - } - } - } - - // append additional data sent to us - if ($other = request_var('cssother', '')) - { - $css_data .= str_replace(' ;; ', ";\n", $other) . ';'; - $css_data = preg_replace("#\*/;\n#", "*/\n", $css_data); - } - } - // make sure we have $show_css set, so we can link to the show_css page if we need to - else if (!$hide_css) - { - $show_css = true; - } - - if ($submit || $add_custom) - { - if ($submit) - { - // if the user submitted a modification replace the old class definition in the stylesheet - // with the new one - if (preg_match('#^' . preg_quote($edit_class, '#') . '[ \t\n]*?\{(.*?)\}#ms', $stylesheet)) - { - $stylesheet = preg_replace('#^(' . preg_quote($edit_class, '#') . '[ \t\n]*?\{).*?(\})#ms', "$1\n\t" . str_replace("\n", "\n\t", $css_data) . "\n$2", $stylesheet); - } - $message = $user->lang['THEME_UPDATED']; - } - else - { - // check whether the custom class name is valid - if (!preg_match('/^[a-z0-9\.,:#_\ \t->*]+$/i', $custom_class)) - { - trigger_error($user->lang['THEME_ERR_CLASS_CHARS'] . adm_back_link($this->u_action . "&action=edit&id=$theme_id&text_rows=$text_rows"), E_USER_WARNING); - } - else - { - // append an empty class definition to the stylesheet - $stylesheet .= "\n$custom_class {\n\t\n}"; - $message = $user->lang['THEME_CLASS_ADDED']; - } - } - - // where should we store the CSS? - if (!$safe_mode && !$theme_info['theme_storedb'] && file_exists($stylesheet_path) && @is_writable($stylesheet_path)) - { - // write stylesheet to file - if (!($fp = fopen($stylesheet_path, 'wb'))) + if (!($fp = fopen($file, 'wb'))) { trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING); } - fwrite($fp, $stylesheet); + fwrite($fp, $theme_data); fclose($fp); } else @@ -1375,7 +1060,7 @@ parse_css_file = {PARSE_CSS_FILE} $sql_ary = array( 'theme_mtime' => time(), 'theme_storedb' => 1, - 'theme_data' => $this->db_theme_data($theme_info, $stylesheet), + 'theme_data' => $this->db_theme_data($theme_info, $theme_data), ); $sql = 'UPDATE ' . STYLES_THEME_TABLE . ' SET ' . $db->sql_build_array('UPDATE', $sql_ary) . ' @@ -1384,30 +1069,119 @@ parse_css_file = {PARSE_CSS_FILE} $cache->destroy('sql', STYLES_THEME_TABLE); - // notify the user if the template was not stored in the db before his modification + // notify the user if the theme was not stored in the db before his modification if (!$theme_info['theme_storedb']) { add_log('admin', 'LOG_THEME_EDIT_DETAILS', $theme_info['theme_name']); $message .= '