Commit 81e8a73e authored by sikeda's avatar sikeda
Browse files

[dev] Custom CSS and CSS per language are no longer embedded in HTML; now they...

[dev] Custom CSS and CSS per language are no longer embedded in HTML; now they are separate CSS file.  New function Sympa::Tools::WWW::get_css_url() gives their URL including hash key to distingush updated CSS.


git-svn-id: https://subversion.renater.fr/sympa/branches/sympa-6.2-branch@12859 05aa8bb8-cd2b-0410-b1d7-8918dfa770ce
parent 28d61d03
......@@ -18,20 +18,12 @@
select[multiple], select[size] { height: auto; background-image: none; }
</style>
[% IF custom_css %]
<style>
[% custom_css %]
</style>
[% ELSE %]
<link rel="stylesheet" href="[% css_url %]/style.css?version=[% version %]" media="screen" title="Sympa CSS" />
[% END %]
[% IF locale_css %]
<style>
[% locale_css %]
</style>
[% END %]
[% IF main_css ~%]
<link rel="stylesheet" href="[% main_css %]" title="Sympa CSS" />
[%~ END %]
[% IF lang_css ~%]
<link rel="stylesheet" href="[% lang_css %]" />
[%~ END %]
[% IF conf.favicon_url %]
<link rel="shortcut icon" href="[% conf.favicon_url %]" />
[% ELSE %]
......
......@@ -997,8 +997,8 @@ unless (Conf::data_structure_uptodate()) {
);
}
 
# Update main CSS if required.
Sympa::Tools::WWW::update_css();
## Update main CSS if required.
#Sympa::Tools::WWW::update_css();
 
our %changed_params;
 
......@@ -2609,6 +2609,25 @@ sub send_html {
}
}
 
# Main CSS, possiblly customized.
my $main_css;
if ($session->{'custom_css'}) {
$main_css = Sympa::Tools::WWW::get_css_url($robot,
custom_css =>
{map { ($_ => $param->{$_}) } grep {/\Acolor_/} keys %$param});
unless ($main_css) {
wwslog('info', 'Error while parsing custom CSS');
delete $param->{'custom_css'};
}
}
$main_css ||= Sympa::Tools::WWW::get_css_url($robot);
$param->{'main_css'} = $main_css;
# Per-locale CSS.
$param->{'lang_css'} =
Sympa::Tools::WWW::get_css_url($robot, lang => $param->{'lang'})
if $param->{'lang'};
# XSS escaping applied to all outgoing parameters.
## Escape parameters on a copy to avoid altering useful data.
my $param_copy = Sympa::Tools::Data::dup_var($param);
......@@ -2629,51 +2648,6 @@ sub send_html {
$param_copy->{plugins} =
$plugins ? sub { $plugins->tt2Fragments(@_) } : sub { () };
 
## Custom CSSes. They are stored to $param_copy so that they won't be
## escaped.
# testing custom CSS.
if ($session->{'custom_css'}) {
# Do not include locale paths (lang parameter).
# The css.tt2 by each locales will override styles in main CSS.
my $css;
my $css_template = Sympa::Template->new(
$list || $robot,
plugins => $plugins,
subdir => 'web_tt2'
);
unless ($css_template->parse($param, 'css.tt2', \$css)) {
wwslog('info', 'Error while parsing custom CSS');
delete $param_copy->{'custom_css'};
} else {
$param_copy->{'custom_css'} = $css;
}
}
# per-locale CSS.
if (Sympa::search_fullpath(
$list || $robot, 'css.tt2',
subdir => 'web_tt2',
lang => $param->{'lang'},
lang_only => 1
)
) {
# Conversely, include only locale paths.
my $css;
my $css_template = Sympa::Template->new(
$list || $robot,
subdir => 'web_tt2',
lang => $param->{'lang'},
lang_only => 1
);
unless ($css_template->parse($param, 'css.tt2', \$css)) {
wwslog('info', 'Error while parsing CSS css.tt2 for lang %s',
$param->{'lang'});
} else {
$param_copy->{'locale_css'} = $css;
}
}
# Now include locale paths (lang parameter).
my $template = Sympa::Template->new(
$list || $robot,
......@@ -7589,19 +7563,11 @@ sub do_edit_template {
# Server show colors, and install static css in future edit colors etc.
sub do_skinsedit {
wwslog('info', '');
my $f;
my $dir = Conf::get_robot_conf($robot, 'css_path');
my $css_url = Conf::get_robot_conf($robot, 'css_url');
 
## Checking families and other virtual hosts.
# Checking families and other virtual hosts.
get_server_details();
 
$param->{'css_warning'} =
"parameter css_url seems strange, it must be the url of a directory not a css file"
if ($css_url =~ /\.css$/);
if (($in{'editcolors'}) && ($in{'subaction'} eq 'reset')) {
if ($in{'editcolors'} and $in{'subaction'} eq 'reset') {
delete $session->{'custom_css'};
delete $param->{'session'}{'custom_css'};
delete $param->{'custom_css'};
......@@ -7609,6 +7575,8 @@ sub do_skinsedit {
foreach my $colornumber (0 .. 15) {
delete $session->{'color_' . $colornumber};
delete $param->{'session'}{'color_' . $colornumber};
$param->{'color_' . $colornumber} =
Conf::get_robot_conf($robot, 'color_' . $colornumber);
}
}
 
......@@ -7616,9 +7584,7 @@ sub do_skinsedit {
return unless $in{'custom_color_number'} =~ /color_/;
$param->{'custom_color_number'} = $in{'custom_color_number'};
$param->{'custom_color_value'} = $in{'custom_color_value'};
$param->{'custom_css'} =
$css_url . '/' . $param->{'user'}{'email'} . '.style.css';
$session->{'custom_css'} = $param->{'custom_css'};
$param->{'custom_css'} = $session->{'custom_css'} = 1;
 
$session->{$in{'custom_color_number'}} = $in{'custom_color_value'};
 
......@@ -7626,7 +7592,6 @@ sub do_skinsedit {
foreach my $colornumber (0 .. 15) {
if ($session->{'color_' . $colornumber}) {
$param->{'color_' . $colornumber} =
$session->{'color_' . $colornumber};
$param->{'session'}{'color_' . $colornumber} =
$session->{'color_' . $colornumber};
}
......@@ -7634,99 +7599,15 @@ sub do_skinsedit {
}
 
if ($in{'subaction'} eq 'install' or $in{'installcss'}) {
# Do not include locale subdirectories (lang parameter).
# The css.tt2 by each locale will override styles in main CSS.
my $css_template = Sympa::Template->new($robot, subdir => 'web_tt2');
my $date = time;
my $style_file;
# update config
foreach my $colornumber (0 .. 15) {
Conf::set_robot_conf(
$robot,
'color_' . $colornumber,
$session->{'color_' . $colornumber}
) if ($session->{'color_' . $colornumber});
}
$param->{'conf'} = $Conf::Conf;
foreach my $css (qw(style.css)) {
$param->{'css'} = $css;
my $css_file;
# if user use editcolor form we must generate a static CSS that
# used custom colors.
if ($in{'subaction_test'}) {
$css_file = "$dir/$param->{'user'}{'email'}.$css";
} else {
$css_file = "$dir/$css";
}
unless (-d $dir) {
unless (mkdir $dir, 0775) {
Sympa::Report::reject_report_web('intern', "mkdir_failed",
{'path' => $dir},
$param->{'action'}, '', $param->{'user'}{'email'},
$robot);
wwslog('err', 'Failed to create directory %s: %s',
$dir, $ERRNO);
return undef;
}
chmod 0775, $dir;
wwslog('notice', 'Created missing directory %s', $dir);
}
## Keep a copy of the previous CSS (only if this is not a custom
## css).
if ((-f "$css_file") && !($in{'editcolors'})) {
unless (rename "$css_file", "$css_file.$date") {
Sympa::Report::reject_report_web(
'intern',
'cannot_rename_file',
{'path' => "$css_file.$date"},
$param->{'action'},
'',
$param->{'user'}{'email'},
$robot
);
wwslog('err', 'Can\'t open file %s.%s', $css_file, $date);
return undef;
}
}
if ($in{'subaction_install'}) {
foreach my $colornumber (0 .. 15) {
$param->{'color_' . $colornumber} =
$session->{'color_' . $colornumber}
if ($session->{'color_' . $colornumber});
}
}
unless (open(CSS, ">$css_file")) {
Sympa::Report::reject_report_web(
'intern', 'cannot_open_file',
{'path' => "$css_file"}, $param->{'action'},
'', $param->{'user'}{'email'},
$robot
);
wwslog('err', 'Can\'t open file (write) %s', $css_file);
return undef;
}
unless ($css_template->parse($param, 'css.tt2', \*CSS)) {
my $error = $css_template->{last_error};
$error = $error->as_string if ref $error;
$param->{'tt2_error'} = $error;
Sympa::send_notify_to_listmaster($robot, 'web_tt2_error',
[$error]);
wwslog('info', 'Error while installing %s: %s',
$css_file, $error);
}
close(CSS);
## Make the CSS readable to anyone
chmod 0775, "$css_file";
# Update config.
my @keys = grep { $session->{$_} } map { 'color_' . $_ } (0 .. 15);
foreach my $key (@keys) {
Conf::set_robot_conf($robot, $key, $session->{$key});
}
@{$param->{'conf'}}{@keys} = @{$session}{@keys};
@{$param}{@keys} = @{$session}{@keys};
Sympa::Tools::WWW::get_css_url($robot, force => 1);
 
$param->{'css_result'} = 1;
}
......@@ -23081,30 +22962,7 @@ sub do_arc_delete {
}
 
# DEPRECATED. No longer used.
#sub do_css {
# wwslog('debug', '(%s)', $in{'file'});
# $param->{'bypass'} = 'extreme';
# print "Content-type: text/css; charset=utf-8\n\n";
# $param->{'css'} = $in{'file'};
#
# # Do not include locale subdirectories (lang parameter).
# # The css.tt2 by each locale will override styles in main CSS.
# my $css_template = Sympa::Template->new($robot, subdir => 'web_tt2');
# unless ($css_template->parse($param, 'css.tt2', \*STDOUT)) {
# my $error = $css_template->{last_error};
# $error = $error->as_string if ref $error;
# $param->{'tt2_error'} = $error;
#
# Sympa::send_notify_to_listmaster($robot, 'web_tt2_error', [$error]);
# wwslog('info', '/%s: error: %s', $in{'file'}, $error);
# my $error_escaped = $error;
# $error_escaped =~ s/&/&amp;/g;
# $error_escaped =~ s/\//&#47;/g;
# printf STDOUT "\n/* %s */\n", $error_escaped;
# }
#
# return;
#}
#sub do_css;
 
sub do_rss_request {
wwslog('info', '');
......
......@@ -845,138 +845,237 @@ sub get_template_path {
}
# Old name: Conf::update_css().
sub update_css {
# DEPRECATED. No longer used.
#sub update_css;
# get_css_url($robot, [ force => 1 ], [ lang => $lang | custom_css => $param ])
# Old name: (part of) Conf::update_css().
sub get_css_url {
my $robot = shift;
my %options = @_;
my $force = $options{force};
# Get parameters for parsing.
my $lang;
my $param = {};
foreach my $p (
grep { /_color\z/ or /\Acolor_/ or /_url\z/ }
map { $_->{name} } grep { $_->{name} } @Sympa::ConfDef::params
) {
$param->{$p} = Conf::get_robot_conf($robot, $p);
}
if ($options{custom_css}) {
# Override colors for parsing.
my %colors = %{$options{custom_css}};
my @keys =
grep { defined $colors{$_} and length $colors{$_} } keys %colors;
@{$param}{@keys} = @colors{@keys};
$param->{custom_css} = 1;
} elsif ($options{lang}) {
$lang = Sympa::Language::canonic_lang($options{lang});
# Malformed lang parameter.
return '' unless $lang;
$param->{lang} = $lang;
}
$param->{css} = 'style.css'; # Compat. <= 6.2.16.
# Get path and mtime of template file.
my ($template_path, $template_mtime, $css_hash);
if ($lang) {
# Include only locale paths.
$template_path = Sympa::search_fullpath(
$robot, 'css.tt2',
subdir => 'web_tt2',
lang => $lang,
lang_only => 1
);
# No template for specified language.
return '' unless $template_path;
} else {
# Do not include locale paths (lang parameter).
# The css.tt2 by each locale will override styles in main CSS.
$template_path =
Sympa::search_fullpath($robot, 'css.tt2', subdir => 'web_tt2');
unless ($template_path) { # Impossible case.
return Sympa::Tools::Text::weburl(
Conf::get_robot_conf($robot, 'css_url'),
['style.css']);
}
}
$template_mtime = Sympa::Tools::File::get_mtime($template_path);
$param->{path} = $template_path;
$param->{mtime} = $template_mtime;
my $hash = Digest::MD5::md5_hex(
join ',',
map { $_ . '=' . $param->{$_} }
grep { defined $param->{$_} and length $param->{$_} }
sort keys %$param
);
my ($dir, $path, $url);
if ($options{custom_css}) {
$dir =
sprintf '%s/%s/%s',
Conf::get_robot_conf($robot, 'static_content_path'),
'css', $robot;
# Expire old files.
if (opendir my $dh, $dir) {
foreach my $file (readdir $dh) {
next unless $file =~ /\Astyle[.][0-9a-f]+[.]css\b/;
next unless -f $dir . '/' . $file;
next
if time - 3600 <
Sympa::Tools::File::get_mtime($dir . '/' . $file);
unlink $dir . '/' . $file;
}
closedir $dh;
}
$path = $dir . '/style.' . $hash . '.css';
$url =
Sympa::Tools::Text::weburl(
Conf::get_robot_conf($robot, 'static_content_url'),
['css', $robot, 'style.' . $hash . '.css']);
} elsif ($lang) {
$param->{'lang'} = $lang;
$dir =
sprintf '%s/%s/%s/%s',
Conf::get_robot_conf($robot, 'static_content_path'),
'css', $robot, $lang;
$path = $dir . '/lang.css';
$url = Sympa::Tools::Text::weburl(
Conf::get_robot_conf($robot, 'static_content_url'),
['css', $robot, $lang, 'lang.css'],
query => {h => $hash}
);
} else {
# Use css_path and css_url parameters so that the user may provide
# their own CSS.
$dir = Conf::get_robot_conf($robot, 'css_path');
$path = $dir . '/style.css';
$url =
Sympa::Tools::Text::weburl(
Conf::get_robot_conf($robot, 'css_url'),
['style.css'], query => {h => $hash});
}
# Update the CSS if it is missing or if a new css.tt2 was installed.
unless (!-f $path
or Sympa::Tools::File::get_mtime($path) < $template_mtime
or $options{force}) {
return $url;
}
$log->syslog(
'notice',
'Template file %s has changed; updating static CSS file %s; previous file renamed',
$template_path,
$path
);
# Set umask.
my $umask = umask 022;
# create or update static CSS files
my $css_updated = undef;
my @robots = ('*', keys %{$Conf::Conf{'robots'}});
foreach my $robot (@robots) {
my $dir = Conf::get_robot_conf($robot, 'css_path');
# Create directory if required
unless (-d $dir) {
my $error;
File::Path::make_path(
$dir,
{ mode => 0755,
owner => Sympa::Constants::USER(),
group => Sympa::Constants::GROUP(),
error => \$error
}
);
if (@$error) {
my ($target, $err) = %{$error->[-1] || {}};
## Get colors for parsing
my $param = {};
Sympa::send_notify_to_listmaster(
$robot,
'css_update_failed',
{ error => 'cannot_mkdir',
target => $target,
message => $err
}
);
$log->syslog('err', 'Failed to create %s: %s', $target, $err);
foreach my $p (
map { $_->{name} }
grep { $_->{name} } @Sympa::ConfDef::params
) {
$param->{$p} = Conf::get_robot_conf($robot, $p)
if $p =~ /_color\z/
or $p =~ /\Acolor_/
or $p =~ /_url\z/;
umask $umask;
return undef;
}
}
# Create directory if required
unless (-d $dir) {
my $error;
File::Path::make_path(
$dir,
{ mode => 0755,
owner => Sympa::Constants::USER(),
group => Sympa::Constants::GROUP(),
error => \$error
}
);
if (@$error) {
my ($target, $err) = %{$error->[-1] || {}};
Sympa::send_notify_to_listmaster(
$robot,
'css_update_failed',
{ error => 'cannot_mkdir',
target => $target,
message => $err
}
);
$log->syslog('err', 'Failed to create %s: %s', $target, $err);
# Lock file to prevent multiple processes from writing it.
my $lock_fh = Sympa::LockedFile->new($path, -1, '+');
unless ($lock_fh) {
umask $umask;
return $url;
}
umask $umask;
return undef;
my $fh;
unless (open $fh, '>', $path . '.new') {
my $errno = $ERRNO;
Sympa::send_notify_to_listmaster(
$robot,
'css_update_failed',
{ error => 'cannot_open_file',
file => $path,
message => $errno,
}
}
);
$log->syslog('err', 'Failed to open (write) file %s: %s',
$path, $errno);
my $css_tt2_path =
Sympa::search_fullpath($robot, 'css.tt2', subdir => 'web_tt2');
my $css_tt2_mtime = Sympa::Tools::File::get_mtime($css_tt2_path);
foreach my $css (qw(style.css)) {
# Lock file to prevent multiple processes from writing it.
my $lock_fh = Sympa::LockedFile->new($dir . '/' . $css, -1, '+');
next unless $lock_fh;
$param->{'css'} = $css;
# Update the CSS if it is missing or if a new css.tt2 was
# installed
if (!-f $dir . '/' . $css
or $css_tt2_mtime >
Sympa::Tools::File::get_mtime($dir . '/' . $css)
or $force) {
$log->syslog(
'notice',
'TT2 file %s has changed; updating static CSS file %s/%s; previous file renamed',
$css_tt2_path,
$dir,
$css
);
## Keep copy of previous file
rename $dir . '/' . $css, $dir . '/' . $css . '.' . time;
unless (open CSS, '>', $dir . '/' . $css) {
my $errno = $ERRNO;
Sympa::send_notify_to_listmaster(
$robot,
'css_update_failed',
{ error => 'cannot_open_file',
file => "$dir/$css",
message => $errno,
}
);
$log->syslog('err',
'Failed to open (write) file %s/%s: %s',
$dir, $css, $errno);
umask $umask;
return undef;
}
umask $umask;
return undef;
}
my $css_template =
Sympa::Template->new($robot, subdir => 'web_tt2');
unless ($css_template->parse($param, 'css.tt2', \*CSS)) {
my $error = $css_template->{last_error};
$error = $error->as_string if ref $error;
Sympa::send_notify_to_listmaster($robot,
'css_update_failed',
{error => 'tt2_error', message => $error});
$log->syslog('err', 'Error while installing %s/%s',
$dir, $css);
}
my $template;
if ($lang) {
$template = Sympa::Template->new(
$robot,
subdir => 'web_tt2',
lang => $lang,
lang_only => 1
);
} else {
$template = Sympa::Template->new($robot, subdir => 'web_tt2');
}
unless ($template->parse($param, 'css.tt2', $fh)) {
my $error = $template->{last_error};
$error = $error->as_string if ref $error;
Sympa::send_notify_to_listmaster($robot, 'css_update_failed',
{error => 'tt2_error', message => $error});
$log->syslog('err', 'Error while installing %s', $path);
# Keep previous file.
close $fh;
unlink $path . '.new';
$css_updated++;
umask $umask;
return $url;
}
close CSS;
}
}
close $fh;
# Keep copy of previous file.
unless (
(not -f $path or rename($path, $path .