2002-08-19 13:59:45 +00:00
|
|
|
# -*- Mode: perl; indent-tabs-mode: nil -*-
|
|
|
|
#
|
|
|
|
# The contents of this file are subject to the Mozilla Public
|
|
|
|
# License Version 1.1 (the "License"); you may not use this file
|
|
|
|
# except in compliance with the License. You may obtain a copy of
|
|
|
|
# the License at http://www.mozilla.org/MPL/
|
|
|
|
#
|
|
|
|
# Software distributed under the License is distributed on an "AS
|
|
|
|
# IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
# implied. See the License for the specific language governing
|
|
|
|
# rights and limitations under the License.
|
|
|
|
#
|
|
|
|
# The Original Code is the Bugzilla Bug Tracking System.
|
|
|
|
#
|
|
|
|
# The Initial Developer of the Original Code is Netscape Communications
|
|
|
|
# Corporation. Portions created by Netscape are
|
|
|
|
# Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
# Rights Reserved.
|
|
|
|
#
|
|
|
|
# Contributor(s): Terry Weissman <terry@mozilla.org>
|
|
|
|
# Dan Mosedale <dmose@mozilla.org>
|
2002-08-27 04:28:05 +00:00
|
|
|
# Jacob Steenhagen <jake@bugzilla.org>
|
2002-08-19 13:59:45 +00:00
|
|
|
# Bradley Baetz <bbaetz@student.usyd.edu.au>
|
|
|
|
# Christopher Aillon <christopher@aillon.com>
|
2005-06-15 03:55:00 +00:00
|
|
|
# Max Kanat-Alexander <mkanat@bugzilla.org>
|
2005-09-01 21:39:21 +00:00
|
|
|
# Frédéric Buclin <LpSolit@gmail.com>
|
2002-08-19 13:59:45 +00:00
|
|
|
|
|
|
|
package Bugzilla::Util;
|
|
|
|
|
2002-12-15 09:24:08 +00:00
|
|
|
use strict;
|
2002-11-27 16:00:44 +00:00
|
|
|
|
2002-10-16 10:49:56 +00:00
|
|
|
use base qw(Exporter);
|
|
|
|
@Bugzilla::Util::EXPORT = qw(is_tainted trick_taint detaint_natural
|
2005-05-03 19:41:23 +00:00
|
|
|
detaint_signed
|
2002-12-15 09:24:08 +00:00
|
|
|
html_quote url_quote value_quote xml_quote
|
2003-08-22 13:55:23 +00:00
|
|
|
css_class_quote
|
2005-07-14 06:01:35 +00:00
|
|
|
i_am_cgi
|
2002-10-16 10:49:56 +00:00
|
|
|
lsearch max min
|
2005-04-19 17:55:10 +00:00
|
|
|
diff_arrays diff_strings
|
|
|
|
trim wrap_comment find_wrap_point
|
2005-08-15 17:58:19 +00:00
|
|
|
perform_substs
|
2005-08-15 17:43:38 +00:00
|
|
|
format_time format_time_decimal validate_date
|
2005-08-04 11:51:25 +00:00
|
|
|
file_mod_time is_7bit_clean
|
2005-09-01 21:39:21 +00:00
|
|
|
bz_crypt generate_random_password
|
2005-12-29 22:56:01 +00:00
|
|
|
validate_email_syntax clean_text);
|
2002-10-16 10:49:56 +00:00
|
|
|
|
2002-12-15 09:24:08 +00:00
|
|
|
use Bugzilla::Config;
|
2005-02-09 17:30:20 +00:00
|
|
|
use Bugzilla::Constants;
|
2005-08-15 17:43:38 +00:00
|
|
|
|
2005-01-16 13:36:05 +00:00
|
|
|
use Date::Parse;
|
|
|
|
use Date::Format;
|
2005-02-27 01:14:08 +00:00
|
|
|
use Text::Wrap;
|
2002-10-16 10:49:56 +00:00
|
|
|
|
|
|
|
# This is from the perlsec page, slightly modifed to remove a warning
|
|
|
|
# From that page:
|
|
|
|
# This function makes use of the fact that the presence of
|
|
|
|
# tainted data anywhere within an expression renders the
|
|
|
|
# entire expression tainted.
|
|
|
|
# Don't ask me how it works...
|
|
|
|
sub is_tainted {
|
|
|
|
return not eval { my $foo = join('',@_), kill 0; 1; };
|
|
|
|
}
|
|
|
|
|
|
|
|
sub trick_taint {
|
2003-11-22 03:50:42 +00:00
|
|
|
require Carp;
|
|
|
|
Carp::confess("Undef to trick_taint") unless defined $_[0];
|
2005-06-16 19:00:58 +00:00
|
|
|
my ($match) = $_[0] =~ /^(.*)$/s;
|
|
|
|
$_[0] = $match;
|
2002-10-16 10:49:56 +00:00
|
|
|
return (defined($_[0]));
|
|
|
|
}
|
|
|
|
|
|
|
|
sub detaint_natural {
|
2005-06-16 19:00:58 +00:00
|
|
|
my ($match) = $_[0] =~ /^(\d+)$/;
|
|
|
|
$_[0] = $match;
|
2002-10-16 10:49:56 +00:00
|
|
|
return (defined($_[0]));
|
|
|
|
}
|
|
|
|
|
2005-05-03 19:41:23 +00:00
|
|
|
sub detaint_signed {
|
2005-06-16 19:00:58 +00:00
|
|
|
my ($match) = $_[0] =~ /^([-+]?\d+)$/;
|
|
|
|
$_[0] = $match;
|
2005-05-03 19:41:23 +00:00
|
|
|
# Remove any leading plus sign.
|
|
|
|
if (defined($_[0]) && $_[0] =~ /^\+(\d+)$/) {
|
|
|
|
$_[0] = $1;
|
|
|
|
}
|
|
|
|
return (defined($_[0]));
|
|
|
|
}
|
|
|
|
|
2002-10-16 10:49:56 +00:00
|
|
|
sub html_quote {
|
|
|
|
my ($var) = (@_);
|
|
|
|
$var =~ s/\&/\&/g;
|
|
|
|
$var =~ s/</\</g;
|
|
|
|
$var =~ s/>/\>/g;
|
|
|
|
$var =~ s/\"/\"/g;
|
|
|
|
return $var;
|
|
|
|
}
|
|
|
|
|
2005-11-25 21:57:13 +00:00
|
|
|
# This originally came from CGI.pm, by Lincoln D. Stein
|
2002-10-26 01:57:09 +00:00
|
|
|
sub url_quote {
|
|
|
|
my ($toencode) = (@_);
|
|
|
|
$toencode =~ s/([^a-zA-Z0-9_\-.])/uc sprintf("%%%02x",ord($1))/eg;
|
|
|
|
return $toencode;
|
|
|
|
}
|
|
|
|
|
2003-08-22 13:55:23 +00:00
|
|
|
sub css_class_quote {
|
|
|
|
my ($toencode) = (@_);
|
|
|
|
$toencode =~ s/ /_/g;
|
|
|
|
$toencode =~ s/([^a-zA-Z0-9_\-.])/uc sprintf("&#x%x;",ord($1))/eg;
|
|
|
|
return $toencode;
|
|
|
|
}
|
|
|
|
|
2002-10-16 10:49:56 +00:00
|
|
|
sub value_quote {
|
|
|
|
my ($var) = (@_);
|
|
|
|
$var =~ s/\&/\&/g;
|
|
|
|
$var =~ s/</\</g;
|
|
|
|
$var =~ s/>/\>/g;
|
|
|
|
$var =~ s/\"/\"/g;
|
|
|
|
# See bug http://bugzilla.mozilla.org/show_bug.cgi?id=4928 for
|
|
|
|
# explanaion of why bugzilla does this linebreak substitution.
|
|
|
|
# This caused form submission problems in mozilla (bug 22983, 32000).
|
|
|
|
$var =~ s/\r\n/\
/g;
|
|
|
|
$var =~ s/\n\r/\
/g;
|
|
|
|
$var =~ s/\r/\
/g;
|
|
|
|
$var =~ s/\n/\
/g;
|
|
|
|
return $var;
|
|
|
|
}
|
|
|
|
|
2002-12-15 09:24:08 +00:00
|
|
|
sub xml_quote {
|
|
|
|
my ($var) = (@_);
|
|
|
|
$var =~ s/\&/\&/g;
|
|
|
|
$var =~ s/</\</g;
|
|
|
|
$var =~ s/>/\>/g;
|
|
|
|
$var =~ s/\"/\"/g;
|
|
|
|
$var =~ s/\'/\'/g;
|
|
|
|
return $var;
|
|
|
|
}
|
|
|
|
|
2005-07-20 21:30:58 +00:00
|
|
|
sub url_decode {
|
|
|
|
my ($todecode) = (@_);
|
|
|
|
$todecode =~ tr/+/ /; # pluses become spaces
|
|
|
|
$todecode =~ s/%([0-9a-fA-F]{2})/pack("c",hex($1))/ge;
|
|
|
|
return $todecode;
|
|
|
|
}
|
|
|
|
|
2005-08-13 12:27:04 +00:00
|
|
|
sub i_am_cgi {
|
2005-07-14 06:01:35 +00:00
|
|
|
# I use SERVER_SOFTWARE because it's required to be
|
|
|
|
# defined for all requests in the CGI spec.
|
|
|
|
return exists $ENV{'SERVER_SOFTWARE'} ? 1 : 0;
|
|
|
|
}
|
|
|
|
|
2002-10-16 10:49:56 +00:00
|
|
|
sub lsearch {
|
|
|
|
my ($list,$item) = (@_);
|
|
|
|
my $count = 0;
|
|
|
|
foreach my $i (@$list) {
|
|
|
|
if ($i eq $item) {
|
|
|
|
return $count;
|
|
|
|
}
|
|
|
|
$count++;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub max {
|
|
|
|
my $max = shift(@_);
|
|
|
|
foreach my $val (@_) {
|
|
|
|
$max = $val if $val > $max;
|
|
|
|
}
|
|
|
|
return $max;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub min {
|
|
|
|
my $min = shift(@_);
|
|
|
|
foreach my $val (@_) {
|
|
|
|
$min = $val if $val < $min;
|
|
|
|
}
|
|
|
|
return $min;
|
|
|
|
}
|
|
|
|
|
2005-02-25 02:34:11 +00:00
|
|
|
sub diff_arrays {
|
|
|
|
my ($old_ref, $new_ref) = @_;
|
|
|
|
|
|
|
|
my @old = @$old_ref;
|
|
|
|
my @new = @$new_ref;
|
|
|
|
|
|
|
|
# For each pair of (old, new) entries:
|
|
|
|
# If they're equal, set them to empty. When done, @old contains entries
|
|
|
|
# that were removed; @new contains ones that got added.
|
|
|
|
foreach my $oldv (@old) {
|
|
|
|
foreach my $newv (@new) {
|
|
|
|
next if ($newv eq '');
|
|
|
|
if ($oldv eq $newv) {
|
|
|
|
$newv = $oldv = '';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
my @removed = grep { $_ ne '' } @old;
|
|
|
|
my @added = grep { $_ ne '' } @new;
|
|
|
|
return (\@removed, \@added);
|
|
|
|
}
|
|
|
|
|
2002-10-16 10:49:56 +00:00
|
|
|
sub trim {
|
|
|
|
my ($str) = @_;
|
2003-04-25 05:41:29 +00:00
|
|
|
if ($str) {
|
|
|
|
$str =~ s/^\s+//g;
|
|
|
|
$str =~ s/\s+$//g;
|
|
|
|
}
|
2002-10-16 10:49:56 +00:00
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2005-01-16 13:02:35 +00:00
|
|
|
sub diff_strings {
|
|
|
|
my ($oldstr, $newstr) = @_;
|
|
|
|
|
|
|
|
# Split the old and new strings into arrays containing their values.
|
|
|
|
$oldstr =~ s/[\s,]+/ /g;
|
|
|
|
$newstr =~ s/[\s,]+/ /g;
|
|
|
|
my @old = split(" ", $oldstr);
|
|
|
|
my @new = split(" ", $newstr);
|
|
|
|
|
2005-02-25 02:34:11 +00:00
|
|
|
my ($rem, $add) = diff_arrays(\@old, \@new);
|
2005-01-16 13:02:35 +00:00
|
|
|
|
2005-02-25 02:34:11 +00:00
|
|
|
my $removed = join (", ", @$rem);
|
|
|
|
my $added = join (", ", @$add);
|
2005-01-16 13:02:35 +00:00
|
|
|
|
|
|
|
return ($removed, $added);
|
|
|
|
}
|
|
|
|
|
2005-08-13 12:27:04 +00:00
|
|
|
sub wrap_comment {
|
2005-02-09 17:30:20 +00:00
|
|
|
my ($comment) = @_;
|
2005-02-27 01:14:08 +00:00
|
|
|
my $wrappedcomment = "";
|
|
|
|
|
|
|
|
# Use 'local', as recommended by Text::Wrap's perldoc.
|
|
|
|
local $Text::Wrap::columns = COMMENT_COLS;
|
|
|
|
# Make words that are longer than COMMENT_COLS not wrap.
|
|
|
|
local $Text::Wrap::huge = 'overflow';
|
|
|
|
# Don't mess with tabs.
|
|
|
|
local $Text::Wrap::unexpand = 0;
|
|
|
|
|
|
|
|
# If the line starts with ">", don't wrap it. Otherwise, wrap.
|
|
|
|
foreach my $line (split(/\r\n|\r|\n/, $comment)) {
|
|
|
|
if ($line =~ qr/^>/) {
|
|
|
|
$wrappedcomment .= ($line . "\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$wrappedcomment .= (wrap('', '', $line) . "\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return $wrappedcomment;
|
2005-02-09 17:30:20 +00:00
|
|
|
}
|
|
|
|
|
2005-08-13 12:27:04 +00:00
|
|
|
sub find_wrap_point {
|
2005-04-19 17:55:10 +00:00
|
|
|
my ($string, $maxpos) = @_;
|
|
|
|
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
|
|
|
|
$wrappoint = rindex($string, " ", $maxpos); # look for space
|
|
|
|
if ($wrappoint < 0) { # can't find space
|
|
|
|
$wrappoint = rindex($string, "-", $maxpos); # look for hyphen
|
|
|
|
if ($wrappoint < 0) { # can't find hyphen
|
|
|
|
$wrappoint = $maxpos; # just truncate it
|
|
|
|
} else {
|
|
|
|
$wrappoint++; # leave hyphen on the left side
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return $wrappoint;
|
|
|
|
}
|
|
|
|
|
2005-08-15 17:58:19 +00:00
|
|
|
sub perform_substs {
|
|
|
|
my ($str, $substs) = (@_);
|
|
|
|
$str =~ s/%([a-z]*)%/(defined $substs->{$1} ? $substs->{$1} : Param($1))/eg;
|
|
|
|
return $str;
|
|
|
|
}
|
|
|
|
|
2005-08-13 12:27:04 +00:00
|
|
|
sub format_time {
|
2005-05-10 20:30:13 +00:00
|
|
|
my ($date, $format) = @_;
|
|
|
|
|
|
|
|
# If $format is undefined, try to guess the correct date format.
|
|
|
|
my $show_timezone;
|
|
|
|
if (!defined($format)) {
|
|
|
|
if ($date =~ m/^(\d{4})[-\.](\d{2})[-\.](\d{2}) (\d{2}):(\d{2})(:(\d{2}))?$/) {
|
|
|
|
my $sec = $7;
|
|
|
|
if (defined $sec) {
|
|
|
|
$format = "%Y-%m-%d %T";
|
|
|
|
} else {
|
|
|
|
$format = "%Y-%m-%d %R";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
# Default date format. See Date::Format for other formats available.
|
|
|
|
$format = "%Y-%m-%d %R";
|
|
|
|
}
|
|
|
|
# By default, we want the timezone to be displayed.
|
|
|
|
$show_timezone = 1;
|
2002-11-27 16:00:44 +00:00
|
|
|
}
|
|
|
|
else {
|
2005-05-10 20:30:13 +00:00
|
|
|
# Search for %Z or %z, meaning we want the timezone to be displayed.
|
|
|
|
# Till bug 182238 gets fixed, we assume Param('timezone') is used.
|
|
|
|
$show_timezone = ($format =~ s/\s?%Z$//i);
|
2002-11-27 16:00:44 +00:00
|
|
|
}
|
|
|
|
|
2005-05-10 20:30:13 +00:00
|
|
|
# str2time($date) is undefined if $date has an invalid date format.
|
|
|
|
my $time = str2time($date);
|
|
|
|
|
|
|
|
if (defined $time) {
|
|
|
|
$date = time2str($format, $time);
|
|
|
|
$date .= " " . &::Param('timezone') if $show_timezone;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
# Don't let invalid (time) strings to be passed to templates!
|
|
|
|
$date = '';
|
2002-11-27 16:00:44 +00:00
|
|
|
}
|
2005-05-10 20:30:13 +00:00
|
|
|
return trim($date);
|
2002-11-27 16:00:44 +00:00
|
|
|
}
|
|
|
|
|
2005-01-16 13:25:46 +00:00
|
|
|
sub format_time_decimal {
|
|
|
|
my ($time) = (@_);
|
|
|
|
|
|
|
|
my $newtime = sprintf("%.2f", $time);
|
|
|
|
|
|
|
|
if ($newtime =~ /0\Z/) {
|
|
|
|
$newtime = sprintf("%.1f", $time);
|
|
|
|
}
|
|
|
|
|
|
|
|
return $newtime;
|
|
|
|
}
|
|
|
|
|
2005-08-13 12:27:04 +00:00
|
|
|
sub file_mod_time {
|
2005-01-27 20:08:34 +00:00
|
|
|
my ($filename) = (@_);
|
|
|
|
my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
|
|
|
|
$atime,$mtime,$ctime,$blksize,$blocks)
|
|
|
|
= stat($filename);
|
|
|
|
return $mtime;
|
|
|
|
}
|
|
|
|
|
2005-08-13 12:27:04 +00:00
|
|
|
sub bz_crypt {
|
2005-07-13 03:57:02 +00:00
|
|
|
my ($password) = @_;
|
|
|
|
|
|
|
|
# The list of characters that can appear in a salt. Salts and hashes
|
|
|
|
# are both encoded as a sequence of characters from a set containing
|
|
|
|
# 64 characters, each one of which represents 6 bits of the salt/hash.
|
|
|
|
# The encoding is similar to BASE64, the difference being that the
|
|
|
|
# BASE64 plus sign (+) is replaced with a forward slash (/).
|
|
|
|
my @saltchars = (0..9, 'A'..'Z', 'a'..'z', '.', '/');
|
|
|
|
|
|
|
|
# Generate the salt. We use an 8 character (48 bit) salt for maximum
|
|
|
|
# security on systems whose crypt uses MD5. Systems with older
|
|
|
|
# versions of crypt will just use the first two characters of the salt.
|
|
|
|
my $salt = '';
|
|
|
|
for ( my $i=0 ; $i < 8 ; ++$i ) {
|
|
|
|
$salt .= $saltchars[rand(64)];
|
|
|
|
}
|
|
|
|
|
|
|
|
# Crypt the password.
|
|
|
|
my $cryptedpassword = crypt($password, $salt);
|
|
|
|
|
|
|
|
# Return the crypted password.
|
|
|
|
return $cryptedpassword;
|
|
|
|
}
|
|
|
|
|
2005-09-01 21:39:21 +00:00
|
|
|
sub generate_random_password {
|
|
|
|
my $size = shift || 10; # default to 10 chars if nothing specified
|
|
|
|
return join("", map{ ('0'..'9','a'..'z','A'..'Z')[rand 62] } (1..$size));
|
|
|
|
}
|
|
|
|
|
2005-08-15 17:43:38 +00:00
|
|
|
sub validate_email_syntax {
|
|
|
|
my ($addr) = @_;
|
2005-07-20 21:24:19 +00:00
|
|
|
my $match = Param('emailregexp');
|
2005-08-15 17:43:38 +00:00
|
|
|
my $ret = ($addr =~ /$match/ && $addr !~ /[\\\(\)<>&,;:"\[\] \t\r\n]/);
|
|
|
|
return $ret ? 1 : 0;
|
2005-07-20 21:24:19 +00:00
|
|
|
}
|
|
|
|
|
2005-08-15 17:43:38 +00:00
|
|
|
sub validate_date {
|
|
|
|
my ($date) = @_;
|
2005-02-25 03:28:02 +00:00
|
|
|
my $date2;
|
2005-01-16 13:36:05 +00:00
|
|
|
|
2005-02-25 03:28:02 +00:00
|
|
|
# $ts is undefined if the parser fails.
|
|
|
|
my $ts = str2time($date);
|
|
|
|
if ($ts) {
|
|
|
|
$date2 = time2str("%Y-%m-%d", $ts);
|
2005-01-16 13:36:05 +00:00
|
|
|
|
2005-02-25 03:28:02 +00:00
|
|
|
$date =~ s/(\d+)-0*(\d+?)-0*(\d+?)/$1-$2-$3/;
|
|
|
|
$date2 =~ s/(\d+)-0*(\d+?)-0*(\d+?)/$1-$2-$3/;
|
|
|
|
}
|
2005-08-15 17:43:38 +00:00
|
|
|
my $ret = ($ts && $date eq $date2);
|
|
|
|
return $ret ? 1 : 0;
|
2005-01-16 13:36:05 +00:00
|
|
|
}
|
|
|
|
|
2005-08-04 11:51:25 +00:00
|
|
|
sub is_7bit_clean {
|
|
|
|
return $_[0] !~ /[^\x20-\x7E\x0A\x0D]/;
|
|
|
|
}
|
|
|
|
|
2005-12-29 22:56:01 +00:00
|
|
|
sub clean_text {
|
|
|
|
my ($dtext) = shift;
|
2006-01-08 19:56:04 +00:00
|
|
|
$dtext =~ s/[\x00-\x1F\x7F]+/ /g; # change control characters into a space
|
|
|
|
return trim($dtext);
|
2005-12-29 22:56:01 +00:00
|
|
|
}
|
|
|
|
|
2002-10-16 10:49:56 +00:00
|
|
|
1;
|
|
|
|
|
|
|
|
__END__
|
|
|
|
|
2002-08-19 13:59:45 +00:00
|
|
|
=head1 NAME
|
|
|
|
|
|
|
|
Bugzilla::Util - Generic utility functions for bugzilla
|
|
|
|
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
use Bugzilla::Util;
|
|
|
|
|
|
|
|
# Functions for dealing with variable tainting
|
|
|
|
$rv = is_tainted($var);
|
|
|
|
trick_taint($var);
|
|
|
|
detaint_natural($var);
|
2005-05-03 19:41:23 +00:00
|
|
|
detaint_signed($var);
|
2002-08-19 13:59:45 +00:00
|
|
|
|
|
|
|
# Functions for quoting
|
|
|
|
html_quote($var);
|
2002-10-26 01:57:09 +00:00
|
|
|
url_quote($var);
|
2002-08-19 13:59:45 +00:00
|
|
|
value_quote($var);
|
2002-12-15 09:24:08 +00:00
|
|
|
xml_quote($var);
|
2002-08-19 13:59:45 +00:00
|
|
|
|
2005-07-20 21:30:58 +00:00
|
|
|
# Functions for decoding
|
|
|
|
$rv = url_decode($var);
|
2005-07-26 14:09:48 +00:00
|
|
|
|
2005-07-14 06:01:35 +00:00
|
|
|
# Functions that tell you about your environment
|
|
|
|
my $is_cgi = i_am_cgi();
|
|
|
|
|
2002-08-19 13:59:45 +00:00
|
|
|
# Functions for searching
|
|
|
|
$loc = lsearch(\@arr, $val);
|
|
|
|
$val = max($a, $b, $c);
|
|
|
|
$val = min($a, $b, $c);
|
|
|
|
|
2005-02-25 02:34:11 +00:00
|
|
|
# Data manipulation
|
|
|
|
($removed, $added) = diff_arrays(\@old, \@new);
|
|
|
|
|
2005-01-16 13:02:35 +00:00
|
|
|
# Functions for manipulating strings
|
2002-08-19 13:59:45 +00:00
|
|
|
$val = trim(" abc ");
|
2005-01-16 13:02:35 +00:00
|
|
|
($removed, $added) = diff_strings($old, $new);
|
2005-02-09 17:30:20 +00:00
|
|
|
$wrapped = wrap_comment($comment);
|
2005-08-15 17:58:19 +00:00
|
|
|
$msg = perform_substs($str, $substs);
|
2002-08-19 13:59:45 +00:00
|
|
|
|
2002-11-27 16:00:44 +00:00
|
|
|
# Functions for formatting time
|
|
|
|
format_time($time);
|
|
|
|
|
2005-01-27 20:08:34 +00:00
|
|
|
# Functions for dealing with files
|
|
|
|
$time = file_mod_time($filename);
|
|
|
|
|
2005-07-13 03:57:02 +00:00
|
|
|
# Cryptographic Functions
|
|
|
|
$crypted_password = bz_crypt($password);
|
2005-09-01 21:39:21 +00:00
|
|
|
$new_password = generate_random_password($password_length);
|
2005-07-13 03:57:02 +00:00
|
|
|
|
2005-07-20 21:30:58 +00:00
|
|
|
# Validation Functions
|
2005-08-15 17:43:38 +00:00
|
|
|
validate_email_syntax($email);
|
|
|
|
validate_date($date);
|
2005-07-20 21:30:58 +00:00
|
|
|
|
2002-08-19 13:59:45 +00:00
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
This package contains various utility functions which do not belong anywhere
|
|
|
|
else.
|
|
|
|
|
|
|
|
B<It is not intended as a general dumping group for something which
|
|
|
|
people feel might be useful somewhere, someday>. Do not add methods to this
|
|
|
|
package unless it is intended to be used for a significant number of files,
|
|
|
|
and it does not belong anywhere else.
|
|
|
|
|
|
|
|
=head1 FUNCTIONS
|
|
|
|
|
|
|
|
This package provides several types of routines:
|
|
|
|
|
|
|
|
=head2 Tainting
|
|
|
|
|
|
|
|
Several functions are available to deal with tainted variables. B<Use these
|
|
|
|
with care> to avoid security holes.
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item C<is_tainted>
|
|
|
|
|
|
|
|
Determines whether a particular variable is tainted
|
|
|
|
|
|
|
|
=item C<trick_taint($val)>
|
|
|
|
|
|
|
|
Tricks perl into untainting a particular variable.
|
|
|
|
|
|
|
|
Use trick_taint() when you know that there is no way that the data
|
|
|
|
in a scalar can be tainted, but taint mode still bails on it.
|
|
|
|
|
|
|
|
B<WARNING!! Using this routine on data that really could be tainted defeats
|
2002-08-19 14:30:28 +00:00
|
|
|
the purpose of taint mode. It should only be used on variables that have been
|
|
|
|
sanity checked in some way and have been determined to be OK.>
|
2002-08-19 13:59:45 +00:00
|
|
|
|
|
|
|
=item C<detaint_natural($num)>
|
|
|
|
|
|
|
|
This routine detaints a natural number. It returns a true value if the
|
|
|
|
value passed in was a valid natural number, else it returns false. You
|
|
|
|
B<MUST> check the result of this routine to avoid security holes.
|
|
|
|
|
2005-05-03 19:41:23 +00:00
|
|
|
=item C<detaint_signed($num)>
|
|
|
|
|
|
|
|
This routine detaints a signed integer. It returns a true value if the
|
|
|
|
value passed in was a valid signed integer, else it returns false. You
|
|
|
|
B<MUST> check the result of this routine to avoid security holes.
|
|
|
|
|
2002-08-19 13:59:45 +00:00
|
|
|
=back
|
|
|
|
|
|
|
|
=head2 Quoting
|
|
|
|
|
|
|
|
Some values may need to be quoted from perl. However, this should in general
|
|
|
|
be done in the template where possible.
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item C<html_quote($val)>
|
|
|
|
|
|
|
|
Returns a value quoted for use in HTML, with &, E<lt>, E<gt>, and E<34> being
|
|
|
|
replaced with their appropriate HTML entities.
|
|
|
|
|
2002-10-26 01:57:09 +00:00
|
|
|
=item C<url_quote($val)>
|
|
|
|
|
|
|
|
Quotes characters so that they may be included as part of a url.
|
|
|
|
|
2003-08-22 13:55:23 +00:00
|
|
|
=item C<css_class_quote($val)>
|
|
|
|
|
|
|
|
Quotes characters so that they may be used as CSS class names. Spaces
|
|
|
|
are replaced by underscores.
|
|
|
|
|
2002-08-19 13:59:45 +00:00
|
|
|
=item C<value_quote($val)>
|
|
|
|
|
|
|
|
As well as escaping html like C<html_quote>, this routine converts newlines
|
|
|
|
into 
, suitable for use in html attributes.
|
|
|
|
|
2002-12-15 09:24:08 +00:00
|
|
|
=item C<xml_quote($val)>
|
|
|
|
|
|
|
|
This is similar to C<html_quote>, except that ' is escaped to '. This
|
|
|
|
is kept separate from html_quote partly for compatibility with previous code
|
|
|
|
(for ') and partly for future handling of non-ASCII characters.
|
|
|
|
|
2005-07-20 21:30:58 +00:00
|
|
|
=item C<url_decode($val)>
|
|
|
|
|
|
|
|
Converts the %xx encoding from the given URL back to its original form.
|
|
|
|
|
2005-07-14 06:01:35 +00:00
|
|
|
=item C<i_am_cgi()>
|
|
|
|
|
|
|
|
Tells you whether or not you are being run as a CGI script in a web
|
|
|
|
server. For example, it would return false if the caller is running
|
|
|
|
in a command-line script.
|
|
|
|
|
2002-08-19 13:59:45 +00:00
|
|
|
=back
|
|
|
|
|
|
|
|
=head2 Searching
|
|
|
|
|
|
|
|
Functions for searching within a set of values.
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item C<lsearch($list, $item)>
|
|
|
|
|
|
|
|
Returns the position of C<$item> in C<$list>. C<$list> must be a list
|
|
|
|
reference.
|
|
|
|
|
|
|
|
If the item is not in the list, returns -1.
|
|
|
|
|
|
|
|
=item C<max($a, $b, ...)>
|
|
|
|
|
|
|
|
Returns the maximum from a set of values.
|
|
|
|
|
|
|
|
=item C<min($a, $b, ...)>
|
|
|
|
|
|
|
|
Returns the minimum from a set of values.
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
2005-02-25 02:34:11 +00:00
|
|
|
=head2 Data Manipulation
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item C<diff_arrays(\@old, \@new)>
|
|
|
|
|
|
|
|
Description: Takes two arrayrefs, and will tell you what it takes to
|
|
|
|
get from @old to @new.
|
|
|
|
Params: @old = array that you are changing from
|
|
|
|
@new = array that you are changing to
|
|
|
|
Returns: A list of two arrayrefs. The first is a reference to an
|
|
|
|
array containing items that were removed from @old. The
|
|
|
|
second is a reference to an array containing items
|
|
|
|
that were added to @old. If both returned arrays are
|
|
|
|
empty, @old and @new contain the same values.
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
2005-01-16 13:02:35 +00:00
|
|
|
=head2 String Manipulation
|
2002-08-19 13:59:45 +00:00
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item C<trim($str)>
|
|
|
|
|
|
|
|
Removes any leading or trailing whitespace from a string. This routine does not
|
|
|
|
modify the existing string.
|
|
|
|
|
2005-01-16 13:02:35 +00:00
|
|
|
=item C<diff_strings($oldstr, $newstr)>
|
|
|
|
|
|
|
|
Takes two strings containing a list of comma- or space-separated items
|
|
|
|
and returns what items were removed from or added to the new one,
|
|
|
|
compared to the old one. Returns a list, where the first entry is a scalar
|
|
|
|
containing removed items, and the second entry is a scalar containing added
|
|
|
|
items.
|
|
|
|
|
2005-02-09 17:30:20 +00:00
|
|
|
=item C<wrap_comment($comment)>
|
|
|
|
|
|
|
|
Takes a bug comment, and wraps it to the appropriate length. The length is
|
|
|
|
currently specified in C<Bugzilla::Constants::COMMENT_COLS>. Lines beginning
|
|
|
|
with ">" are assumed to be quotes, and they will not be wrapped.
|
|
|
|
|
|
|
|
The intended use of this function is to wrap comments that are about to be
|
|
|
|
displayed or emailed. Generally, wrapped text should not be stored in the
|
|
|
|
database.
|
|
|
|
|
2005-04-19 17:55:10 +00:00
|
|
|
=item C<find_wrap_point($string, $maxpos)>
|
|
|
|
|
|
|
|
Search for a comma, a whitespace or a hyphen to split $string, within the first
|
|
|
|
$maxpos characters. If none of them is found, just split $string at $maxpos.
|
|
|
|
The search starts at $maxpos and goes back to the beginning of the string.
|
|
|
|
|
2005-08-15 17:58:19 +00:00
|
|
|
=item C<perform_substs($str, $substs)>
|
|
|
|
|
|
|
|
Performs substitutions for sending out email with variables in it,
|
|
|
|
or for inserting a parameter into some other string.
|
|
|
|
|
|
|
|
Takes a string and a reference to a hash containing substitution
|
|
|
|
variables and their values.
|
|
|
|
|
|
|
|
If the hash is not specified, or if we need to substitute something
|
|
|
|
that's not in the hash, then we will use parameters to do the
|
|
|
|
substitution instead.
|
|
|
|
|
|
|
|
Substitutions are always enclosed with '%' symbols. So they look like:
|
|
|
|
%some_variable_name%. If "some_variable_name" is a key in the hash, then
|
|
|
|
its value will be placed into the string. If it's not a key in the hash,
|
|
|
|
then the value of the parameter called "some_variable_name" will be placed
|
|
|
|
into the string.
|
|
|
|
|
2005-08-04 11:51:25 +00:00
|
|
|
=item C<is_7bit_clean($str)>
|
|
|
|
|
|
|
|
Returns true is the string contains only 7-bit characters (ASCII 32 through 126,
|
|
|
|
ASCII 10 (LineFeed) and ASCII 13 (Carrage Return).
|
|
|
|
|
2005-12-29 22:56:01 +00:00
|
|
|
=item C<clean_text($str)>
|
|
|
|
Returns the parameter "cleaned" by exchanging non-printable characters with spaces.
|
|
|
|
Specifically characters (ASCII 0 through 31) and (ASCII 127) will become ASCII 32 (Space).
|
|
|
|
|
2005-04-19 17:55:10 +00:00
|
|
|
=back
|
|
|
|
|
2002-11-27 16:00:44 +00:00
|
|
|
=head2 Formatting Time
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item C<format_time($time)>
|
|
|
|
|
2005-05-10 20:30:13 +00:00
|
|
|
Takes a time, converts it to the desired format and appends the timezone
|
|
|
|
as defined in editparams.cgi, if desired. This routine will be expanded
|
|
|
|
in the future to adjust for user preferences regarding what timezone to
|
|
|
|
display times in.
|
|
|
|
|
|
|
|
This routine is mainly called from templates to filter dates, see
|
|
|
|
"FILTER time" in Templates.pm. In this case, $format is undefined and
|
|
|
|
the routine has to "guess" the date format that was passed to $dbh->sql_date_format().
|
|
|
|
|
2002-11-27 16:00:44 +00:00
|
|
|
|
2005-01-16 13:25:46 +00:00
|
|
|
=item C<format_time_decimal($time)>
|
|
|
|
|
|
|
|
Returns a number with 2 digit precision, unless the last digit is a 0. Then it
|
|
|
|
returns only 1 digit precision.
|
|
|
|
|
2005-07-26 14:09:48 +00:00
|
|
|
=back
|
|
|
|
|
|
|
|
|
2005-01-27 20:08:34 +00:00
|
|
|
=head2 Files
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item C<file_mod_time($filename)>
|
|
|
|
|
2005-01-28 18:56:26 +00:00
|
|
|
Takes a filename and returns the modification time. It returns it in the format
|
|
|
|
of the "mtime" parameter of the perl "stat" function.
|
2005-01-16 13:25:46 +00:00
|
|
|
|
2002-11-27 16:00:44 +00:00
|
|
|
=back
|
|
|
|
|
2005-07-13 03:57:02 +00:00
|
|
|
=head2 Cryptography
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
|
|
|
=item C<bz_crypt($password)>
|
|
|
|
|
|
|
|
Takes a string and returns a C<crypt>ed value for it, using a random salt.
|
|
|
|
|
|
|
|
Please always use this function instead of the built-in perl "crypt"
|
|
|
|
when initially encrypting a password.
|
|
|
|
|
|
|
|
=begin undocumented
|
|
|
|
|
|
|
|
Random salts are generated because the alternative is usually
|
|
|
|
to use the first two characters of the password itself, and since
|
|
|
|
the salt appears in plaintext at the beginning of the encrypted
|
|
|
|
password string this has the effect of revealing the first two
|
|
|
|
characters of the password to anyone who views the encrypted version.
|
|
|
|
|
|
|
|
=end undocumented
|
|
|
|
|
2005-09-01 21:39:21 +00:00
|
|
|
=item C<generate_random_password($password_length)>
|
|
|
|
|
|
|
|
Returns an alphanumeric string with the specified length
|
|
|
|
(10 characters by default). Use this function to generate passwords
|
|
|
|
and tokens.
|
|
|
|
|
2005-07-13 03:57:02 +00:00
|
|
|
=back
|
2005-07-20 21:30:58 +00:00
|
|
|
|
|
|
|
=head2 Validation
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
2005-08-15 17:43:38 +00:00
|
|
|
=item C<validate_email_syntax($email)>
|
|
|
|
|
|
|
|
Do a syntax checking for a legal email address and returns 1 if
|
|
|
|
the check is successful, else returns 0.
|
|
|
|
|
|
|
|
=item C<validate_date($date)>
|
2005-07-20 21:30:58 +00:00
|
|
|
|
2005-08-15 17:43:38 +00:00
|
|
|
Make sure the date has the correct format and returns 1 if
|
|
|
|
the check is successful, else returns 0.
|
2005-07-20 21:30:58 +00:00
|
|
|
|
|
|
|
=back
|