Merge branch '21.11.x-rmaint' into 21.11.x-security

This commit is contained in:
danyonsewell 2023-08-04 01:10:31 +00:00
commit 4b94de1036
18 changed files with 170 additions and 58 deletions

View File

@ -1218,14 +1218,8 @@ sub GetMarcBiblio {
return;
}
my $dbh = C4::Context->dbh;
my $sth = $dbh->prepare("SELECT biblioitemnumber FROM biblioitems WHERE biblionumber=? ");
$sth->execute($biblionumber);
my $row = $sth->fetchrow_hashref;
my $biblioitemnumber = $row->{'biblioitemnumber'};
my $marcxml = GetXmlBiblio( $biblionumber );
$marcxml = StripNonXmlChars( $marcxml );
my $frameworkcode = GetFrameworkCode($biblionumber);
MARC::File::XML->default_record_format( C4::Context->preference('marcflavour') );
my $record = MARC::Record->new();
@ -1237,8 +1231,6 @@ sub GetMarcBiblio {
if ($@) { warn " problem with :$biblionumber : $@ \n$marcxml"; }
return unless $record;
C4::Biblio::_koha_marc_update_bib_ids( $record, $frameworkcode, $biblionumber,
$biblioitemnumber );
C4::Biblio::EmbedItemsInMarcBiblio({
marc_record => $record,
biblionumber => $biblionumber,

View File

@ -29,7 +29,7 @@ use vars qw{ $VERSION };
# - #4 : the developer version. The 4th number is the database subversion.
# used by developers when the database changes. updatedatabase take care of the changes itself
# and is automatically called by Auth.pm when needed.
$VERSION = "21.11.21.000";
$VERSION = "21.11.22.000";
sub version {
return $VERSION;

View File

@ -59,10 +59,10 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>-v</option>|<option>--verbose</option></term>
<listitem>
<para>Enable verbose output.</para>
</listitem>
<term><option>--queue</option></term>
<listitem>
<para>Allows specifying the queue worker (defaults to 'default').</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>-h</option>|<option>--help</option></term>

View File

@ -72,3 +72,5 @@ do
[ "$chdir" != "no" ] && cd "$starting_dir"
fi
done
exit 0

0
installer/data/mysql/db_revs/211120000.pl Normal file → Executable file
View File

View File

@ -2,6 +2,7 @@ use Modern::Perl;
return {
bug_number => undef,
description => 'Koha 21.11.12 release',
description => 'Koha 21.11.21 release',
up => sub {},
}

View File

@ -0,0 +1,8 @@
use Modern::Perl;
return {
bug_number => undef,
description => 'Koha 21.11.22 release',
up => sub {},
}

View File

@ -72,7 +72,11 @@
<ol>
<li>
<label for="spec" class="required">setSpec: </label>
<input type="text" id="spec" name="spec" value="[% spec | html %]" required="required" class="required" />
[% IF ( spec == "" ) %]
<input type="text" id="spec" class="focus" name="spec" value="[% spec | html %]" required="required" class="required" />
[% ELSE %]
<input type="text" id="spec" name="spec" value="[% spec | html %]" required="required" class="required" />
[% END %]
<span class="required">Required</span>
</li>
<li>

View File

@ -376,22 +376,22 @@ Patrons:
choices:
1: Enable
0: Disable
- "pseudonymization to comply with GDPR for personal information."
- "Patrons and transactions will be copied to a separate table for statistics purpose."
- "pseudonymization to comply with data privacy policies and regulations like GDPR for managing personal information."
- "Patrons and transactions will be copied to a separate table for statistical purposes."
- "<br/>Use the following fields for patrons:"
- pref: PseudonymizationPatronFields
multiple:
title: "Patron's title"
city: "City"
state: "State"
zipcode: "Zipcode"
zipcode: "ZIP/Postal code"
country: "Country"
branchcode: "Patron's library"
categorycode: "Patron's category"
categorycode: "Patron category"
dateenrolled: "Date the patron was added to Koha"
sex: "Patron's gender"
sort1: "Sort1"
sort2: "Sort2"
sort1: "Sort 1"
sort2: "Sort 2"
- "<br/> And the following fields for the transactions:"
- pref: PseudonymizationTransactionFields
multiple:

View File

@ -95,7 +95,12 @@
<fieldset class="rows">
<ol>
<li><label for="name" class="required">Server name: </label>
<input type="text" name="servername" id="servername" size="65" maxlength="100" value="[% server.servername | html %]" required="required" /> <span class="required">Required</span>
[% IF server.servername %]
<input type="text" name="servername" id="servername" size="65" maxlength="100" value="[% server.servername | html %]" required="required" />
[% ELSE %]
<input type="text" name="servername" id="servername" class="focus" size="65" maxlength="100" value="[% server.servername | html %]" required="required" />
[% END %]
<span class="required">Required</span>
</li>
<li><label for="host" class="required">Hostname: </label> <input type="text" name="host" id="host" size="30" value="[% server.host | html %]" required="required" /> <span class="required">Required</span>

View File

@ -451,20 +451,6 @@ function PopupMARCFieldDoc(field) {
}
}
function PopupMARCFieldDoc(field) {
[% IF Koha.Preference('marcfielddocurl') %]
var docurl = "[% Koha.Preference('marcfielddocurl').replace('"','&quot;') | html %]";
docurl = docurl.replace("{MARC}", "[% marcflavour | html %]");
docurl = docurl.replace("{FIELD}", ""+field);
docurl = docurl.replace("{LANG}", "[% lang | html %]");
window.open(docurl);
[% ELSIF ( marcflavour == 'MARC21' ) %]
_MARC21FieldDoc(field);
[% ELSIF ( marcflavour == 'UNIMARC' ) %]
_UNIMARCFieldDoc(field);
[% END %]
}
function _MARC21FieldDoc(field) {
if(field == 0) {
window.open("http://www.loc.gov/marc/bibliographic/bdleader.html");

View File

@ -1462,7 +1462,7 @@
var value = parseInt($(this).val());
var found_holds = $("select[name='rank-request'][disabled='disabled']").length ; //Count how many are found
if( !isNaN(value) ) { //If moved to 'del'
var after = row.parent().find("tr:nth-child("+(value+1+found_holds )+")"); //Go to the row 1 after the new value (and skip found holds)
var after = row.parent().find(`tr:nth-child(${value+found_holds})`); //Go to the row 1 after the new value (and skip found holds)
if (prev_rank_request > value) {
row.insertBefore(after);
} else {

View File

@ -395,14 +395,13 @@
</table>
[% ELSE %]
<div class="dialog alert">
No log found
[% IF ( CATALOGUING ) %]
for <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% object | url %]">Bibliographic record [% object | html %]</a>
No log found for <a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=[% object | url %]">Bibliographic record [% object | html %]</a>.
[% ELSIF ( MEMBERS ) %]
No log found for <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% object | url %]">[% INCLUDE 'patron-title.inc' %]</a>.
[% ELSE %]
No log found.
[% END %]
[% IF ( MEMBERS ) %]
for <a href="/cgi-bin/koha/members/moremember.pl?borrowernumber=[% object | url %]">[% INCLUDE 'patron-title.inc' %]</a>
[% END %]
.
</div>
[% END %]
[% END %]

View File

@ -450,6 +450,9 @@
[% BLOCK jsinclude %]
[% Asset.js("lib/jquery/plugins/jquery.deserialize.min.js") | $raw %]
<script>
window.addEventListener('pageshow', function( e ){
$('.form-control').prop('disabled' , false );
});
$(document).ready(function() {
[% IF search_groups %]
function branch_limit() {
@ -548,6 +551,5 @@ $(document).ready(function() {
$(this).parent().parent().remove();
$('.search-term-row .search-term-input select[name="op"]').first().prop("disabled",true).hide();
});
</script>
[% END %]

View File

@ -1310,11 +1310,7 @@
<xsl:call-template name="listCallNumbers">
<xsl:with-param name="items" select="$reference_items[items:resultbranch=$currentbranch and items:substatus=$current_substatus]"/>
<xsl:with-param name="max" select="$OPACResultsMaxItems"/>
<xsl:with-param name="status_text">
<xsl:value-of select="concat($currentbranch,': ')"/>
<xsl:value-of select="exsl:node-set($item_status_list)/status[@english=$current_substatus]|$current_substatus"/>
<!-- Note that value-of here picks string value of first node only from the union; keep in mind too that current_substatus may contain an authorised value -->
</xsl:with-param>
<xsl:with-param name="status_text" select="concat($currentbranch,': ',$current_substatus)"/>
<xsl:with-param name="class_block" select="concat('notforloandesc_',$current_substatus)"/>
<xsl:with-param name="class_status" select="'ItemBranch'"/>
<xsl:with-param name="OPACItemLocation" select="$OPACItemLocation"/>
@ -1335,7 +1331,6 @@
<status english="Pending hold">Pending hold</status>
<status english="In transit">In transit</status>
<status english="Waiting">On hold</status>
<status english="Not for loan">Not for loan</status>
</xsl:variable>
<xsl:variable name="unavailable_items" select="key('item-by-status', 'reallynotforloan')|key('item-by-status', 'other')"/>
<xsl:choose>
@ -1355,7 +1350,12 @@
<xsl:with-param name="status_text">
<xsl:value-of select="$currentbranch"/>
<xsl:text>: </xsl:text>
<xsl:value-of select="exsl:node-set($item_status_list)/status[@english=$current_substatus]|$current_substatus"/><!-- See former comment on value-of and union -->
<xsl:if test="items:status='other'">
<xsl:value-of select="exsl:node-set($other_status_list)/status[@english=$current_substatus]"/>
</xsl:if>
<xsl:if test="items:status='reallynotforloan'">
<xsl:value-of select="$current_substatus"/>
</xsl:if>
</xsl:with-param>
<xsl:with-param name="class_block" select="concat('unavailable_',items:substatus)"/>
<xsl:with-param name="class_status" select="'ItemBranch'"/>
@ -1374,7 +1374,12 @@
<xsl:with-param name="items" select="$unavailable_items[items:substatus=$current_substatus]"/>
<xsl:with-param name="max" select="0"/>
<xsl:with-param name="status_text">
<xsl:value-of select="exsl:node-set($item_status_list)/status[@english=$current_substatus]|$current_substatus"/><!-- See former comment on value-of and union -->
<xsl:if test="items:status='other'">
<xsl:value-of select="exsl:node-set($other_status_list)/status[@english=$current_substatus]"/>
</xsl:if>
<xsl:if test="items:status='reallynotforloan'">
<xsl:value-of select="$current_substatus"/>
</xsl:if>
</xsl:with-param>
<xsl:with-param name="class_block" select="concat('unavailable_',$current_substatus)"/>
<xsl:with-param name="class_status" select="UnavailableSubstatus"/>

View File

@ -118,8 +118,10 @@ use C4::Biblio qw( GetMarcFromKohaField );
}
}
my @decoding_errors;
my ( @decoding_errors, @ids_not_in_marc );
my $biblios = Koha::Biblios->search;
my ( $biblio_tag, $biblio_subfield ) = C4::Biblio::GetMarcFromKohaField( "biblio.biblionumber" );
my ( $biblioitem_tag, $biblioitem_subfield ) = C4::Biblio::GetMarcFromKohaField( "biblioitems.biblioitemnumber" );
while ( my $biblio = $biblios->next ) {
my $record = eval{$biblio->metadata->record;};
if ($@) {
@ -160,6 +162,33 @@ use C4::Biblio qw( GetMarcFromKohaField );
new_item($_) for @decoding_errors;
new_hint("The bibliographic records must have a valid MARCXML or you will face encoding issues or wrong displays");
}
if (@ids_not_in_marc) {
new_section("Bibliographic records have MARCXML without biblionumber or biblioitemnumber");
for my $id (@ids_not_in_marc) {
if ( exists $id->{biblioitemnumber} ) {
new_item(
sprintf(q{Biblionumber %s has biblioitemnumber '%s' but should be '%s' in %s$%s},
$id->{biblionumber},
$id->{biblioitemnumber},
$id->{biblioitemnumber_in_marc},
$biblioitem_tag,
$biblioitem_subfield,
)
);
}
else {
new_item(
sprintf(q{Biblionumber %s has '%s' in %s$%s},
$id->{biblionumber},
$id->{biblionumber_in_marc},
$biblio_tag,
$biblio_subfield,
)
);
}
}
new_hint("The bibliographic records must have the biblionumber and biblioitemnumber in MARCXML");
}
}
{

View File

@ -420,8 +420,6 @@ sub run_tests {
is( GetMarcPrice( $record_for_isbn, $marcflavour ), 100,
"GetMarcPrice returns the correct value");
my $newincbiblioitemnumber=$biblioitemnumber+1;
$dbh->do("UPDATE biblioitems SET biblioitemnumber = ? WHERE biblionumber = ?;", undef, $newincbiblioitemnumber, $biblionumber );
my $updatedrecord = GetMarcBiblio({
biblionumber => $biblionumber,
embed_items => 0 });
@ -434,7 +432,6 @@ sub run_tests {
} else {
$biblioitemnumbertotest = $updatedrecord->field($biblioitem_tag)->subfield($biblioitem_subfield);
}
is ($newincbiblioitemnumber, $biblioitemnumbertotest, 'Check newincbiblioitemnumber');
# test for GetMarcUrls
$marc_record->append_fields(
@ -597,14 +594,14 @@ sub create_author_field {
}
subtest 'MARC21' => sub {
plan tests => 47;
plan tests => 46;
run_tests('MARC21');
$schema->storage->txn_rollback;
$schema->storage->txn_begin;
};
subtest 'UNIMARC' => sub {
plan tests => 47;
plan tests => 46;
# Mock the auth type data for UNIMARC
$dbh->do("UPDATE auth_types SET auth_tag_to_report = '106' WHERE auth_tag_to_report = '100'") or die $dbh->errstr;

82
xt/find-missing-csrf.t Executable file
View File

@ -0,0 +1,82 @@
#!/usr/bin/perl
# Copyright 2021 Koha development team
#
# This file is part of Koha.
#
# Koha is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# Koha is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Koha; if not, see <http://www.gnu.org/licenses>.
use Modern::Perl;
use Test::More tests => 1;
use File::Find;
use File::Slurp;
use Data::Dumper;
my @themes;
# OPAC themes
my $opac_dir = 'koha-tmpl/opac-tmpl';
opendir ( my $dh, $opac_dir ) or die "can't opendir $opac_dir: $!";
for my $theme ( grep { not /^\.|lib|js|xslt/ } readdir($dh) ) {
push @themes, "$opac_dir/$theme/en";
}
close $dh;
# STAFF themes
my $staff_dir = 'koha-tmpl/intranet-tmpl';
opendir ( $dh, $staff_dir ) or die "can't opendir $staff_dir: $!";
for my $theme ( grep { not /^\.|lib|js/ } readdir($dh) ) {
push @themes, "$staff_dir/$theme/en";
}
close $dh;
my @files;
sub wanted {
my $name = $File::Find::name;
push @files, $name
if $name =~ m[\.(tt|inc)$] and -f $name;
}
find({ wanted => \&wanted, no_chdir => 1 }, @themes );
my @errors;
for my $file ( @files ) {
my @e = check_csrf_in_forms($file);
push @errors, { file => $file, errors => \@e } if @e;
}
is( @errors, 0, "Template variables should be correctly escaped" )
or diag(Dumper @errors);
sub check_csrf_in_forms {
my ( $file ) = @_;
my @lines = read_file($file);
my @errors;
return @errors unless grep { $_ =~ m|<form| } @lines;
my ( $open, $found ) = ( 0, 0 );
my $line = 0 ;
for my $l (@lines) {
$line++;
$open = $line if ( $l =~ m{<form} && !( $l =~ m{method=('|")get('|")} ) );
$found++ if ( $l =~ m|csrf\-token\.inc| && $open );
if ( $open && $l =~ m|</form| ) {
push @errors,
"The <form> starting on line $open is missing it's corresponding csrf_token include (see bug 22990)"
if !$found;
$found = 0;
}
}
return @errors;
}