--- /dev/null
+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
--- /dev/null
+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' );
+};