diff --git a/Koha/Util.pm b/Koha/Util.pm new file mode 100644 index 00000000000..ce618635d3f --- /dev/null +++ b/Koha/Util.pm @@ -0,0 +1,87 @@ +package Koha::Util; + +# Copyright Rijksmuseum 2018 +# +# 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, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +use Modern::Perl; +use C4::Context; + +=head1 NAME + +Koha::Util + +=head1 SYNOPSIS + + use Koha::Util; + my $cgi = CGI->new; + my $referer = Koha::Util::localReferer($cgi); + +=head1 DESCRIPTION + +Utility class + +=head1 FUNCTIONS + +=head2 localReferer + + my $referer = Koha::Util::localReferer( $cgi, { fallback => '/', remove_language => 1, staff => 1 }); + + If the referer is a local URI, return local path. + Otherwise return fallback. + Optional parameters fallback, remove_language and staff. If you do not + pass staff, opac is assumed. + +=cut + +sub localReferer { + my ( $cgi, $params ) = @_; + my $referer = $cgi->referer; + my $fallback = $params->{fallback} // '/'; + my $staff = $params->{staff}; # no staff means OPAC + return $fallback if !$referer; + + my $base = C4::Context->preference($staff ? 'staffClientBaseURL' : 'OPACBaseURL'); + my $rv; + + # Try ..BaseURL first, otherwise use CGI::url + if( $base ) { + if( substr($referer, 0, length($base)) eq $base && + $referer =~ /\/cgi-bin\/koha\// ) + { + $rv = substr( $referer, length($base) ); + $rv =~ s/^\///; + $rv = '/'.$rv; + } + } else { + my $cgibase = $cgi->url( -base => 1 ); + $cgibase =~ s/^https?://; + if( $referer =~ /$cgibase(\/cgi-bin\/koha\/.*)$/ ) { + $rv = $1; + } + } + $rv =~ s/(?<=[?&])language=[\w-]+(&|$)// if $rv and $params->{remove_language}; + return $rv // $fallback; +} + +1; + +=head1 AUTHOR + + Marcel de Rooy, Rijksmuseum Amsterdam, The Netherlands + Koha development team + +=cut diff --git a/t/Koha/Util/localReferer.t b/t/Koha/Util/localReferer.t new file mode 100644 index 00000000000..a1d860dea45 --- /dev/null +++ b/t/Koha/Util/localReferer.t @@ -0,0 +1,60 @@ +use Modern::Perl; + +use Test::More tests => 1; +use Test::MockObject; + +use t::lib::Mocks; +use Koha::Util; + +subtest 'Tests for localReferer' => sub { + plan tests => 10; + + my ( $referer, $base ); + my $cgi = Test::MockObject->new; + $cgi->mock( 'referer', sub { $referer } ); + $cgi->mock( 'url', sub { $base } ); # base for [opac-]changelanguage + + # Start with filled OPACBaseIRL + t::lib::Mocks::mock_preference('OPACBaseURL', 'https://koha.nl' ); + $referer = 'https://somewhere.com/myscript'; + is( Koha::Util::localReferer($cgi), '/', 'External referer' ); + + my $search = '/cgi-bin/koha/opac-search.pl?q=perl'; + $referer = "https://koha.nl$search"; + is( Koha::Util::localReferer($cgi), $search, 'opac-search' ); + + $referer = 'https://koha.nl/custom/stuff'; + is( Koha::Util::localReferer($cgi), '/', 'custom url' ); + + # trailing backslash + t::lib::Mocks::mock_preference('OPACBaseURL', 'http://koha.nl/' ); + $referer = "http://koha.nl$search"; + is( Koha::Util::localReferer($cgi), $search, 'opac-search, trailing backslash' ); + + # no OPACBaseURL + t::lib::Mocks::mock_preference('OPACBaseURL', ''); + $referer = 'https://somewhere.com/myscript'; + $base = 'http://koha.nl'; + is( Koha::Util::localReferer($cgi), '/', 'no opacbaseurl, external' ); + + $referer = "https://koha.nl$search"; + $base = 'https://koha.nl'; + is( Koha::Util::localReferer($cgi), $search, 'no opacbaseurl, opac-search' ); + $base = 'http://koha.nl'; + is( Koha::Util::localReferer($cgi), $search, 'no opacbaseurl, opac-search, protocol diff' ); + + # base contains https, referer http (this should be very unusual) + # test parameters remove_language. staff + t::lib::Mocks::mock_preference('staffClientBaseURL', '' ); + $search = '/cgi-bin/koha/catalogue/search.pl?q=perl'; # staff + $referer = "http://koha.nl:8080$search&language=zz-ZZ&debug=1"; + $base = 'https://koha.nl:8080'; + is( Koha::Util::localReferer($cgi, { remove_language => 1, staff => 1 }), $search.'&debug=1', 'no baseurl, staff search, protocol diff (base https)' ); + + # custom script, test fallback parameter + $referer = 'https://koha.nl/custom/stuff'; + $base = 'https://koha.nl'; + is( Koha::Util::localReferer($cgi, { fallback => 'ZZZ' }), 'ZZZ', 'no opacbaseurl, custom url, test fallback' ); + $base = 'http://koha.nl'; + is( Koha::Util::localReferer($cgi), '/', 'no opacbaseurl, custom url, protocol diff' ); +};