diff options
-rw-r--r-- | Bugzilla.pm | 36 | ||||
-rw-r--r-- | Bugzilla/Auth/Login/CGI.pm | 8 | ||||
-rw-r--r-- | Bugzilla/Auth/Persist/Cookie.pm | 7 | ||||
-rw-r--r-- | Bugzilla/CGI.pm | 33 | ||||
-rw-r--r-- | Bugzilla/Hook.pm | 3 | ||||
-rw-r--r--[-rwxr-xr-x] | Bugzilla/WebService.pm | 40 | ||||
-rw-r--r-- | Bugzilla/WebService/Server.pm | 3 | ||||
-rw-r--r-- | Bugzilla/WebService/Server/JSONRPC.pm | 11 | ||||
-rw-r--r-- | Bugzilla/WebService/Server/XMLRPC.pm | 5 | ||||
-rw-r--r-- | Bugzilla/WebService/User.pm | 10 |
10 files changed, 135 insertions, 21 deletions
diff --git a/Bugzilla.pm b/Bugzilla.pm index a373aa801..666b1ec15 100644 --- a/Bugzilla.pm +++ b/Bugzilla.pm @@ -234,6 +234,22 @@ sub cgi { return $class->request_cache->{cgi}; } +sub input_params { + my ($class, $params) = @_; + my $cache = $class->request_cache; + # This is how the WebService and other places set input_params. + if (defined $params) { + $cache->{input_params} = $params; + } + return $cache->{input_params} if defined $cache->{input_params}; + + # Making this scalar makes it a tied hash to the internals of $cgi, + # so if a variable is changed, then it actually changes the $cgi object + # as well. + $cache->{input_params} = $class->cgi->Vars; + return $cache->{input_params}; +} + sub localconfig { my $class = shift; $class->request_cache->{localconfig} ||= read_localconfig(); @@ -647,6 +663,26 @@ The current C<cgi> object. Note that modules should B<not> be using this in general. Not all Bugzilla actions are cgi requests. Its useful as a convenience method for those scripts/templates which are only use via CGI, though. +=item C<input_params> + +When running under the WebService, this is a hashref containing the arguments +passed to the WebService method that was called. When running in a normal +script, this is a hashref containing the contents of the CGI parameters. + +Modifying this hashref will modify the CGI parameters or the WebService +arguments (depending on what C<input_params> currently represents). + +This should be used instead of L</cgi> in situations where your code +could be being called by either a normal CGI script or a WebService method, +such as during a code hook. + +B<Note:> When C<input_params> represents the CGI parameters, any +parameter specified more than once (like C<foo=bar&foo=baz>) will appear +as an arrayref in the hash, but any value specified only once will appear +as a scalar. This means that even if a value I<can> appear multiple times, +if it only I<does> appear once, then it will be a scalar in C<input_params>, +not an arrayref. + =item C<user> C<undef> if there is no currently logged in user or if the login code has not diff --git a/Bugzilla/Auth/Login/CGI.pm b/Bugzilla/Auth/Login/CGI.pm index a93bc3d3a..407582af4 100644 --- a/Bugzilla/Auth/Login/CGI.pm +++ b/Bugzilla/Auth/Login/CGI.pm @@ -40,12 +40,10 @@ use Bugzilla::Error; sub get_login_info { my ($self) = @_; - my $cgi = Bugzilla->cgi; - - my $username = trim($cgi->param("Bugzilla_login")); - my $password = $cgi->param("Bugzilla_password"); + my $params = Bugzilla->input_params; - $cgi->delete('Bugzilla_login', 'Bugzilla_password'); + my $username = trim(delete $params->{"Bugzilla_login"}); + my $password = delete $params->{"Bugzilla_password"}; if (!defined $username || !defined $password) { return { failure => AUTH_NODATA }; diff --git a/Bugzilla/Auth/Persist/Cookie.pm b/Bugzilla/Auth/Persist/Cookie.pm index 4458e31b5..1e1b3a871 100644 --- a/Bugzilla/Auth/Persist/Cookie.pm +++ b/Bugzilla/Auth/Persist/Cookie.pm @@ -48,9 +48,10 @@ sub persist_login { my ($self, $user) = @_; my $dbh = Bugzilla->dbh; my $cgi = Bugzilla->cgi; + my $input_params = Bugzilla->input_params; my $ip_addr; - if ($cgi->param('Bugzilla_restrictlogin')) { + if ($input_params->{'Bugzilla_restrictlogin'}) { $ip_addr = $cgi->remote_addr; # The IP address is valid, at least for comparing with itself in a # subsequent login @@ -80,8 +81,8 @@ sub persist_login { # or admin didn't forbid it and user told to remember. if ( Bugzilla->params->{'rememberlogin'} eq 'on' || (Bugzilla->params->{'rememberlogin'} ne 'off' && - $cgi->param('Bugzilla_remember') && - $cgi->param('Bugzilla_remember') eq 'on') ) + $input_params->{'Bugzilla_remember'} && + $input_params->{'Bugzilla_remember'} eq 'on') ) { # Not a session cookie, so set an infinite expiry $cookieargs{'-expires'} = 'Fri, 01-Jan-2038 00:00:00 GMT'; diff --git a/Bugzilla/CGI.pm b/Bugzilla/CGI.pm index 8c68f996c..bebff2d63 100644 --- a/Bugzilla/CGI.pm +++ b/Bugzilla/CGI.pm @@ -416,6 +416,39 @@ sub url_is_attachment_base { return ($self->self_url =~ $regex) ? 1 : 0; } +########################## +# Vars TIEHASH Interface # +########################## + +# Fix the TIEHASH interface (scalar $cgi->Vars) to return and accept +# arrayrefs. +sub STORE { + my $self = shift; + my ($param, $value) = @_; + if (defined $value and ref $value eq 'ARRAY') { + return $self->param(-name => $param, -value => $value); + } + return $self->SUPER::STORE(@_); +} + +sub FETCH { + my ($self, $param) = @_; + return $self if $param eq 'CGI'; # CGI.pm did this, so we do too. + my @result = $self->param($param); + return undef if !scalar(@result); + return $result[0] if scalar(@result) == 1; + return \@result; +} + +# For the Vars TIEHASH interface: the normal CGI.pm DELETE doesn't return +# the value deleted, but Perl's "delete" expects that value. +sub DELETE { + my ($self, $param) = @_; + my $value = $self->FETCH($param); + $self->delete($param); + return $value; +} + 1; __END__ diff --git a/Bugzilla/Hook.pm b/Bugzilla/Hook.pm index 51bce7fbe..69fa2f654 100644 --- a/Bugzilla/Hook.pm +++ b/Bugzilla/Hook.pm @@ -144,6 +144,9 @@ These params are accessible through L<Bugzilla/hook_args>. That returns a hashref. Very frequently, if you want your hook to do anything, you have to modify these variables. +You may also want to use L<Bugzilla/input_params> to get parameters +that were passed to the current CGI script or WebService method. + =head2 Versioning Extensions Every extension must have a file in its root called F<info.pl>. diff --git a/Bugzilla/WebService.pm b/Bugzilla/WebService.pm index 75fcf6bc9..222923e70 100755..100644 --- a/Bugzilla/WebService.pm +++ b/Bugzilla/WebService.pm @@ -142,11 +142,51 @@ how this is implemented for those frontends. =head1 LOGGING IN +There are various ways to log in: + +=over + +=item C<User.login> + You can use L<Bugzilla::WebService::User/login> to log in as a Bugzilla user. This issues standard HTTP cookies that you must then use in future calls, so your client must be capable of receiving and transmitting cookies. +=item C<Bugzilla_login> and C<Bugzilla_password> + +B<Added in Bugzilla 3.6> + +You can specify C<Bugzilla_login> and C<Bugzilla_password> as arguments +to any WebService method, and you will be logged in as that user if your +credentials are correct. Here are the arguments you can specify to any +WebService method to perform a login: + +=over + +=item C<Bugzilla_login> (string) - A user's login name. + +=item C<Bugzilla_password> (string) - That user's password. + +=item C<Bugzilla_restrictlogin> (boolean) - Optional. If true, +then your login will only be valid for your IP address. + +=item C<Bugzilla_rememberlogin> (boolean) - Optional. If true, +then the cookie sent back to you with the method response will +not expire. + +=back + +The C<Bugzilla_restrictlogin> and C<Bugzilla_rememberlogin> options +are only used when you have also specified C<Bugzilla_login> and +C<Bugzilla_password>. + +Note that Bugzilla will return HTTP cookies along with the method +response when you use these arguments (just like the C<User.login> method +above). + +=back + =head1 STABLE, EXPERIMENTAL, and UNSTABLE Methods are marked B<STABLE> if you can expect their parameters and diff --git a/Bugzilla/WebService/Server.pm b/Bugzilla/WebService/Server.pm index 2db182fd4..115c7df89 100644 --- a/Bugzilla/WebService/Server.pm +++ b/Bugzilla/WebService/Server.pm @@ -21,7 +21,8 @@ use strict; sub handle_login { my ($self, $class, $method, $full_method) = @_; eval "require $class"; - return if $class->login_exempt($method); + return if ($class->login_exempt($method) + and !defined Bugzilla->input_params->{Bugzilla_login}); Bugzilla->login(); } diff --git a/Bugzilla/WebService/Server/JSONRPC.pm b/Bugzilla/WebService/Server/JSONRPC.pm index e54387a6d..919370a2a 100644 --- a/Bugzilla/WebService/Server/JSONRPC.pm +++ b/Bugzilla/WebService/Server/JSONRPC.pm @@ -112,12 +112,6 @@ sub _argument_type_check { my $self = shift; my $params = $self->SUPER::_argument_type_check(@_); - # This is the best time to do login checks. - $self->handle_login(); - - # If there are no parameters, we don't need to parse them. - return $params if !ref $params; - # JSON-RPC 1.0 requires all parameters to be passed as an array, so # we just pull out the first item and assume it's an object. if (ref $params eq 'ARRAY') { @@ -144,6 +138,11 @@ sub _argument_type_check { } } + Bugzilla->input_params($params); + + # This is the best time to do login checks. + $self->handle_login(); + # Bugzilla::WebService packages call internal methods like # $self->_some_private_method. So we have to inherit from # that class as well as this Server class. diff --git a/Bugzilla/WebService/Server/XMLRPC.pm b/Bugzilla/WebService/Server/XMLRPC.pm index b2a50712a..cbfb1b7f2 100644 --- a/Bugzilla/WebService/Server/XMLRPC.pm +++ b/Bugzilla/WebService/Server/XMLRPC.pm @@ -78,6 +78,7 @@ sub deserialize { $som->{_bz_do_taint} = 1; } bless $som, 'Bugzilla::XMLRPC::SOM'; + Bugzilla->input_params($som->paramsin); return $som; } @@ -146,11 +147,13 @@ use Bugzilla::WebService::Util qw(taint_data); sub paramsin { my $self = shift; + return $self->{bz_params_in} if $self->{bz_params_in}; my $params = $self->SUPER::paramsin(@_); if ($self->{_bz_do_taint}) { taint_data($params); } - return $params; + $self->{bz_params_in} = $params; + return $self->{bz_params_in}; } 1; diff --git a/Bugzilla/WebService/User.pm b/Bugzilla/WebService/User.pm index ba899cd4d..67a4720de 100644 --- a/Bugzilla/WebService/User.pm +++ b/Bugzilla/WebService/User.pm @@ -61,12 +61,12 @@ sub login { } # Make sure the CGI user info class works if necessary. - my $cgi = Bugzilla->cgi; - $cgi->param('Bugzilla_login', $params->{login}); - $cgi->param('Bugzilla_password', $params->{password}); - $cgi->param('Bugzilla_remember', $remember); + my $input_params = Bugzilla->input_params; + $input_params->{'Bugzilla_login'} = $params->{login}; + $input_params->{'Bugzilla_password'} = $params->{password}; + $input_params->{'Bugzilla_remember'} = $remember; - Bugzilla->login; + Bugzilla->login(); return { id => $self->type('int', Bugzilla->user->id) }; } |