Bug 9504: URL escape in OPAC more searches

OPACSearchForTitleIn is a syspref used to add links as "more searches" in OPAC record detail page.
The links can contain vars depending on record values like title, ISBN, ...
Thoses values must be URL-escaped because they can contain special characters that will brake URL and/or HTML.

This patch add a method C4::Output::parametrized_url() that replaces vars in URL usign escape and UTF-8 encoding.

Test plan :
- Define in OPACSearchForTitleIn a link with all possible vars : TITLE, AUTHOR, ISBN, ISSN, CONTROLNUMBER, BIBLIONUMBER
- Edit a record to add special characters in title : ", &, ? ...
- Go to OPAC detail pages of this record
=> Check that URL is well encoded
=> Click on link to check the term is well encoded (diacritical characters, ...)

Signed-off-by: Liz Rea <liz@catalyst.net.nz>
Nice test plan, thanks!

Verified bug and fix - both look good.
Signed-off-by: Mason James <mtj@kohaaloha.com>
Signed-off-by: Jared Camins-Esakov <jcamins@cpbibliography.com>
This commit is contained in:
Fridolyn SOMERS 2013-01-29 18:03:02 +01:00 committed by Chris Cormack
parent 568ff3c1ea
commit 5f4fce34b4
4 changed files with 51 additions and 22 deletions

View File

@ -28,6 +28,8 @@ package C4::Output;
use strict;
#use warnings; FIXME - Bug 2505
use URI::Escape;
use C4::Context;
use C4::Dates qw(format_date);
use C4::Budgets qw(GetCurrency);
@ -42,13 +44,13 @@ BEGIN {
@ISA = qw(Exporter);
@EXPORT_OK = qw(&is_ajax ajax_fail); # More stuff should go here instead
%EXPORT_TAGS = ( all =>[qw(setlanguagecookie pagination_bar
%EXPORT_TAGS = ( all =>[qw(setlanguagecookie pagination_bar parametrized_url
&output_with_http_headers &output_ajax_with_http_headers &output_html_with_http_headers)],
ajax =>[qw(&output_with_http_headers &output_ajax_with_http_headers is_ajax)],
html =>[qw(&output_with_http_headers &output_html_with_http_headers)]
);
push @EXPORT, qw(
setlanguagecookie getlanguagecookie pagination_bar
setlanguagecookie getlanguagecookie pagination_bar parametrized_url
);
push @EXPORT, qw(
&output_html_with_http_headers &output_ajax_with_http_headers &output_with_http_headers FormatData FormatNumber
@ -327,6 +329,18 @@ sub is_ajax {
return ( $x_req and $x_req =~ /XMLHttpRequest/i ) ? 1 : 0;
}
sub parametrized_url {
my $url = shift || ''; # ie page.pl?ln={LANG}
my $vars = shift || {}; # ie { LANG => en }
my $ret = $url;
while ( my ($key,$val) = each %$vars) {
my $val_url = URI::Escape::uri_escape_utf8($val);
$ret =~ s/\{$key\}/$val_url/g;
}
$ret =~ s/\{[^\{]*\}//g; # remove not defined vars
return $ret;
}
END { } # module clean-up code here (global destructor)
1;

View File

@ -181,15 +181,20 @@ my $marcissns = GetMarcISSN ( $record, $marcflavour );
my $issn = $marcissns->[0] || '';
if (my $search_for_title = C4::Context->preference('OPACSearchForTitleIn')){
$dat->{author} ? $search_for_title =~ s/{AUTHOR}/$dat->{author}/g : $search_for_title =~ s/{AUTHOR}//g;
$dat->{title} =~ s/\/+$//; # remove trailing slash
$dat->{title} =~ s/\s+$//; # remove trailing space
$dat->{title} ? $search_for_title =~ s/{TITLE}/$dat->{title}/g : $search_for_title =~ s/{TITLE}//g;
$isbn ? $search_for_title =~ s/{ISBN}/$isbn/g : $search_for_title =~ s/{ISBN}//g;
$issn ? $search_for_title =~ s/{ISSN}/$issn/g : $search_for_title =~ s/{ISSN}//g;
$marccontrolnumber ? $search_for_title =~ s/{CONTROLNUMBER}/$marccontrolnumber/g : $search_for_title =~ s/{CONTROLNUMBER}//g;
$search_for_title =~ s/{BIBLIONUMBER}/$biblionumber/g;
$template->param('OPACSearchForTitleIn' => $search_for_title);
$search_for_title = parametrized_url(
$search_for_title,
{
TITLE => $dat->{title},
AUTHOR => $dat->{author},
ISBN => $isbn,
ISSN => $issn,
CONTROLNUMBER => $marccontrolnumber,
BIBLIONUMBER => $biblionumber,
}
);
$template->param('OPACSearchForTitleIn' => $search_for_title);
}
output_html_with_http_headers $query, $cookie, $template->output;

View File

@ -296,15 +296,20 @@ my $marcissns = GetMarcISSN( $record, $marcflavour );
my $issn = $marcissns->[0] || '';
if (my $search_for_title = C4::Context->preference('OPACSearchForTitleIn')){
$dat->{author} ? $search_for_title =~ s/{AUTHOR}/$dat->{author}/g : $search_for_title =~ s/{AUTHOR}//g;
$dat->{title} =~ s/\/+$//; # remove trailing slash
$dat->{title} =~ s/\s+$//; # remove trailing space
$dat->{title} ? $search_for_title =~ s/{TITLE}/$dat->{title}/g : $search_for_title =~ s/{TITLE}//g;
$isbn ? $search_for_title =~ s/{ISBN}/$isbn/g : $search_for_title =~ s/{ISBN}//g;
$issn ? $search_for_title =~ s/{ISSN}/$issn/g : $search_for_title =~ s/{ISSN}//g;
$marccontrolnumber ? $search_for_title =~ s/{CONTROLNUMBER}/$marccontrolnumber/g : $search_for_title =~ s/{CONTROLNUMBER}//g;
$search_for_title =~ s/{BIBLIONUMBER}/$biblionumber/g;
$template->param('OPACSearchForTitleIn' => $search_for_title);
$search_for_title = parametrized_url(
$search_for_title,
{
TITLE => $dat->{title},
AUTHOR => $dat->{author},
ISBN => $isbn,
ISSN => $issn,
CONTROLNUMBER => $marccontrolnumber,
BIBLIONUMBER => $biblionumber,
}
);
$template->param('OPACSearchForTitleIn' => $search_for_title);
}
$template->param(

View File

@ -934,14 +934,19 @@ my $marcissns = GetMarcISSN ( $record, $marcflavour );
my $issn = $marcissns->[0] || '';
if (my $search_for_title = C4::Context->preference('OPACSearchForTitleIn')){
$dat->{author} ? $search_for_title =~ s/{AUTHOR}/$dat->{author}/g : $search_for_title =~ s/{AUTHOR}//g;
$dat->{title} =~ s/\/+$//; # remove trailing slash
$dat->{title} =~ s/\s+$//; # remove trailing space
$dat->{title} ? $search_for_title =~ s/{TITLE}/$dat->{title}/g : $search_for_title =~ s/{TITLE}//g;
$isbn ? $search_for_title =~ s/{ISBN}/$isbn/g : $search_for_title =~ s/{ISBN}//g;
$issn ? $search_for_title =~ s/{ISSN}/$issn/g : $search_for_title =~ s/{ISSN}//g;
$marccontrolnumber ? $search_for_title =~ s/{CONTROLNUMBER}/$marccontrolnumber/g : $search_for_title =~ s/{CONTROLNUMBER}//g;
$search_for_title =~ s/{BIBLIONUMBER}/$biblionumber/g;
$search_for_title = parametrized_url(
$search_for_title,
{
TITLE => $dat->{title},
AUTHOR => $dat->{author},
ISBN => $isbn,
ISSN => $issn,
CONTROLNUMBER => $marccontrolnumber,
BIBLIONUMBER => $biblionumber,
}
);
$template->param('OPACSearchForTitleIn' => $search_for_title);
}