Index: buglist.cgi =================================================================== --- buglist.cgi (wersja 600) +++ buglist.cgi (kopia robocza) @@ -301,9 +301,10 @@ my $dbh = Bugzilla->dbh; $query_name = trim($query_name); - my ($query_obj) = grep {$_->name eq $query_name} @{Bugzilla->user->queries}; + my ($query_obj) = grep {lc($_->name) eq lc($query_name)} @{Bugzilla->user->queries}; if ($query_obj) { + $query_obj->set_name($query_name); $query_obj->set_url($query); $query_obj->set_query_type($query_type); $query_obj->update(); @@ -665,6 +666,8 @@ DefineColumn($field->name, 'bugs.' . $field->name, $field->description); } +Bugzilla::Hook::process("buglist-columns", {'columns' => $columns} ); + ################################################################################ # Display Column Determination ################################################################################ Index: Bugzilla/Constants.pm =================================================================== --- Bugzilla/Constants.pm (wersja 600) +++ Bugzilla/Constants.pm (kopia robocza) @@ -147,7 +147,7 @@ # CONSTANTS # # Bugzilla version -use constant BUGZILLA_VERSION => "3.0.4"; +use constant BUGZILLA_VERSION => "3.0.5"; # # ControlMap constants for group_control_map. Index: Bugzilla/DB/Mysql.pm =================================================================== --- Bugzilla/DB/Mysql.pm (wersja 600) +++ Bugzilla/DB/Mysql.pm (kopia robocza) @@ -133,7 +133,7 @@ # Add the boolean mode modifier if the search string contains # boolean operators. - my $mode = ($text =~ /[+-<>()~*"]/ ? "IN BOOLEAN MODE" : ""); + my $mode = ($text =~ /[+\-<>()~*"]/ ? "IN BOOLEAN MODE" : ""); # quote the text for use in the MATCH AGAINST expression $text = $self->quote($text); Index: Bugzilla/Hook.pm =================================================================== --- Bugzilla/Hook.pm (wersja 600) +++ Bugzilla/Hook.pm (kopia robocza) @@ -59,7 +59,7 @@ =head1 NAME -Bugzilla::Hook - Extendible extension hooks for Bugzilla code +Bugzilla::Hook - Extendable extension hooks for Bugzilla code =head1 SYNOPSIS @@ -127,8 +127,38 @@ =head1 HOOKS -This describes what hooks exist in Bugzilla currently. +This describes what hooks exist in Bugzilla currently. They are mostly +in alphabetical order, but some related hooks are near each other instead +of being alphabetical. +=head2 buglist-columns + +This happens in buglist.cgi after the standard columns have been defined and +right before the display column determination. It gives you the opportunity +to add additional display columns. + +Params: + +=over + +=item C - A hashref, where the keys are unique string identifiers +for the column being defined and the values are hashrefs with the +following fields: + +=over + +=item C - The name of the column in the database. + +=item C - The title of the column as displayed to users. + +=back + +The definition is structured as: + +$columns->{$id} = { name => $name, title => $title }; + +=back + =head2 enter_bug-entrydefaultvars This happens right before the template is loaded on enter_bug.cgi. @@ -190,3 +220,36 @@ database when run. =back + +=head2 webservice + +This hook allows you to add your own modules to the WebService. (See +L<Bugzilla::WebService>.) + +Params: + +=over + +=item C<dispatch> + +A hashref that you can specify the names of your modules and what Perl +module handles the functions for that module. (This is actually sent to +L<SOAP::Lite/dispatch_with>. You can see how that's used in F<xmlrpc.cgi>.) + +The Perl module name must start with C<extensions::yourextension::lib::> +(replace C<yourextension> with the name of your extension). The C<package> +declaration inside that module must also start with +C<extensions::yourextension::lib::> in that module's code. + +Example: + + $dispatch->{Example} = "extensions::example::lib::Example"; + +And then you'd have a module F<extensions/example/lib/Example.pm> + +It's recommended that all the keys you put in C<dispatch> start with the +name of your extension, so that you don't conflict with the standard Bugzilla +WebService functions (and so that you also don't conflict with other +plugins). + +=back \ No newline at end of file Index: Bugzilla/Install/Filesystem.pm =================================================================== --- Bugzilla/Install/Filesystem.pm (wersja 600) +++ Bugzilla/Install/Filesystem.pm (kopia robocza) @@ -153,6 +153,8 @@ dirs => $ws_dir_readable }, $templatedir => { files => $ws_readable, dirs => $ws_dir_readable }, + $extensionsdir => { files => $ws_readable, + dirs => $ws_dir_readable }, images => { files => $ws_readable, dirs => $ws_dir_readable }, css => { files => $ws_readable, Index: Bugzilla/Install/Requirements.pm =================================================================== --- Bugzilla/Install/Requirements.pm (wersja 600) +++ Bugzilla/Install/Requirements.pm (kopia robocza) @@ -91,10 +91,14 @@ version => ON_WINDOWS ? '2.16' : '2.00' }, { - # This will pull in Email::MIME for us, also. + package => 'Email-MIME', + module => 'Email::MIME', + version => '1.861' + }, + { package => 'Email-MIME-Modifier', module => 'Email::MIME::Modifier', - version => 0 + version => '1.442' }, ); Index: Bugzilla/Search/Saved.pm =================================================================== --- Bugzilla/Search/Saved.pm (wersja 600) +++ Bugzilla/Search/Saved.pm (kopia robocza) @@ -55,7 +55,7 @@ link_in_footer => \&_check_link_in_footer, }; -use constant UPDATE_COLUMNS => qw(query query_type); +use constant UPDATE_COLUMNS => qw(name query query_type); ############## # Validators # @@ -79,6 +79,8 @@ $query || ThrowUserError("buglist_parameters_required"); my $cgi = new Bugzilla::CGI($query); $cgi->clean_search_url; + # Don't store the query name as a parameter. + $cgi->delete('known_name'); return $cgi->query_string; } @@ -188,6 +190,7 @@ # Mutators # ############ +sub set_name { $_[0]->set('name', $_[1]); } sub set_url { $_[0]->set('query', $_[1]); } sub set_query_type { $_[0]->set('query_type', $_[1]); } Index: Bugzilla/User.pm =================================================================== --- Bugzilla/User.pm (wersja 600) +++ Bugzilla/User.pm (kopia robocza) @@ -682,7 +682,7 @@ } trick_taint($product_name); my $can_enter = - grep($_->name eq $product_name, @{$self->get_enterable_products}); + grep(lc($_->name) eq lc($product_name), @{$self->get_enterable_products}); return 1 if $can_enter; @@ -2005,7 +2005,7 @@ =item C<visible_groups_as_string> -Returns the result of C<visible_groups_direct> as a string (a comma-separated +Returns the result of C<visible_groups_inherited> as a string (a comma-separated list). =item C<product_responsibilities> Index: Bugzilla/WebService/Constants.pm =================================================================== --- Bugzilla/WebService/Constants.pm (wersja 600) +++ Bugzilla/WebService/Constants.pm (kopia robocza) @@ -50,6 +50,8 @@ # comment that it was retired. Also, if an error changes its name, you'll # have to fix it here. use constant WS_ERROR_CODE => { + # Generic Bugzilla::Object errors are 50-99. + param_required => 50, # Bug errors usually occupy the 100-200 range. invalid_bug_id_or_alias => 100, invalid_bug_id_non_existent => 101, Index: Bugzilla/WebService/User.pm =================================================================== --- Bugzilla/WebService/User.pm (wersja 600) +++ Bugzilla/WebService/User.pm (kopia robocza) @@ -37,6 +37,12 @@ sub login { my ($self, $params) = @_; my $remember = $params->{remember}; + + # Username and password params are required + foreach my $param ("login", "password") { + defined $params->{$param} + || ThrowCodeError('param_required', { param => $param }); + } # Convert $remember from a boolean 0/1 value to a CGI-compatible one. if (defined($remember)) { @@ -180,6 +186,10 @@ The account has been disabled. A reason may be specified with the error. +=item 50 (Param Required) + +A login or password parameter was not provided. + =back =back Index: contrib/bzdbcopy.pl =================================================================== --- contrib/bzdbcopy.pl (wersja 600) +++ contrib/bzdbcopy.pl (kopia robocza) @@ -48,6 +48,14 @@ . SOURCE_DB_TYPE . "...\n"; my $source_db = Bugzilla::DB::_connect(SOURCE_DB_TYPE, 'localhost', SOURCE_DB_NAME, undef, undef, SOURCE_DB_USER, SOURCE_DB_PASSWORD); +# Don't read entire tables into memory. +if (SOURCE_DB_TYPE eq 'Mysql') { + $source_db->{'mysql_use_result'}=1; + + # MySQL cannot have two queries running at the same time. Ensure the schema + # is loaded from the database so bz_column_info will not execute a query + $source_db->_bz_real_schema; +} print "Connecting to the '" . TARGET_DB_NAME . "' target database on " . TARGET_DB_TYPE . "...\n"; @@ -81,7 +89,8 @@ @table_columns; my $select_query = "SELECT " . join(',', @table_columns) . " FROM $table"; - my $data_in = $source_db->selectall_arrayref($select_query); + my $select_sth = $source_db->prepare($select_query); + $select_sth->execute(); my $insert_query = "INSERT INTO $table ( " . join(',', @table_columns) . " ) VALUES ("; @@ -97,7 +106,7 @@ print "Writing data to the target '$table' table on " . TARGET_DB_TYPE . "..."; - foreach my $row (@$data_in) { + while (my $row = $select_sth->fetchrow_arrayref) { # Each column needs to be bound separately, because # many columns need to be dealt with specially. my $colnum = 0; Index: contrib/syncLDAP.pl =================================================================== --- contrib/syncLDAP.pl (wersja 600) +++ contrib/syncLDAP.pl (kopia robocza) @@ -96,12 +96,18 @@ print "No LDAP server defined in bugzilla preferences.\n"; exit; } -my $LDAPport = "389"; # default LDAP port -if($LDAPserver =~ /:/) { - ($LDAPserver, $LDAPport) = split(":",$LDAPserver); +my $LDAPconn; +if($LDAPserver =~ /:\/\//) { + # if the "LDAPserver" parameter is in uri scheme + $LDAPconn = Net::LDAP->new($LDAPserver, version => 3); +} else { + my $LDAPport = "389"; # default LDAP port + if($LDAPserver =~ /:/) { + ($LDAPserver, $LDAPport) = split(":",$LDAPserver); + } + $LDAPconn = Net::LDAP->new($LDAPserver, port => $LDAPport, version => 3); } -my $LDAPconn = Net::LDAP->new($LDAPserver, port => $LDAPport, version => 3); if(!$LDAPconn) { print "Connecting to LDAP server failed. Check LDAPserver setting.\n"; exit; Index: email_in.pl =================================================================== --- email_in.pl (wersja 600) +++ email_in.pl (kopia robocza) @@ -330,6 +330,8 @@ $var =~ s/\>/>/g; $var =~ s/\"/\"/g; $var =~ s/@/@/g; + # Also remove undesired newlines and consecutive spaces. + $var =~ s/[\n\s]+/ /gms; return $var; } @@ -352,10 +354,12 @@ $msg =~ s/at .+ line.*$//ms; $msg =~ s/^Compilation failed in require.+$//ms; $msg = html_strip($msg); - my $reply = reply(to => $input_email, top_post => 1, body => "$msg\n"); + my $from = Bugzilla->params->{'mailfrom'}; + my $reply = reply(to => $input_email, from => $from, top_post => 1, + body => "$msg\n"); MessageToMTA($reply->as_string); } - print STDERR $msg; + print STDERR "$msg\n"; # We exit with a successful value, because we don't want the MTA # to *also* send a failure notice. exit; Index: importxml.pl =================================================================== --- importxml.pl (wersja 600) +++ importxml.pl (kopia robocza) @@ -379,8 +379,13 @@ elsif ($encoding =~ /filename/) { # read the attachment file Error("attach_path is required", undef) unless ($attach_path); - my $attach_filename = $attach_path . "/" . $attach->field('data'); - open(ATTACH_FH, $attach_filename) or + + my $filename = $attach->field('data'); + # Remove any leading path data from the filename + $filename =~ s/(.*\/|.*\\)//gs; + + my $attach_filename = $attach_path . "/" . $filename; + open(ATTACH_FH, "<", $attach_filename) or Error("cannot open $attach_filename", undef); $attachment{'data'} = do { local $/; <ATTACH_FH> }; close ATTACH_FH; Index: mod_perl.pl =================================================================== --- mod_perl.pl (wersja 600) +++ mod_perl.pl (kopia robocza) @@ -100,10 +100,12 @@ package Bugzilla::ModPerl::CleanupHandler; use strict; use Apache2::Const -compile => qw(OK); +use Bugzilla; sub handler { my $r = shift; - + + Bugzilla::_cleanup(); # Sometimes mod_perl doesn't properly call DESTROY on all # the objects in pnotes() foreach my $key (keys %{$r->pnotes}) { Index: template/en/default/admin/groups/create.html.tmpl =================================================================== --- template/en/default/admin/groups/create.html.tmpl (wersja 600) +++ template/en/default/admin/groups/create.html.tmpl (kopia robocza) @@ -55,8 +55,7 @@ <p><b>Name</b> is what is used with the B<!-- blah -->ugzilla->user->in_group() function in any customized cgi files you write that use a given group. It can also be used by people submitting [% terms.bugs %] by email to -limit [% terms.abug %] to a certain set of groups. It may not contain -any spaces.</p> +limit [% terms.abug %] to a certain set of groups.</p> <p><b>Description</b> is what will be shown in the [% terms.bug %] reports to members of the group where they can choose whether Index: template/en/default/admin/params/ldap.html.tmpl =================================================================== --- template/en/default/admin/params/ldap.html.tmpl (wersja 600) +++ template/en/default/admin/params/ldap.html.tmpl (kopia robocza) @@ -32,8 +32,8 @@ "ldapi://%2fvar%2flib%2fldap_sock (for a socket-based " _ "local connection.", - LDAPstartls => "Whether to require encrypted communication once normal " _ - "LDAP connection achieved with the server.", + LDAPstarttls => "Whether to require encrypted communication once a normal " _ + "LDAP connection is achieved with the server.", LDAPbinddn => "If your LDAP server requires that you use a binddn and password " _ "instead of binding anonymously, enter it here " _ Index: template/en/default/bug/create/create.html.tmpl =================================================================== --- template/en/default/bug/create/create.html.tmpl (wersja 600) +++ template/en/default/bug/create/create.html.tmpl (kopia robocza) @@ -401,7 +401,7 @@ [% USE Bugzilla %] [% FOREACH field = Bugzilla.get_fields({ obsolete => 0, custom => 1, enter_bug => 1 }) %] - [% SET value = ${field.name} IF ${field.name}.defined %] + [% SET value = ${field.name}.defined ? ${field.name} : "" %] <tr> [% PROCESS bug/field.html.tmpl editable=1 value_span=2 %] </tr> Index: template/en/default/bug/show.xml.tmpl =================================================================== --- template/en/default/bug/show.xml.tmpl (wersja 600) +++ template/en/default/bug/show.xml.tmpl (kopia robocza) @@ -109,6 +109,9 @@ </attachment> [% END %] [% END %] + + [% Hook.process("bug_end") %] + </bug> [% END %] [% END %] Index: template/en/default/flag/list.html.tmpl =================================================================== --- template/en/default/flag/list.html.tmpl (wersja 600) +++ template/en/default/flag/list.html.tmpl (kopia robocza) @@ -156,7 +156,7 @@ <td> <select id="flag_type-[% type.id %]" name="flag_type-[% type.id %]" title="[% type.description FILTER html %]" - [% " disabled=\"disabled\"" UNLESS user.can_request_flag(type) %] + [% " disabled=\"disabled\"" UNLESS (type.is_requestable && user.can_request_flag(type)) || user.can_set_flag(type) %] onchange="toggleRequesteeField(this);" class="flag_select"> <option value="X"></option> @@ -200,7 +200,7 @@ <td> <select id="flag_type-[% type.id %]" name="flag_type-[% type.id %]" title="[% type.description FILTER html %]" - [% " disabled=\"disabled\"" UNLESS user.can_request_flag(type) %] + [% " disabled=\"disabled\"" UNLESS (type.is_requestable && user.can_request_flag(type)) || user.can_set_flag(type) %] onchange="toggleRequesteeField(this);" class="flag_select"> <option value="X"></option> Index: template/en/default/list/edit-multiple.html.tmpl =================================================================== --- template/en/default/list/edit-multiple.html.tmpl (wersja 600) +++ template/en/default/list/edit-multiple.html.tmpl (kopia robocza) @@ -215,6 +215,8 @@ allow_dont_change = 1 %] </tr> [% END %] + + [% Hook.process("after_custom_fields") %] </table> Index: template/en/default/pages/release-notes.html.tmpl =================================================================== --- template/en/default/pages/release-notes.html.tmpl (wersja 600) +++ template/en/default/pages/release-notes.html.tmpl (kopia robocza) @@ -20,7 +20,7 @@ [% PROCESS global/variables.none.tmpl %] [% INCLUDE global/header.html.tmpl - title = "$terms.Bugzilla 3.0.4 Release Notes" + title = "$terms.Bugzilla 3.0.5 Release Notes" style_urls = ['skins/standard/release-notes.css'] %] @@ -60,7 +60,30 @@ most important fixes in each release. If you want a detailed list of <em>everything</em> that's changed in each version, you should use our <a href="http://www.bugzilla.org/status/changes.html">Change Log Page</a>.</p> + + <h3>3.0.5</h3> +<ul> + <li>If you don't have permission to set a flag, it will now appear + unchangeable in the UI. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=433851">[% terms.Bug %] 433851</a>)</li> + <li>If you were running mod_perl, [% terms.Bugzilla %] was not correctly + closing its connections to the database since 3.0.3, and so sometimes + the DB would run out of connections. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=441592">[% terms.Bug %] 441592</a>)</li> + <li>The installation script is now clear about exactly which + <code>Email::</code> modules are required in Perl, thus avoiding the + problem where emails show up with a body like + <samp>SCALAR(0xBF126795)</samp>. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=441541">[% terms.Bug %] 441541</a>)</li> + <li><a href="[% Param('docs_urlbase') FILTER html %]api/email_in.html">email_in.pl</a> + is no longer case-sensitive for values of <kbd>@product</kbd>. + (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=365697">[% terms.Bug %] 365697</a>)</li> +</ul> + +<p>See also the <a href="#v30_security">Security Advisory</a> section for + information about security issues fixed in this release.</p> + <h3>3.0.4</h3> <ul> @@ -660,6 +683,13 @@ <h2><a name="v30_security"></a>Security Updates in This Release</h2> +<h3>3.0.5</h3> + +<p>[% terms.Bugzilla %] contains one security fix for + <a href="[% Param('docs_urlbase') FILTER html %]api/importxml.html">importxml.pl</a>. + For details, see the + <a href="http://www.bugzilla.org/security/2.22.4/">Security Advisory</a>.</p> + <h3>3.0.4</h3> <p>[% terms.Bugzilla %] 3.0.4 contains three security fixes. @@ -717,49 +747,10 @@ <h3>Steps For Upgrading</h3> -<ol> - <li>Read these entire Release Notes, particularly the "Notes for - Upgraders" section above.</li> +<p>Once you have read the notes above, see the + <a href="[% Param('docs_urlbase') FILTER html %]upgrade.html">Upgrading + documentation</a> for instructions on how to upgrade.</p> - <li>View the <a href="sanitycheck.cgi">Sanity Check</a> page on your - installation before upgrading. Attempt to fix all warnings that - the page produces before you go any further, or you may experience - problems during your upgrade.</li> - - <li>Make a backup of the [% terms.Bugzilla %] database before you upgrade, - perhaps by using <kbd>mysqldump</kbd>. <strong>THIS IS VERY - IMPORTANT</strong>. If anything goes wrong during the upgrade, your - installation can be corrupted beyond recovery. Having a backup keeps you - safe. - - <p>Example: <kbd>mysqldump -u root -p bu[%# trick filter %]gs > - bu[%# trick filter %]gs-db.sql</kbd></p></li> - - <li>Replace the files in your installation with the new version of - [% terms.Bugzilla %], or you can try to use CVS to upgrade. - - <p>You can also use a brand-new [% terms.Bugzilla %] directory, as long - as you copy over the old <kbd>data/</kbd> directory and the - <kbd>localconfig</kbd> file to the new installation.</p></li> - - <li>Now follow the standard - <a href="[% Param('docs_urlbase') FILTER html %]installing-bugzilla.html"> - [%- terms.Bugzilla %] installation process</a>.</li> - - <li>Run <kbd>checksetup.pl</kbd> after you install the new version.</li> - - <li>View the <a href="sanitycheck.cgi">Sanity Check</a> page again after - you run <kbd>checksetup.pl</kbd>.</li> - - <li>It is recommended that, if possible, you fix any problems you find - immediately. Failure to do this may mean that [% terms.Bugzilla %] will - not work correctly. Be aware that if the sanity check page contains more - errors after an upgrade, it doesn't necessarily mean there are more - errors in your database than there were before, as additional tests - are added to the sanity check over time, and it is possible that those - errors weren't being checked for in the old version.</li> -</ol> - <h2><a name="v30_code_changes"></a>Code Changes Which May Affect Customizations</h2> Index: xmlrpc.cgi =================================================================== --- xmlrpc.cgi (wersja 600) +++ xmlrpc.cgi (kopia robocza) @@ -20,6 +20,7 @@ use Bugzilla; use Bugzilla::Constants; +use Bugzilla::Hook; # Use an eval here so that runtests.pl accepts this script even if SOAP-Lite # is not installed. @@ -29,11 +30,16 @@ Bugzilla->usage_mode(Bugzilla::Constants::USAGE_MODE_WEBSERVICE); +my %hook_dispatch; +Bugzilla::Hook::process('webservice', { dispatch => \%hook_dispatch }); +local @INC = (bz_locations()->{extensionsdir}, @INC); + my $response = Bugzilla::WebService::XMLRPC::Transport::HTTP::CGI ->dispatch_with({'Bugzilla' => 'Bugzilla::WebService::Bugzilla', 'Bug' => 'Bugzilla::WebService::Bug', 'User' => 'Bugzilla::WebService::User', 'Product' => 'Bugzilla::WebService::Product', + %hook_dispatch }) ->on_action(\&Bugzilla::WebService::handle_login) ->handle;