Commit acfa0af7 authored by Per Cederqvist's avatar Per Cederqvist
Browse files

Imported Bugzilla 2.17.7.

parent 0a5b086c
......@@ -77,7 +77,8 @@ sub query
# of hashes in which each hash represents a single attachment.
&::SendSQL("
SELECT attach_id, DATE_FORMAT(creation_ts, '%Y.%m.%d %H:%i'),
mimetype, description, ispatch, isobsolete, isprivate, submitter_id
mimetype, description, ispatch, isobsolete, isprivate,
submitter_id, LENGTH(thedata)
FROM attachments WHERE bug_id = $bugid ORDER BY attach_id
");
my @attachments = ();
......@@ -85,8 +86,8 @@ sub query
my %a;
my $submitter_id;
($a{'attachid'}, $a{'date'}, $a{'contenttype'}, $a{'description'},
$a{'ispatch'}, $a{'isobsolete'}, $a{'isprivate'}, $submitter_id)
= &::FetchSQLData();
$a{'ispatch'}, $a{'isobsolete'}, $a{'isprivate'}, $submitter_id,
$a{'datasize'}) = &::FetchSQLData();
# Retrieve a list of flags for this attachment.
$a{'flags'} = Bugzilla::Flag::match({ 'attach_id' => $a{'attachid'} });
......
......@@ -99,8 +99,17 @@ sub login {
}
sub logout {
use Bugzilla::Auth::CGI;
# remove cookies and clean up database state
Bugzilla::Auth::CGI->logout();
logout_request();
}
sub logout_request {
undef $_user;
$::userid = 0;
delete $::COOKIE{"Bugzilla_login"};
delete $::COOKIE{"Bugzilla_logincookie"};
}
my $_dbh;
......@@ -266,10 +275,13 @@ L<Bugzilla::User|Bugzilla::User>.
=item C<logout>
Logs out the current user. For the moment, this will just cause calls to
C<user> to return C<undef>. Eventually this will handle deleting cookies from
the browser and values from the database, which is currently all handled
by C<relogin.cgi>.
Logs out the current user.
=item C<logout_request>
Essentially, causes calls to C<user> to return C<undef>. This has the
effect of logging out a user for the current request only; cookies and
database state are left intact.
=item C<dbh>
......
......@@ -72,17 +72,32 @@ sub login {
$userid, $ipaddr);
my $logincookie = $dbh->selectrow_array("SELECT LAST_INSERT_ID()");
$cgi->send_cookie(-name => 'Bugzilla_login',
-value => $userid,
-expires => 'Fri, 01-Jan-2038 00:00:00 GMT');
$cgi->send_cookie(-name => 'Bugzilla_logincookie',
-value => $logincookie,
-expires => 'Fri, 01-Jan-2038 00:00:00 GMT');
# Remember cookie only if admin has told so
# or admin didn't forbid it and user told to remember.
if ((Param('rememberlogin') eq 'on') ||
((Param('rememberlogin') ne 'off') &&
($cgi->param('Bugzilla_remember') eq 'on'))) {
$cgi->send_cookie(-name => 'Bugzilla_login',
-value => $userid,
-expires => 'Fri, 01-Jan-2038 00:00:00 GMT');
$cgi->send_cookie(-name => 'Bugzilla_logincookie',
-value => $logincookie,
-expires => 'Fri, 01-Jan-2038 00:00:00 GMT');
}
else {
$cgi->send_cookie(-name => 'Bugzilla_login',
-value => $userid);
$cgi->send_cookie(-name => 'Bugzilla_logincookie',
-value => $logincookie);
}
# compat code. The cookie value is used for logouts, and that
# isn't generic yet.
$::COOKIE{'Bugzilla_logincookie'} = $logincookie;
} elsif ($authres == AUTH_NODATA) {
}
elsif ($authres == AUTH_NODATA) {
# No data from the form, so try to login via cookies
$username = $cgi->cookie("Bugzilla_login");
$passwd = $cgi->cookie("Bugzilla_logincookie");
......@@ -177,6 +192,28 @@ sub login {
}
sub logout {
my ($class, $user) = @_;
if ($user) {
# Even though we know the userid must match, we still check it in the
# SQL as a sanity check, since there is no locking here, and if
# the user logged out from two machines simulataniously, while someone
# else logged in and got the same cookie, we could be logging the
# other user out here. Yes, this is very very very unlikely, but why
# take chances? - bbaetz
my $dbh = Bugzilla->dbh;
$dbh->do("DELETE FROM logincookies WHERE cookie = ? AND userid = ?",
undef, $::COOKIE{"Bugzilla_logincookie"}, $user->id);
}
my $cgi = Bugzilla->cgi;
$cgi->send_cookie(-name => "Bugzilla_login",
-expires => "Tue, 15-Sep-1998 21:49:00 GMT");
$cgi->send_cookie(-name => "Bugzilla_logincookie",
-expires => "Tue, 15-Sep-1998 21:49:00 GMT");
}
1;
__END__
......@@ -188,7 +225,7 @@ Bugzilla::Auth::CGI - CGI-based logins for Bugzilla
=head1 SUMMARY
This is a L<login module|Bugzilla::Auth/"LOGIN"> for Bugzilla. Users connecting
from a CGI script use this module to authenticate.
from a CGI script use this module to authenticate. Logouts are also handled here.
=head1 BEHAVIOUR
......@@ -198,6 +235,9 @@ using the CGI parameters I<Bugzilla_login> and I<Bugzilla_password>.
If no data is present for that, then cookies are tried, using
L<Bugzilla::Auth::Cookie>.
When a logout is performed, we take care of removing the relevant
logincookie database entry and effectively deleting the client cookie.
=head1 SEE ALSO
L<Bugzilla::Auth>
/CGI.pm/1.4/Sun Sep 14 06:05:21 2003//TBUGZILLA-2_17_6
/Cookie.pm/1.1/Sat Mar 22 04:47:18 2003//TBUGZILLA-2_17_6
/DB.pm/1.3/Sun Oct 26 05:43:29 2003//TBUGZILLA-2_17_6
/LDAP.pm/1.4/Mon Jul 14 13:35:12 2003//TBUGZILLA-2_17_6
/CGI.pm/1.6/Fri Jan 16 22:46:31 2004//TBUGZILLA-2_17_7
/Cookie.pm/1.1/Sat Mar 22 04:47:18 2003//TBUGZILLA-2_17_7
/DB.pm/1.4/Sun Dec 7 02:11:00 2003//TBUGZILLA-2_17_7
/LDAP.pm/1.4/Mon Jul 14 13:35:12 2003//TBUGZILLA-2_17_7
D
NBUGZILLA-2_17_6
NBUGZILLA-2_17_7
......@@ -39,50 +39,72 @@ sub authenticate {
return (AUTH_NODATA) unless defined $username && defined $passwd;
my $dbh = Bugzilla->dbh;
# We're just testing against the db, so any value is ok
# We're just testing against the db: any value is ok
trick_taint($username);
# Retrieve the user's ID and crypted password from the database.
my $sth = $dbh->prepare_cached("SELECT userid,cryptpassword,disabledtext " .
"FROM profiles " .
"WHERE login_name=?");
my ($userid, $realcryptpwd, $disabledtext) =
$dbh->selectrow_array($sth,
undef,
$username);
# If the user doesn't exist, return now
my $userid = $class->get_id_from_username($username);
return (AUTH_LOGINFAILED) unless defined $userid;
# OK, now authenticate the user
# Get the salt from the user's crypted password.
my $salt = $realcryptpwd;
# Using the salt, crypt the password the user entered.
my $enteredCryptedPassword = crypt($passwd, $salt);
return (AUTH_LOGINFAILED, $userid)
unless $class->check_password($userid, $passwd);
# Make sure the passwords match or return an error
return (AUTH_LOGINFAILED, $userid) unless
($enteredCryptedPassword eq $realcryptpwd);
# Now we know that the user has logged in successfully,
# so delete any password tokens for them
# The user's credentials are okay, so delete any outstanding
# password tokens they may have generated.
require Token;
Token::DeletePasswordTokens($userid, "user_logged_in");
# The user may have had their account disabled
# Account may have been disabled
my $disabledtext = $class->get_disabled($userid);
return (AUTH_DISABLED, $userid, $disabledtext)
if $disabledtext ne '';
# If we get to here, then the user is allowed to login, so we're done!
return (AUTH_OK, $userid);
}
sub can_edit { return 1; }
sub get_id_from_username {
my ($class, $username) = @_;
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare_cached("SELECT userid FROM profiles " .
"WHERE login_name=?");
my ($userid) = $dbh->selectrow_array($sth, undef, $username);
return $userid;
}
sub get_disabled {
my ($class, $userid) = @_;
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare_cached("SELECT disabledtext FROM profiles " .
"WHERE userid=?");
my ($text) = $dbh->selectrow_array($sth, undef, $userid);
return $text;
}
sub check_password {
my ($class, $userid, $passwd) = @_;
my $dbh = Bugzilla->dbh;
my $sth = $dbh->prepare_cached("SELECT cryptpassword FROM profiles " .
"WHERE userid=?");
my ($realcryptpwd) = $dbh->selectrow_array($sth, undef, $userid);
# Get the salt from the user's crypted password.
my $salt = $realcryptpwd;
# Using the salt, crypt the password the user entered.
my $enteredCryptedPassword = crypt($passwd, $salt);
return $enteredCryptedPassword eq $realcryptpwd;
}
sub change_password {
my ($class, $userid, $password) = @_;
my $dbh = Bugzilla->dbh;
my $cryptpassword = Crypt($password);
$dbh->do("UPDATE profiles SET cryptpassword = ? WHERE userid = ?",
undef, $cryptpassword, $userid);
}
1;
__END__
......
......@@ -32,6 +32,9 @@ package Bugzilla::BugMail;
use RelationSet;
use Bugzilla::Config qw(:DEFAULT $datadir);
use Bugzilla::Util;
# This code is really ugly. It was a commandline interface, then it was moved
# There are package-global variables which we rely on ProcessOneBug to clean
# up each time, and other sorts of fun.
......@@ -66,7 +69,7 @@ sub AUTOLOAD {
}
# This is run when we load the package
if (open(NOMAIL, "<data/nomail")) {
if (open(NOMAIL, '<', "$datadir/nomail")) {
while (<NOMAIL>) {
$nomail{trim($_)} = 1;
}
......
......@@ -23,7 +23,8 @@ use strict;
package Bugzilla::CGI;
use CGI qw(-no_xhtml -oldstyle_urls :private_tempfiles :unique_headers);
use CGI qw(-no_xhtml -oldstyle_urls :private_tempfiles :unique_headers SERVER_PUSH);
use CGI::Util qw(rearrange);
use base qw(CGI);
......@@ -45,6 +46,9 @@ sub new {
my $self = $class->SUPER::new(@args);
# Make sure our outgoing cookie list is empty on each invocation
$self->{Bugzilla_cookie_list} = [];
# Make sure that we don't send any charset headers
$self->charset('');
......@@ -107,22 +111,65 @@ sub canonicalise_query {
return join("&", @parameters);
}
# CGI.pm makes this nph, but apache doesn't like that
# Overwrite to handle nph parameter. This should stay here until perl 5.8.1 CGI
# has been fixed to support -nph as a parameter
#
sub multipart_init {
my($self,@p) = @_;
my($boundary,$nph,@other) = rearrange(['BOUNDARY','NPH'],@p);
$boundary = $boundary || '------- =_aaaaaaaaaa0';
$self->{'separator'} = "\r\n--$boundary$\r\n";
$self->{'final_separator'} = "\r\n--$boundary--\r\n";
my $type = SERVER_PUSH($boundary);
return $self->header(
-nph => 0,
-type => $type,
(map { split "=", $_, 2 } @other),
) . "WARNING: YOUR BROWSER DOESN'T SUPPORT THIS SERVER-PUSH TECHNOLOGY." . $self->multipart_end;
}
# Override header so we can add the cookies in
sub header {
my $self = shift;
unshift(@_, '-nph' => undef);
# Add the cookies in if we have any
if (scalar(@{$self->{Bugzilla_cookie_list}})) {
if (scalar(@_) == 1) {
# if there's only one parameter, then it's a Content-Type.
# Since we're adding parameters we have to name it.
unshift(@_, '-type' => shift(@_));
}
unshift(@_, '-cookie' => $self->{Bugzilla_cookie_list});
}
return $self->SUPER::header(@_);
}
# We override the entirety of multipart_start instead of falling through to
# SUPER because the built-in one can't deal with cookies in any kind of sane
# way. This sub is gratuitously swiped from the real CGI.pm, but fixed so
# it actually works (but only as much as we need it to).
sub multipart_start {
my(@header);
my($self,@p) = @_;
my($type,@other) = rearrange([['TYPE','CONTENT_TYPE','CONTENT-TYPE']],@p);
$type = $type || 'text/html';
push(@header,"Content-Type: $type");
# Add the cookies in if we have any
if (scalar(@{$self->{Bugzilla_cookie_list}})) {
foreach my $cookie (@{$self->{Bugzilla_cookie_list}}) {
push @header, "Set-Cookie: $cookie";
}
}
return $self->SUPER::multipart_init(@_);
my $header = join($CGI::CRLF,@header)."${CGI::CRLF}${CGI::CRLF}";
return $header;
}
# The various parts of Bugzilla which create cookies don't want to have to
# pass them arround to all of the callers. Instead, store them locally here,
# and then output as required from |headers|.
# This is done instead of just printing the result from the script, because
# we need to use |$r->header_out| under mod_perl (which is what CGI.pm
# does, and we need to match, plus if we don't |print| anything, we can turn
# off mod_perl/Apache's header parsing for a small perf gain)
# and then output as required from |header|.
sub send_cookie {
my $self = shift;
......@@ -134,9 +181,7 @@ sub send_cookie {
# we're expiring an entry.
require CGI::Cookie;
my $cookie = CGI::Cookie->new(@_);
# XXX - mod_perl
print "Set-Cookie: $cookie\r\n";
push @{$self->{Bugzilla_cookie_list}}, $cookie;
return;
}
......
/.cvsignore/1.1/Mon Aug 26 22:24:55 2002//TBUGZILLA-2_17_6
/Auth.pm/1.2/Sat Oct 18 22:46:22 2003//TBUGZILLA-2_17_6
/BugMail.pm/1.7/Thu Aug 14 17:49:08 2003//TBUGZILLA-2_17_6
/CGI.pm/1.6/Fri May 9 02:32:21 2003//TBUGZILLA-2_17_6
/Chart.pm/1.2/Sat Nov 8 00:27:43 2003//TBUGZILLA-2_17_6
/Config.pm/1.17/Mon Nov 10 03:56:38 2003//TBUGZILLA-2_17_6
/Constants.pm/1.3/Mon May 5 01:15:34 2003//TBUGZILLA-2_17_6
/DB.pm/1.8/Sat Mar 22 04:47:15 2003//TBUGZILLA-2_17_6
/Error.pm/1.4/Sun Sep 14 06:05:10 2003//TBUGZILLA-2_17_6
/Flag.pm/1.14/Sat Oct 25 01:34:33 2003//TBUGZILLA-2_17_6
/FlagType.pm/1.4/Sun Sep 14 06:05:10 2003//TBUGZILLA-2_17_6
/Search.pm/1.47/Sun Nov 2 15:22:42 2003//TBUGZILLA-2_17_6
/Series.pm/1.2/Sat Nov 8 00:25:21 2003//TBUGZILLA-2_17_6
/Template.pm/1.12/Wed Sep 17 22:12:56 2003//TBUGZILLA-2_17_6
/User.pm/1.16/Sun Sep 14 06:05:10 2003//TBUGZILLA-2_17_6
/Util.pm/1.11/Fri Aug 22 13:55:16 2003//TBUGZILLA-2_17_6
/.cvsignore/1.1/Mon Aug 26 22:24:55 2002//TBUGZILLA-2_17_7
/Auth.pm/1.2/Sat Oct 18 22:46:22 2003//TBUGZILLA-2_17_7
/BugMail.pm/1.9/Mon Jan 26 07:04:22 2004//TBUGZILLA-2_17_7
/CGI.pm/1.9/Wed Feb 25 14:06:33 2004//TBUGZILLA-2_17_7
/Chart.pm/1.3/Thu Jan 22 00:02:27 2004//TBUGZILLA-2_17_7
/Config.pm/1.20/Wed Mar 3 07:35:43 2004//TBUGZILLA-2_17_7
/Constants.pm/1.7/Sun Feb 29 16:18:58 2004//TBUGZILLA-2_17_7
/DB.pm/1.9/Sat Nov 22 03:50:40 2003//TBUGZILLA-2_17_7
/Error.pm/1.4/Sun Sep 14 06:05:10 2003//TBUGZILLA-2_17_7
/Flag.pm/1.15/Sat Jan 31 00:49:56 2004//TBUGZILLA-2_17_7
/FlagType.pm/1.6/Sat Jan 31 00:49:56 2004//TBUGZILLA-2_17_7
/Search.pm/1.52/Fri Feb 13 01:45:21 2004//TBUGZILLA-2_17_7
/Series.pm/1.4/Thu Feb 12 22:33:06 2004//TBUGZILLA-2_17_7
/Template.pm/1.15/Thu Feb 5 18:14:03 2004//TBUGZILLA-2_17_7
/User.pm/1.17/Sat Nov 22 03:32:51 2003//TBUGZILLA-2_17_7
/Util.pm/1.12/Sat Nov 22 03:50:40 2003//TBUGZILLA-2_17_7
D/Auth////
D/Template////
NBUGZILLA-2_17_6
NBUGZILLA-2_17_7
......@@ -89,6 +89,9 @@ sub init {
$self->{'datefrom'} = $cgi->param('datefrom');
$self->{'dateto'} = $cgi->param('dateto');
# If we are cumulating, a grand total makes no sense
$self->{'gt'} = 0 if $self->{'cumulate'};
# Make sure the dates are ones we are able to interpret
foreach my $date ('datefrom', 'dateto') {
if ($self->{$date}) {
......
......@@ -34,6 +34,29 @@ use base qw(Exporter);
use Bugzilla::Util;
# Under mod_perl, get this from a .htaccess config variable,
# and/or default from the current 'real' dir
# At some stage after this, it may be possible for these dir locations
# to go into localconfig. localconfig can't be specified in a config file,
# except possibly with mod_perl. If you move localconfig, you need to change
# the define here.
# $libpath is really only for mod_perl; its not yet possible to move the
# .pms elsewhere.
# $webdotdir must be in the webtree somewhere. Even if you use a local dot,
# we output images to there. Also, if $webdot dir is not relative to the
# bugzilla root directory, you'll need to change showdependancygraph.cgi to
# set image_url to the correct location.
# The script should really generate these graphs directly...
# Note that if $libpath is changed, some stuff will break, notably dependancy
# graphs (since the path will be wrong in the HTML). This will be fixed at
# some point.
our $libpath = '.';
our $localconfig = "$libpath/localconfig";
our $datadir = "$libpath/data";
our $templatedir = "$libpath/template";
our $webdotdir = "$datadir/webdot";
# Module stuff
@Bugzilla::Config::EXPORT = qw(Param);
......@@ -42,16 +65,18 @@ use Bugzilla::Util;
# when it shouldn't
# ChmodDataFile is here until that stuff all moves out of globals.pl
# into this file
@Bugzilla::Config::EXPORT_OK = qw($contenttypes ChmodDataFile);
@Bugzilla::Config::EXPORT_OK = qw(ChmodDataFile);
%Bugzilla::Config::EXPORT_TAGS =
(
admin => [qw(GetParamList UpdateParams SetParam WriteParams)],
db => [qw($db_host $db_port $db_name $db_user $db_pass $db_sock)],
locations => [qw($libpath $localconfig $datadir $templatedir $webdotdir)],
);
Exporter::export_ok_tags('admin', 'db');
Exporter::export_ok_tags('admin', 'db', 'locations');
# Bugzilla version
$Bugzilla::Config::VERSION = "2.17.6";
$Bugzilla::Config::VERSION = "2.17.7";
use Safe;
......@@ -74,23 +99,24 @@ my %param;
# XXX - mod_perl - need to register Apache init handler for params
sub _load_datafiles {
# read in localconfig variables
do 'localconfig';
do $localconfig;
if (-e 'data/params') {
if (-e "$datadir/params") {
# Handle reading old param files by munging the symbol table
# Don't have to do this if we use safe mode, since its evaled
# in a sandbox where $foo is in the same module as $::foo
#local *::param = \%param;
# Note that checksetup.pl sets file permissions on 'data/params'
# Note that checksetup.pl sets file permissions on '$datadir/params'
# Using Safe mode is _not_ a guarantee of safety if someone does
# manage to write to the file. However, it won't hurt...
# See bug 165144 for not needing to eval this at all
my $s = new Safe;
$s->rdo('data/params');
die "Error evaluating data/params: $@" if $@;
$s->rdo("$datadir/params");
die "Error reading $datadir/params: $!" if $!;
die "Error evaluating $datadir/params: $@" if $@;
# Now read the param back out from the sandbox
%param = %{$s->varglob('param')};
......@@ -132,7 +158,7 @@ sub Param {
return $param{$param} if exists $param{$param};
# Else error out
die "No value for param $param";
die "No value for param $param (try running checksetup.pl again)";
}
sub GetParamList {
......@@ -226,17 +252,17 @@ sub WriteParams {
require File::Temp;
my ($fh, $tmpname) = File::Temp::tempfile('params.XXXXX',
DIR => 'data' );
DIR => $datadir );
print $fh (Data::Dumper->Dump([ \%param ], [ '*param' ]))
|| die "Can't write param file: $!";
close $fh;
rename $tmpname, "data/params"
|| die "Can't rename $tmpname to data/params: $!";
rename $tmpname, "$datadir/params"
|| die "Can't rename $tmpname to $datadir/params: $!";
ChmodDataFile('data/params', 0666);
ChmodDataFile("$datadir/params", 0666);
}
# Some files in the data directory must be world readable iff we don't have
......@@ -248,7 +274,7 @@ sub WriteParams {
sub ChmodDataFile {
my ($file, $mask) = @_;
my $perm = 0770;
if ((stat('data'))[2] & 0002) {
if ((stat($datadir))[2] & 0002) {
$perm = 0777;
}
$perm = $perm & $mask;
......@@ -321,10 +347,6 @@ Bugzilla::Config - Configuration parameters for Bugzilla
use Bugzilla::Config qw(:db);
print "Connecting to $db_name as $db_user with $db_pass\n";
# This variable does not belong in localconfig, and needs to go
# somewhere better
use Bugzilla::Config($contenttypes)
=head1 DESCRIPTION
This package contains ways to access Bugzilla configuration parameters.
......
......@@ -135,9 +135,9 @@ sub connect_shadow {
}
sub connect_main {
my $dsn = "DBI:mysql:host=$::db_host;database=$::db_name;port=$::db_port";
my $dsn = "DBI:mysql:host=$db_host;database=$db_name;port=$db_port";
$dsn .= ";mysql_socket=$::db_sock" if $::db_sock;
$dsn .= ";mysql_socket=$db_sock" if $db_sock;
return _connect($dsn);
}
......
......@@ -244,12 +244,12 @@ sub process {
# no longer valid.
&::SendSQL("
SELECT flags.id
FROM flags, bugs LEFT OUTER JOIN flaginclusions i
ON (flags.type_id = i.type_id
FROM (flags INNER JOIN bugs ON flags.bug_id = bugs.bug_id)
LEFT OUTER JOIN flaginclusions i
ON (flags.type_id = i.type_id
AND (bugs.product_id = i.product_id OR i.product_id IS NULL)
AND (bugs.component_id = i.component_id OR i.component_id IS NULL))
WHERE flags.type_id = $target->{'bug'}->{'id'}
AND flags.bug_id = bugs.bug_id
AND i.type_id IS NULL
");
clear(&::FetchOneColumn()) while &::MoreSQLData();
......
......@@ -34,6 +34,7 @@ use Bugzilla::User;
use Bugzilla::Error;
use Bugzilla::Util;
use Bugzilla::Config;
# Note! This module requires that its caller have said "require CGI.pl"
# to import relevant functions from that script and its companion globals.pl.
......@@ -263,12 +264,12 @@ sub normalize {
# Check for flags whose product/component is no longer included.