summaryrefslogtreecommitdiffstats
path: root/Bugzilla/Install/Util.pm
diff options
context:
space:
mode:
Diffstat (limited to 'Bugzilla/Install/Util.pm')
-rw-r--r--Bugzilla/Install/Util.pm907
1 files changed, 470 insertions, 437 deletions
diff --git a/Bugzilla/Install/Util.pm b/Bugzilla/Install/Util.pm
index b6d28d9c7..a5522e134 100644
--- a/Bugzilla/Install/Util.pm
+++ b/Bugzilla/Install/Util.pm
@@ -27,367 +27,391 @@ use PerlIO;
use base qw(Exporter);
our @EXPORT_OK = qw(
- bin_loc
- get_version_and_os
- extension_code_files
- i_am_persistent
- indicate_progress
- install_string
- include_languages
- success
- template_include_path
- init_console
+ bin_loc
+ get_version_and_os
+ extension_code_files
+ i_am_persistent
+ indicate_progress
+ install_string
+ include_languages
+ success
+ template_include_path
+ init_console
);
sub bin_loc {
- my ($bin, $path) = @_;
- # This module is not needed most of the time and is a bit slow,
- # so we only load it when calling bin_loc().
- require ExtUtils::MM;
-
- # If the binary is a full path...
- if ($bin =~ m{[/\\]}) {
- return MM->maybe_command($bin) || '';
- }
-
- # Otherwise we look for it in the path in a cross-platform way.
- my @path = $path ? @$path : File::Spec->path;
- foreach my $dir (@path) {
- next if !-d $dir;
- my $full_path = File::Spec->catfile($dir, $bin);
- # MM is an alias for ExtUtils::MM. maybe_command is nice
- # because it checks .com, .bat, .exe (etc.) on Windows.
- my $command = MM->maybe_command($full_path);
- return $command if $command;
- }
-
- return '';
+ my ($bin, $path) = @_;
+
+ # This module is not needed most of the time and is a bit slow,
+ # so we only load it when calling bin_loc().
+ require ExtUtils::MM;
+
+ # If the binary is a full path...
+ if ($bin =~ m{[/\\]}) {
+ return MM->maybe_command($bin) || '';
+ }
+
+ # Otherwise we look for it in the path in a cross-platform way.
+ my @path = $path ? @$path : File::Spec->path;
+ foreach my $dir (@path) {
+ next if !-d $dir;
+ my $full_path = File::Spec->catfile($dir, $bin);
+
+ # MM is an alias for ExtUtils::MM. maybe_command is nice
+ # because it checks .com, .bat, .exe (etc.) on Windows.
+ my $command = MM->maybe_command($full_path);
+ return $command if $command;
+ }
+
+ return '';
}
sub get_version_and_os {
- # Display version information
- my @os_details = POSIX::uname;
- # 0 is the name of the OS, 2 is the major version,
- my $os_name = $os_details[0] . ' ' . $os_details[2];
- if (ON_WINDOWS) {
- require Win32;
- $os_name = Win32::GetOSName();
- }
- # $os_details[3] is the minor version.
- return { bz_ver => BUGZILLA_VERSION,
- perl_ver => sprintf('%vd', $^V),
- os_name => $os_name,
- os_ver => $os_details[3] };
+
+ # Display version information
+ my @os_details = POSIX::uname;
+
+ # 0 is the name of the OS, 2 is the major version,
+ my $os_name = $os_details[0] . ' ' . $os_details[2];
+ if (ON_WINDOWS) {
+ require Win32;
+ $os_name = Win32::GetOSName();
+ }
+
+ # $os_details[3] is the minor version.
+ return {
+ bz_ver => BUGZILLA_VERSION,
+ perl_ver => sprintf('%vd', $^V),
+ os_name => $os_name,
+ os_ver => $os_details[3]
+ };
}
sub _extension_paths {
- my $dir = bz_locations()->{'extensionsdir'};
- my @extension_items = glob("$dir/*");
- my @paths;
- foreach my $item (@extension_items) {
- my $basename = basename($item);
- # Skip CVS directories and any hidden files/dirs.
- next if ($basename eq 'CVS' or $basename =~ /^\./);
- if (-d $item) {
- if (!-e "$item/disabled") {
- push(@paths, $item);
- }
- }
- elsif ($item =~ /\.pm$/i) {
- push(@paths, $item);
- }
- }
- return @paths;
+ my $dir = bz_locations()->{'extensionsdir'};
+ my @extension_items = glob("$dir/*");
+ my @paths;
+ foreach my $item (@extension_items) {
+ my $basename = basename($item);
+
+ # Skip CVS directories and any hidden files/dirs.
+ next if ($basename eq 'CVS' or $basename =~ /^\./);
+ if (-d $item) {
+ if (!-e "$item/disabled") {
+ push(@paths, $item);
+ }
+ }
+ elsif ($item =~ /\.pm$/i) {
+ push(@paths, $item);
+ }
+ }
+ return @paths;
}
sub extension_code_files {
- my ($requirements_only) = @_;
- my @files;
- foreach my $path (_extension_paths()) {
- my @load_files;
- if (-d $path) {
- my $extension_file = "$path/Extension.pm";
- my $config_file = "$path/Config.pm";
- if (-e $extension_file) {
- push(@load_files, $extension_file);
- }
- if (-e $config_file) {
- push(@load_files, $config_file);
- }
-
- # Don't load Extension.pm if we just want Config.pm and
- # we found both.
- if ($requirements_only and scalar(@load_files) == 2) {
- shift(@load_files);
- }
- }
- else {
- push(@load_files, $path);
- }
- next if !scalar(@load_files);
- # We know that these paths are safe, because they came from
- # extensionsdir and we checked them specifically for their format.
- # Also, the only thing we ever do with them is pass them to "require".
- trick_taint($_) foreach @load_files;
- push(@files, \@load_files);
+ my ($requirements_only) = @_;
+ my @files;
+ foreach my $path (_extension_paths()) {
+ my @load_files;
+ if (-d $path) {
+ my $extension_file = "$path/Extension.pm";
+ my $config_file = "$path/Config.pm";
+ if (-e $extension_file) {
+ push(@load_files, $extension_file);
+ }
+ if (-e $config_file) {
+ push(@load_files, $config_file);
+ }
+
+ # Don't load Extension.pm if we just want Config.pm and
+ # we found both.
+ if ($requirements_only and scalar(@load_files) == 2) {
+ shift(@load_files);
+ }
}
+ else {
+ push(@load_files, $path);
+ }
+ next if !scalar(@load_files);
+
+ # We know that these paths are safe, because they came from
+ # extensionsdir and we checked them specifically for their format.
+ # Also, the only thing we ever do with them is pass them to "require".
+ trick_taint($_) foreach @load_files;
+ push(@files, \@load_files);
+ }
- return (\@files);
+ return (\@files);
}
sub indicate_progress {
- my ($params) = @_;
- my $current = $params->{current};
- my $total = $params->{total};
- my $every = $params->{every} || 1;
-
- print "." if !($current % $every);
- if ($current == $total || $current % ($every * 60) == 0) {
- print "$current/$total (" . int($current * 100 / $total) . "%)\n";
- }
+ my ($params) = @_;
+ my $current = $params->{current};
+ my $total = $params->{total};
+ my $every = $params->{every} || 1;
+
+ print "." if !($current % $every);
+ if ($current == $total || $current % ($every * 60) == 0) {
+ print "$current/$total (" . int($current * 100 / $total) . "%)\n";
+ }
}
sub feature_description {
- my ($feature_name) = @_;
- eval {
- my $meta = Bugzilla::CPAN->cpan_meta;
+ my ($feature_name) = @_;
+ eval {
+ my $meta = Bugzilla::CPAN->cpan_meta;
- return $meta->feature($feature_name)->description
- } or warn $@;
+ return $meta->feature($feature_name)->description;
+ } or warn $@;
}
sub install_string {
- my ($string_id, $vars) = @_;
- _cache()->{install_string_path} ||= template_include_path();
- my $path = _cache()->{install_string_path};
-
- my $string_template;
- # Find the first template that defines this string.
- foreach my $dir (@$path) {
- my $base = "$dir/setup/strings";
- $string_template = _get_string_from_file($string_id, "$base.txt.pl")
- if !defined $string_template;
- last if defined $string_template;
- }
-
- die "No language defines the string '$string_id'"
- if !defined $string_template;
-
- utf8::decode($string_template) if !utf8::is_utf8($string_template);
-
- $vars ||= {};
- my @replace_keys = keys %$vars;
- foreach my $key (@replace_keys) {
- my $replacement = $vars->{$key};
- die "'$key' in '$string_id' is tainted: '$replacement'"
- if tainted($replacement);
- # We don't want people to start getting clever and inserting
- # ##variable## into their values. So we check if any other
- # key is listed in the *replacement* string, before doing
- # the replacement. This is mostly to protect programmers from
- # making mistakes.
- if (grep($replacement =~ /##$key##/, @replace_keys)) {
- die "Unsafe replacement for '$key' in '$string_id': '$replacement'";
- }
- $string_template =~ s/\Q##$key##\E/$replacement/g;
- }
-
- return $string_template;
+ my ($string_id, $vars) = @_;
+ _cache()->{install_string_path} ||= template_include_path();
+ my $path = _cache()->{install_string_path};
+
+ my $string_template;
+
+ # Find the first template that defines this string.
+ foreach my $dir (@$path) {
+ my $base = "$dir/setup/strings";
+ $string_template = _get_string_from_file($string_id, "$base.txt.pl")
+ if !defined $string_template;
+ last if defined $string_template;
+ }
+
+ die "No language defines the string '$string_id'" if !defined $string_template;
+
+ utf8::decode($string_template) if !utf8::is_utf8($string_template);
+
+ $vars ||= {};
+ my @replace_keys = keys %$vars;
+ foreach my $key (@replace_keys) {
+ my $replacement = $vars->{$key};
+ die "'$key' in '$string_id' is tainted: '$replacement'"
+ if tainted($replacement);
+
+ # We don't want people to start getting clever and inserting
+ # ##variable## into their values. So we check if any other
+ # key is listed in the *replacement* string, before doing
+ # the replacement. This is mostly to protect programmers from
+ # making mistakes.
+ if (grep($replacement =~ /##$key##/, @replace_keys)) {
+ die "Unsafe replacement for '$key' in '$string_id': '$replacement'";
+ }
+ $string_template =~ s/\Q##$key##\E/$replacement/g;
+ }
+
+ return $string_template;
}
sub _wanted_languages {
- my ($requested, @wanted);
-
- # Checking SERVER_SOFTWARE is the same as i_am_cgi() in Bugzilla::Util.
- if (exists $ENV{'SERVER_SOFTWARE'}) {
- my $cgi = eval { Bugzilla->cgi } || eval { require CGI; return CGI->new() };
- $requested = $cgi->http('Accept-Language') || '';
- my $lang = $cgi->cookie('LANG');
- push(@wanted, $lang) if $lang;
- }
- else {
- $requested = get_console_locale();
- }
-
- push(@wanted, _sort_accept_language($requested));
- return \@wanted;
+ my ($requested, @wanted);
+
+ # Checking SERVER_SOFTWARE is the same as i_am_cgi() in Bugzilla::Util.
+ if (exists $ENV{'SERVER_SOFTWARE'}) {
+ my $cgi = eval { Bugzilla->cgi } || eval { require CGI; return CGI->new() };
+ $requested = $cgi->http('Accept-Language') || '';
+ my $lang = $cgi->cookie('LANG');
+ push(@wanted, $lang) if $lang;
+ }
+ else {
+ $requested = get_console_locale();
+ }
+
+ push(@wanted, _sort_accept_language($requested));
+ return \@wanted;
}
sub _wanted_to_actual_languages {
- my ($wanted, $supported) = @_;
-
- my @actual;
- foreach my $lang (@$wanted) {
- # If we support the language we want, or *any version* of
- # the language we want, it gets pushed into @actual.
- #
- # Per RFC 1766 and RFC 2616, things like 'en' match 'en-us' and
- # 'en-uk', but not the other way around. (This is unfortunately
- # not very clearly stated in those RFC; see comment just over 14.5
- # in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4)
- my @found = grep(/^\Q$lang\E(-.+)?$/i, @$supported);
- push(@actual, @found) if @found;
- }
+ my ($wanted, $supported) = @_;
- # We always include English at the bottom if it's not there, even if
- # it wasn't selected by the user.
- if (!grep($_ eq 'en', @actual)) {
- push(@actual, 'en');
- }
+ my @actual;
+ foreach my $lang (@$wanted) {
- return \@actual;
+ # If we support the language we want, or *any version* of
+ # the language we want, it gets pushed into @actual.
+ #
+ # Per RFC 1766 and RFC 2616, things like 'en' match 'en-us' and
+ # 'en-uk', but not the other way around. (This is unfortunately
+ # not very clearly stated in those RFC; see comment just over 14.5
+ # in http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4)
+ my @found = grep(/^\Q$lang\E(-.+)?$/i, @$supported);
+ push(@actual, @found) if @found;
+ }
+
+ # We always include English at the bottom if it's not there, even if
+ # it wasn't selected by the user.
+ if (!grep($_ eq 'en', @actual)) {
+ push(@actual, 'en');
+ }
+
+ return \@actual;
}
sub supported_languages {
- my $cache = _cache();
- return $cache->{supported_languages} if $cache->{supported_languages};
-
- my @dirs = glob(bz_locations()->{'templatedir'} . "/*");
- my @languages;
- foreach my $dir (@dirs) {
- # It's a language directory only if it contains "default" or
- # "custom". This auto-excludes CVS directories as well.
- next if (!-d "$dir/default" and !-d "$dir/custom");
- my $lang = basename($dir);
- # Check for language tag format conforming to RFC 1766.
- next unless $lang =~ /^[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?$/;
- push(@languages, $lang);
- }
+ my $cache = _cache();
+ return $cache->{supported_languages} if $cache->{supported_languages};
+
+ my @dirs = glob(bz_locations()->{'templatedir'} . "/*");
+ my @languages;
+ foreach my $dir (@dirs) {
- $cache->{supported_languages} = \@languages;
- return \@languages;
+ # It's a language directory only if it contains "default" or
+ # "custom". This auto-excludes CVS directories as well.
+ next if (!-d "$dir/default" and !-d "$dir/custom");
+ my $lang = basename($dir);
+
+ # Check for language tag format conforming to RFC 1766.
+ next unless $lang =~ /^[a-zA-Z]{1,8}(-[a-zA-Z]{1,8})?$/;
+ push(@languages, $lang);
+ }
+
+ $cache->{supported_languages} = \@languages;
+ return \@languages;
}
sub include_languages {
- my ($params) = @_;
-
- # Basically, the way this works is that we have a list of languages
- # that we *want*, and a list of languages that Bugzilla actually
- # supports. If there is only one language installed, we take it.
- my $supported = supported_languages();
- return @$supported if @$supported == 1;
-
- my $wanted;
- if ($params->{language}) {
- # We can pass several languages at once as an arrayref
- # or a single language.
- $wanted = $params->{language};
- $wanted = [$wanted] unless ref $wanted;
- }
- else {
- $wanted = _wanted_languages();
- }
- my $actual = _wanted_to_actual_languages($wanted, $supported);
- return @$actual;
+ my ($params) = @_;
+
+ # Basically, the way this works is that we have a list of languages
+ # that we *want*, and a list of languages that Bugzilla actually
+ # supports. If there is only one language installed, we take it.
+ my $supported = supported_languages();
+ return @$supported if @$supported == 1;
+
+ my $wanted;
+ if ($params->{language}) {
+
+ # We can pass several languages at once as an arrayref
+ # or a single language.
+ $wanted = $params->{language};
+ $wanted = [$wanted] unless ref $wanted;
+ }
+ else {
+ $wanted = _wanted_languages();
+ }
+ my $actual = _wanted_to_actual_languages($wanted, $supported);
+ return @$actual;
}
# Used by template_include_path
sub _template_lang_directories {
- my ($languages, $templatedir) = @_;
-
- my @add = qw(custom default);
- my $project = bz_locations->{'project'};
- unshift(@add, $project) if $project;
-
- my @result;
- foreach my $lang (@$languages) {
- foreach my $dir (@add) {
- my $full_dir = "$templatedir/$lang/$dir";
- if (-d $full_dir) {
- trick_taint($full_dir);
- push(@result, $full_dir);
- }
- }
- }
- return @result;
+ my ($languages, $templatedir) = @_;
+
+ my @add = qw(custom default);
+ my $project = bz_locations->{'project'};
+ unshift(@add, $project) if $project;
+
+ my @result;
+ foreach my $lang (@$languages) {
+ foreach my $dir (@add) {
+ my $full_dir = "$templatedir/$lang/$dir";
+ if (-d $full_dir) {
+ trick_taint($full_dir);
+ push(@result, $full_dir);
+ }
+ }
+ }
+ return @result;
}
# Used by template_include_path.
sub _template_base_directories {
- my @template_dirs;
+ my @template_dirs;
- foreach my $path (_extension_paths()) {
- next if !-d $path;
- if ( -d "$path/template") {
- push(@template_dirs, "$path/template");
- }
+ foreach my $path (_extension_paths()) {
+ next if !-d $path;
+ if (-d "$path/template") {
+ push(@template_dirs, "$path/template");
}
+ }
- state $bz_locations = bz_locations();
- push(@template_dirs, $bz_locations->{'templatedir'});
- return \@template_dirs;
+ state $bz_locations = bz_locations();
+ push(@template_dirs, $bz_locations->{'templatedir'});
+ return \@template_dirs;
}
sub template_include_path {
- my ($params) = @_;
- my @used_languages = include_languages($params);
- # Now, we add template directories in the order they will be searched:
- my $template_dirs = _template_base_directories();
-
- my @include_path;
- foreach my $template_dir (@$template_dirs) {
- my @lang_dirs = _template_lang_directories(\@used_languages,
- $template_dir);
- # Hooks get each set of extension directories separately.
- if ($params->{hook}) {
- push(@include_path, \@lang_dirs);
- }
- # Whereas everything else just gets a whole INCLUDE_PATH.
- else {
- push(@include_path, @lang_dirs);
- }
+ my ($params) = @_;
+ my @used_languages = include_languages($params);
+
+ # Now, we add template directories in the order they will be searched:
+ my $template_dirs = _template_base_directories();
+
+ my @include_path;
+ foreach my $template_dir (@$template_dirs) {
+ my @lang_dirs = _template_lang_directories(\@used_languages, $template_dir);
+
+ # Hooks get each set of extension directories separately.
+ if ($params->{hook}) {
+ push(@include_path, \@lang_dirs);
}
- return \@include_path;
+
+ # Whereas everything else just gets a whole INCLUDE_PATH.
+ else {
+ push(@include_path, @lang_dirs);
+ }
+ }
+ return \@include_path;
}
# This is taken straight from Sort::Versions 1.5, which is not included
# with perl by default.
sub vers_cmp {
- my ($a, $b) = @_;
-
- # Remove leading zeroes - Bug 344661
- $a =~ s/^0*(\d.+)/$1/;
- $b =~ s/^0*(\d.+)/$1/;
-
- my @A = ($a =~ /([-.]|\d+|[^-.\d]+)/g);
- my @B = ($b =~ /([-.]|\d+|[^-.\d]+)/g);
-
- my ($A, $B);
- while (@A and @B) {
- $A = shift @A;
- $B = shift @B;
- if ($A eq '-' and $B eq '-') {
- next;
- } elsif ( $A eq '-' ) {
- return -1;
- } elsif ( $B eq '-') {
- return 1;
- } elsif ($A eq '.' and $B eq '.') {
- next;
- } elsif ( $A eq '.' ) {
- return -1;
- } elsif ( $B eq '.' ) {
- return 1;
- } elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) {
- if ($A =~ /^0/ || $B =~ /^0/) {
- return $A cmp $B if $A cmp $B;
- } else {
- return $A <=> $B if $A <=> $B;
- }
- } else {
- $A = uc $A;
- $B = uc $B;
- return $A cmp $B if $A cmp $B;
- }
+ my ($a, $b) = @_;
+
+ # Remove leading zeroes - Bug 344661
+ $a =~ s/^0*(\d.+)/$1/;
+ $b =~ s/^0*(\d.+)/$1/;
+
+ my @A = ($a =~ /([-.]|\d+|[^-.\d]+)/g);
+ my @B = ($b =~ /([-.]|\d+|[^-.\d]+)/g);
+
+ my ($A, $B);
+ while (@A and @B) {
+ $A = shift @A;
+ $B = shift @B;
+ if ($A eq '-' and $B eq '-') {
+ next;
+ }
+ elsif ($A eq '-') {
+ return -1;
+ }
+ elsif ($B eq '-') {
+ return 1;
+ }
+ elsif ($A eq '.' and $B eq '.') {
+ next;
+ }
+ elsif ($A eq '.') {
+ return -1;
+ }
+ elsif ($B eq '.') {
+ return 1;
+ }
+ elsif ($A =~ /^\d+$/ and $B =~ /^\d+$/) {
+ if ($A =~ /^0/ || $B =~ /^0/) {
+ return $A cmp $B if $A cmp $B;
+ }
+ else {
+ return $A <=> $B if $A <=> $B;
+ }
+ }
+ else {
+ $A = uc $A;
+ $B = uc $B;
+ return $A cmp $B if $A cmp $B;
}
- @A <=> @B;
+ }
+ @A <=> @B;
}
sub no_checksetup_from_cgi {
- print "Content-Type: text/html; charset=UTF-8\r\n\r\n";
- print install_string('no_checksetup_from_cgi');
- exit;
+ print "Content-Type: text/html; charset=UTF-8\r\n\r\n";
+ print install_string('no_checksetup_from_cgi');
+ exit;
}
######################
@@ -396,160 +420,169 @@ sub no_checksetup_from_cgi {
# Used by install_string
sub _get_string_from_file {
- my ($string_id, $file) = @_;
- # If we already loaded the file, then use its copy from the cache.
- if (my $strings = _cache()->{strings_from_file}->{$file}) {
- return $strings->{$string_id};
- }
-
- # This module is only needed by checksetup.pl,
- # so only load it when needed.
- require Safe;
-
- return undef if !-e $file;
- my $safe = new Safe;
- $safe->rdo($file);
- my %strings = %{$safe->varglob('strings')};
- _cache()->{strings_from_file}->{$file} = \%strings;
- return $strings{$string_id};
+ my ($string_id, $file) = @_;
+
+ # If we already loaded the file, then use its copy from the cache.
+ if (my $strings = _cache()->{strings_from_file}->{$file}) {
+ return $strings->{$string_id};
+ }
+
+ # This module is only needed by checksetup.pl,
+ # so only load it when needed.
+ require Safe;
+
+ return undef if !-e $file;
+ my $safe = new Safe;
+ $safe->rdo($file);
+ my %strings = %{$safe->varglob('strings')};
+ _cache()->{strings_from_file}->{$file} = \%strings;
+ return $strings{$string_id};
}
# Make an ordered list out of a HTTP Accept-Language header (see RFC 2616, 14.4)
# We ignore '*' and <language-range>;q=0
# For languages with the same priority q the order remains unchanged.
sub _sort_accept_language {
- sub sortQvalue { $b->{'qvalue'} <=> $a->{'qvalue'} }
- my $accept_language = $_[0];
-
- # clean up string.
- $accept_language =~ s/[^A-Za-z;q=0-9\.\-,]//g;
- my @qlanguages;
- my @languages;
- foreach(split /,/, $accept_language) {
- if (m/([A-Za-z\-]+)(?:;q=(\d(?:\.\d+)))?/) {
- my $lang = $1;
- my $qvalue = $2;
- $qvalue = 1 if not defined $qvalue;
- next if $qvalue == 0;
- $qvalue = 1 if $qvalue > 1;
- push(@qlanguages, {'qvalue' => $qvalue, 'language' => $lang});
- }
- }
-
- return map($_->{'language'}, (sort sortQvalue @qlanguages));
+ sub sortQvalue { $b->{'qvalue'} <=> $a->{'qvalue'} }
+ my $accept_language = $_[0];
+
+ # clean up string.
+ $accept_language =~ s/[^A-Za-z;q=0-9\.\-,]//g;
+ my @qlanguages;
+ my @languages;
+ foreach (split /,/, $accept_language) {
+ if (m/([A-Za-z\-]+)(?:;q=(\d(?:\.\d+)))?/) {
+ my $lang = $1;
+ my $qvalue = $2;
+ $qvalue = 1 if not defined $qvalue;
+ next if $qvalue == 0;
+ $qvalue = 1 if $qvalue > 1;
+ push(@qlanguages, {'qvalue' => $qvalue, 'language' => $lang});
+ }
+ }
+
+ return map($_->{'language'}, (sort sortQvalue @qlanguages));
}
sub get_console_locale {
- require Locale::Language;
- my $locale = setlocale(LC_CTYPE);
- my $language;
- # Some distros set e.g. LC_CTYPE = fr_CH.UTF-8. We clean it up.
- if ($locale =~ /^([^\.]+)/) {
- $locale = $1;
- }
- $locale =~ s/_/-/;
- # It's pretty sure that there is no language pack of the form fr-CH
- # installed, so we also include fr as a wanted language.
- if ($locale =~ /^(\S+)\-/) {
- $language = $1;
- $locale .= ",$language";
- }
- else {
- $language = $locale;
- }
-
- # Some OSs or distributions may have setlocale return a string of the form
- # German_Germany.1252 (this example taken from a Windows XP system), which
- # is unsuitable for our needs because Bugzilla works on language codes.
- # We try and convert them here.
- if ($language = Locale::Language::language2code($language)) {
- $locale .= ",$language";
- }
-
- return $locale;
+ require Locale::Language;
+ my $locale = setlocale(LC_CTYPE);
+ my $language;
+
+ # Some distros set e.g. LC_CTYPE = fr_CH.UTF-8. We clean it up.
+ if ($locale =~ /^([^\.]+)/) {
+ $locale = $1;
+ }
+ $locale =~ s/_/-/;
+
+ # It's pretty sure that there is no language pack of the form fr-CH
+ # installed, so we also include fr as a wanted language.
+ if ($locale =~ /^(\S+)\-/) {
+ $language = $1;
+ $locale .= ",$language";
+ }
+ else {
+ $language = $locale;
+ }
+
+ # Some OSs or distributions may have setlocale return a string of the form
+ # German_Germany.1252 (this example taken from a Windows XP system), which
+ # is unsuitable for our needs because Bugzilla works on language codes.
+ # We try and convert them here.
+ if ($language = Locale::Language::language2code($language)) {
+ $locale .= ",$language";
+ }
+
+ return $locale;
}
sub set_output_encoding {
- # If we've already set an encoding layer on STDOUT, don't
- # add another one.
- my @stdout_layers = PerlIO::get_layers(STDOUT);
- return if grep(/^encoding/, @stdout_layers);
-
- my $encoding;
- if (ON_WINDOWS and eval { require Win32::Console }) {
- # Although setlocale() works on Windows, it doesn't always return
- # the current *console's* encoding. So we use OutputCP here instead,
- # when we can.
- $encoding = Win32::Console::OutputCP();
- }
- else {
- my $locale = setlocale(LC_CTYPE);
- if ($locale =~ /\.([^\.]+)$/) {
- $encoding = $1;
- }
- }
- $encoding = "cp$encoding" if ON_WINDOWS;
- $encoding = Encode::resolve_alias($encoding) if $encoding;
- if ($encoding and $encoding !~ /utf-8/i) {
- binmode STDOUT, ":encoding($encoding)";
- binmode STDERR, ":encoding($encoding)";
- }
- else {
- binmode STDOUT, ':utf8';
- binmode STDERR, ':utf8';
- }
+ # If we've already set an encoding layer on STDOUT, don't
+ # add another one.
+ my @stdout_layers = PerlIO::get_layers(STDOUT);
+ return if grep(/^encoding/, @stdout_layers);
+
+ my $encoding;
+ if (ON_WINDOWS and eval { require Win32::Console }) {
+
+ # Although setlocale() works on Windows, it doesn't always return
+ # the current *console's* encoding. So we use OutputCP here instead,
+ # when we can.
+ $encoding = Win32::Console::OutputCP();
+ }
+ else {
+ my $locale = setlocale(LC_CTYPE);
+ if ($locale =~ /\.([^\.]+)$/) {
+ $encoding = $1;
+ }
+ }
+ $encoding = "cp$encoding" if ON_WINDOWS;
+
+ $encoding = Encode::resolve_alias($encoding) if $encoding;
+ if ($encoding and $encoding !~ /utf-8/i) {
+ binmode STDOUT, ":encoding($encoding)";
+ binmode STDERR, ":encoding($encoding)";
+ }
+ else {
+ binmode STDOUT, ':utf8';
+ binmode STDERR, ':utf8';
+ }
}
sub init_console {
- eval { ON_WINDOWS && require Win32::Console::ANSI; };
- $ENV{'ANSI_COLORS_DISABLED'} = 1 if ($@ || !-t *STDOUT);
- $SIG{__DIE__} = \&_console_die;
- prevent_windows_dialog_boxes();
- set_output_encoding();
+ eval { ON_WINDOWS && require Win32::Console::ANSI; };
+ $ENV{'ANSI_COLORS_DISABLED'} = 1 if ($@ || !-t *STDOUT);
+ $SIG{__DIE__} = \&_console_die;
+ prevent_windows_dialog_boxes();
+ set_output_encoding();
}
sub _console_die {
- my ($message) = @_;
- # $^S means "we are in an eval"
- if ($^S) {
- die $message;
- }
- # Remove newlines from the message before we color it, and then
- # add them back in on display. Otherwise the ANSI escape code
- # for resetting the color comes after the newline, and Perl thinks
- # that it should put "at Bugzilla/Install.pm line 1234" after the
- # message.
- $message =~ s/\n+$//;
- # We put quotes around the message to stringify any object exceptions,
- # like Template::Exception.
- die colored("$message", COLOR_ERROR) . "\n";
+ my ($message) = @_;
+
+ # $^S means "we are in an eval"
+ if ($^S) {
+ die $message;
+ }
+
+ # Remove newlines from the message before we color it, and then
+ # add them back in on display. Otherwise the ANSI escape code
+ # for resetting the color comes after the newline, and Perl thinks
+ # that it should put "at Bugzilla/Install.pm line 1234" after the
+ # message.
+ $message =~ s/\n+$//;
+
+ # We put quotes around the message to stringify any object exceptions,
+ # like Template::Exception.
+ die colored("$message", COLOR_ERROR) . "\n";
}
sub success {
- my ($message) = @_;
- print colored($message, COLOR_SUCCESS), "\n";
+ my ($message) = @_;
+ print colored($message, COLOR_SUCCESS), "\n";
}
sub prevent_windows_dialog_boxes {
- # This code comes from http://bugs.activestate.com/show_bug.cgi?id=82183
- # and prevents Perl modules from popping up dialog boxes, particularly
- # during checksetup (since loading DBD::Oracle during checksetup when
- # Oracle isn't installed causes a scary popup and pauses checksetup).
- #
- # Win32::API ships with ActiveState by default, though there could
- # theoretically be a Windows installation without it, I suppose.
- if (ON_WINDOWS and eval { require Win32::API }) {
- # Call kernel32.SetErrorMode with arguments that mean:
- # "The system does not display the critical-error-handler message box.
- # Instead, the system sends the error to the calling process." and
- # "A child process inherits the error mode of its parent process."
- my $SetErrorMode = Win32::API->new('kernel32', 'SetErrorMode',
- 'I', 'I');
- my $SEM_FAILCRITICALERRORS = 0x0001;
- my $SEM_NOGPFAULTERRORBOX = 0x0002;
- $SetErrorMode->Call($SEM_FAILCRITICALERRORS | $SEM_NOGPFAULTERRORBOX);
- }
+
+ # This code comes from http://bugs.activestate.com/show_bug.cgi?id=82183
+ # and prevents Perl modules from popping up dialog boxes, particularly
+ # during checksetup (since loading DBD::Oracle during checksetup when
+ # Oracle isn't installed causes a scary popup and pauses checksetup).
+ #
+ # Win32::API ships with ActiveState by default, though there could
+ # theoretically be a Windows installation without it, I suppose.
+ if (ON_WINDOWS and eval { require Win32::API }) {
+
+ # Call kernel32.SetErrorMode with arguments that mean:
+ # "The system does not display the critical-error-handler message box.
+ # Instead, the system sends the error to the calling process." and
+ # "A child process inherits the error mode of its parent process."
+ my $SetErrorMode = Win32::API->new('kernel32', 'SetErrorMode', 'I', 'I');
+ my $SEM_FAILCRITICALERRORS = 0x0001;
+ my $SEM_NOGPFAULTERRORBOX = 0x0002;
+ $SetErrorMode->Call($SEM_FAILCRITICALERRORS | $SEM_NOGPFAULTERRORBOX);
+ }
}
# This is like request_cache, but it's used only by installation code
@@ -561,20 +594,20 @@ use constant _cache => {};
##############################
sub trick_taint {
- require Carp;
- Carp::confess("Undef to trick_taint") unless defined $_[0];
- my $match = $_[0] =~ /^(.*)$/s;
- $_[0] = $match ? $1 : undef;
- return (defined($_[0]));
+ require Carp;
+ Carp::confess("Undef to trick_taint") unless defined $_[0];
+ my $match = $_[0] =~ /^(.*)$/s;
+ $_[0] = $match ? $1 : undef;
+ return (defined($_[0]));
}
sub trim {
- my ($str) = @_;
- if ($str) {
- $str =~ s/^\s+//g;
- $str =~ s/\s+$//g;
- }
- return $str;
+ my ($str) = @_;
+ if ($str) {
+ $str =~ s/^\s+//g;
+ $str =~ s/\s+$//g;
+ }
+ return $str;
}
__END__