diff --git a/Koha/Items.pm b/Koha/Items.pm index 7827b15b9e..0a05b51553 100644 --- a/Koha/Items.pm +++ b/Koha/Items.pm @@ -32,6 +32,7 @@ use Koha::SearchEngine::Indexer; use Koha::Item::Attributes; use Koha::Item; use Koha::CirculationRules; +use Koha::Regex::Replacement; use base qw(Koha::Objects); @@ -607,25 +608,24 @@ sub apply_regex { my $modifiers = $params->{modifiers} || q{}; my $value = $params->{value}; - $replace =~ s/"/\\"/g; # Protection from embedded code - $replace = '"' . $replace . '"'; # Put in a string for /ee my @available_modifiers = qw( i g ); my $retained_modifiers = q||; for my $modifier ( split //, $modifiers ) { $retained_modifiers .= $modifier if grep { /$modifier/ } @available_modifiers; } + + # The replacement is expanded as DATA (capture-group backreferences and the + # \n \r \t escapes) and never evaluated as code, so @{...}/${...} + # interpolation blocks are inert text, not Perl. if ( $retained_modifiers =~ m/^(ig|gi)$/ ) { - $value =~ s/$search/$replace/igee; - } - elsif ( $retained_modifiers eq 'i' ) { - $value =~ s/$search/$replace/iee; - } - elsif ( $retained_modifiers eq 'g' ) { - $value =~ s/$search/$replace/gee; - } - else { - $value =~ s/$search/$replace/ee; + $value =~ s/$search/Koha::Regex::Replacement::expand_template( $replace, [@{^CAPTURE}], {%+} )/ige; + } elsif ( $retained_modifiers eq 'i' ) { + $value =~ s/$search/Koha::Regex::Replacement::expand_template( $replace, [@{^CAPTURE}], {%+} )/ie; + } elsif ( $retained_modifiers eq 'g' ) { + $value =~ s/$search/Koha::Regex::Replacement::expand_template( $replace, [@{^CAPTURE}], {%+} )/ge; + } else { + $value =~ s/$search/Koha::Regex::Replacement::expand_template( $replace, [@{^CAPTURE}], {%+} )/e; } return $value; diff --git a/Koha/SimpleMARC.pm b/Koha/SimpleMARC.pm index 1c1aa9d93a..30431571b8 100644 --- a/Koha/SimpleMARC.pm +++ b/Koha/SimpleMARC.pm @@ -21,6 +21,8 @@ use Modern::Perl; use constant LAST_TRANSACTION_FIELD => q/005/; # MARC21/UNIMARC our (@ISA, @EXPORT_OK); +use Koha::Regex::Replacement; + BEGIN { require Exporter; our @ISA = qw(Exporter); @@ -696,8 +698,6 @@ sub _modify_values { if ( $regex and $regex->{search} ) { my $replace = $regex->{replace}; - $replace =~ s/"/\\"/g; # Protection from embedded code - $replace = '"' . $replace . '"'; # Put in a string for /ee $regex->{modifiers} //= q||; my @available_modifiers = qw( i g ); my $modifiers = q||; @@ -705,18 +705,20 @@ sub _modify_values { $modifiers .= $modifier if grep {/$modifier/} @available_modifiers; } - foreach my $value ( @$values ) { + my $search = $regex->{search}; + foreach my $value (@$values) { + + # The replacement is expanded as DATA (capture-group backreferences + # and the \n \r \t escapes) and never evaluated as code, so + # @{...}/${...} interpolation blocks are inert text, not Perl. if ( $modifiers =~ m/^(ig|gi)$/ ) { - $value =~ s/$regex->{search}/$replace/igee; - } - elsif ( $modifiers eq 'i' ) { - $value =~ s/$regex->{search}/$replace/iee; - } - elsif ( $modifiers eq 'g' ) { - $value =~ s/$regex->{search}/$replace/gee; - } - else { - $value =~ s/$regex->{search}/$replace/ee; + $value =~ s/$search/Koha::Regex::Replacement::expand_template( $replace, [@{^CAPTURE}], {%+} )/ige; + } elsif ( $modifiers eq 'i' ) { + $value =~ s/$search/Koha::Regex::Replacement::expand_template( $replace, [@{^CAPTURE}], {%+} )/ie; + } elsif ( $modifiers eq 'g' ) { + $value =~ s/$search/Koha::Regex::Replacement::expand_template( $replace, [@{^CAPTURE}], {%+} )/ge; + } else { + $value =~ s/$search/Koha::Regex::Replacement::expand_template( $replace, [@{^CAPTURE}], {%+} )/e; } } }