summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Util.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Util.pm')
-rw-r--r--Bugzilla/Util.pm102
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/</&lt;/g;
+ $var =~ s/>/&gt;/g;
+ $var =~ s/"/&quot;/g;
# Obscure '@'.
$var =~ s/\@/\&#64;/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 {