diff options
Diffstat (limited to 'Bugzilla/Util.pm')
-rw-r--r-- | Bugzilla/Util.pm | 102 |
1 files changed, 66 insertions, 36 deletions
diff --git a/Bugzilla/Util.pm b/Bugzilla/Util.pm index 48507ff9e..2349dc9e9 100644 --- a/Bugzilla/Util.pm +++ b/Bugzilla/Util.pm @@ -28,6 +28,7 @@ package Bugzilla::Util; +use 5.10.1; use strict; use base qw(Exporter); @@ -35,7 +36,7 @@ use base qw(Exporter); detaint_signed html_quote url_quote xml_quote css_class_quote html_light_quote - i_am_cgi correct_urlbase remote_ip validate_ip + i_am_cgi i_am_webservice correct_urlbase remote_ip validate_ip do_ssl_redirect_if_required use_attachbase diff_arrays on_main_db trim wrap_hard wrap_comment find_wrap_point @@ -44,7 +45,7 @@ use base qw(Exporter); bz_crypt generate_random_password validate_email_syntax clean_text get_text template_var disable_utf8 - detect_encoding); + enable_utf8 detect_encoding email_filter); use Bugzilla::Constants; use Bugzilla::RNG qw(irand); @@ -57,7 +58,6 @@ use Digest; use Email::Address; use List::Util qw(first); use Scalar::Util qw(tainted blessed); -use Template::Filters; use Text::Wrap; use Encode qw(encode decode resolve_alias); use Encode::Guess; @@ -87,10 +87,17 @@ sub detaint_signed { # visible strings. # Bug 319331: Handle BiDi disruptions. sub html_quote { - my ($var) = Template::Filters::html_filter(@_); + my $var = shift; + $var =~ s/&/&/g; + $var =~ s/</</g; + $var =~ s/>/>/g; + $var =~ s/"/"/g; # Obscure '@'. $var =~ s/\@/\@/g; - if (Bugzilla->params->{'utf8'}) { + + state $use_utf8 = Bugzilla->params->{'utf8'}; + + if ($use_utf8) { # Remove control characters if the encoding is utf8. # Other multibyte encodings may be using this range; so ignore if not utf8. $var =~ s/(?![\t\r\n])[[:cntrl:]]//g; @@ -116,13 +123,16 @@ sub html_quote { # |U+200e|Left-To-Right Mark |0xe2 0x80 0x8e | # |U+200f|Right-To-Left Mark |0xe2 0x80 0x8f | # -------------------------------------------------------- - $var =~ s/[\x{202a}-\x{202e}]//g; + $var =~ tr/\x{202a}-\x{202e}//d; } return $var; } sub html_light_quote { my ($text) = @_; + # admin/table.html.tmpl calls |FILTER html_light| many times. + # There is no need to recreate the HTML::Scrubber object again and again. + my $scrubber = Bugzilla->process_cache->{html_scrubber}; # List of allowed HTML elements having no attributes. my @allow = qw(b strong em i u p br abbr acronym ins del cite code var @@ -144,7 +154,7 @@ sub html_light_quote { $text =~ s#$chr($safe)$chr#<$1>#go; return $text; } - else { + elsif (!$scrubber) { # We can be less restrictive. We can accept elements with attributes. push(@allow, qw(a blockquote q span)); @@ -187,14 +197,14 @@ sub html_light_quote { }, ); - my $scrubber = HTML::Scrubber->new(default => \@default, - allow => \@allow, - rules => \@rules, - comment => 0, - process => 0); - - return $scrubber->scrub($text); + Bugzilla->process_cache->{html_scrubber} = $scrubber = + HTML::Scrubber->new(default => \@default, + allow => \@allow, + rules => \@rules, + comment => 0, + process => 0); } + return $scrubber->scrub($text); } sub email_filter { @@ -253,6 +263,13 @@ sub i_am_cgi { return exists $ENV{'SERVER_SOFTWARE'} ? 1 : 0; } +sub i_am_webservice { + my $usage_mode = Bugzilla->usage_mode; + return $usage_mode == USAGE_MODE_XMLRPC + || $usage_mode == USAGE_MODE_JSON + || $usage_mode == USAGE_MODE_REST; +} + # This exists as a separate function from Bugzilla::CGI::redirect_to_https # because we don't want to create a CGI object during XML-RPC calls # (doing so can mess up XML-RPC). @@ -475,11 +492,11 @@ sub find_wrap_point { if (!$string) { return 0 } if (length($string) < $maxpos) { return length($string) } my $wrappoint = rindex($string, ",", $maxpos); # look for comma - if ($wrappoint < 0) { # can't find comma + if ($wrappoint <= 0) { # can't find comma $wrappoint = rindex($string, " ", $maxpos); # look for space - if ($wrappoint < 0) { # can't find space + if ($wrappoint <= 0) { # can't find space $wrappoint = rindex($string, "-", $maxpos); # look for hyphen - if ($wrappoint < 0) { # can't find hyphen + if ($wrappoint <= 0) { # can't find hyphen $wrappoint = $maxpos; # just truncate it } else { $wrappoint++; # leave hyphen on the left side @@ -531,9 +548,14 @@ sub datetime_from { # In the database, this is the "0" date. return undef if $date =~ /^0000/; - # strptime($date) returns an empty array if $date has an invalid - # date format. - my @time = strptime($date); + my @time; + # Most dates will be in this format, avoid strptime's generic parser + if ($date =~ /^(\d{4})[\.-](\d{2})[\.-](\d{2})(?: (\d{2}):(\d{2}):(\d{2}))?$/) { + @time = ($6, $5, $4, $3, $2 - 1, $1 - 1900, undef); + } + else { + @time = strptime($date); + } unless (scalar @time) { # If an unknown timezone is passed (such as MSK, for Moskow), @@ -545,10 +567,14 @@ sub datetime_from { return undef if !@time; - # strptime() counts years from 1900, and months from 0 (January). - # We have to fix both values. + # strptime() counts years from 1900, except if they are older than 1901 + # in which case it returns the full year (so 1890 -> 1890, but 1984 -> 84, + # and 3790 -> 1890). We make a guess and assume that 1100 <= year < 3000. + $time[5] += 1900 if $time[5] < 1100; + my %args = ( - year => $time[5] + 1900, + year => $time[5], + # Months start from 0 (January). month => $time[4] + 1, day => $time[3], hour => $time[2], @@ -609,13 +635,13 @@ sub bz_crypt { $algorithm = $1; } + # Wide characters cause crypt and Digest to die. + if (Bugzilla->params->{'utf8'}) { + utf8::encode($password) if utf8::is_utf8($password); + } + my $crypted_password; if (!$algorithm) { - # Wide characters cause crypt to die - if (Bugzilla->params->{'utf8'}) { - utf8::encode($password) if utf8::is_utf8($password); - } - # Crypt the password. $crypted_password = crypt($password, $salt); @@ -730,10 +756,12 @@ sub get_text { sub template_var { my $name = shift; - my $cache = Bugzilla->request_cache->{util_template_var} ||= {}; - my $template = Bugzilla->template_inner; - my $lang = $template->context->{bz_language}; + my $request_cache = Bugzilla->request_cache; + my $cache = $request_cache->{util_template_var} ||= {}; + my $lang = $request_cache->{template_current_lang}->[0] || ''; return $cache->{$lang}->{$name} if defined $cache->{$lang}; + + my $template = Bugzilla->template_inner($lang); my %vars; # Note: If we suddenly start needing a lot of template_var variables, # they should move into their own template, not field-descs. @@ -750,11 +778,7 @@ sub template_var { sub display_value { my ($field, $value) = @_; - my $value_descs = template_var('value_descs'); - if (defined $value_descs->{$field}->{$value}) { - return $value_descs->{$field}->{$value}; - } - return $value; + return template_var('value_descs')->{$field}->{$value} // $value; } sub disable_utf8 { @@ -763,6 +787,12 @@ sub disable_utf8 { } } +sub enable_utf8 { + if (Bugzilla->params->{'utf8'}) { + binmode STDOUT, ':utf8'; # Turn on UTF8 encoding. + } +} + use constant UTF8_ACCIDENTAL => qw(shiftjis big5-eten euc-kr euc-jp); sub detect_encoding { |