From 088e1bcf0c2d6595b838b2e77b6b1060a237acd1 Mon Sep 17 00:00:00 2001
From: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
Date: Wed, 17 Jun 2020 09:43:40 +0200
Subject: [PATCH] Bug 25774: Handle utf8 chars in REST API queries
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

We must utf8 encode the string before json decoding it.

Test plan:
Use "❤" and play with the library search (bug 25288) and Postman to
generate queries using it.

This patch prevents 500:
[2020/06/16 14:11:37] [ERROR] GET /api/v1/libraries: unhandled exception (Mojo::Exception)<<Wide character in subroutine entry at /kohadevbox/koha/Koha/REST/Plugin/Objects.pm line 107.>> Koha::REST::Plugin::Exceptions::__ANON__ /kohadevbox/koha/Koha/REST/Plugin/Exceptions.pm (73)
---
 Koha/REST/Plugin/Objects.pm               |  7 ++++---
 t/db_dependent/Koha/REST/Plugin/Objects.t | 24 +++++++++++++++++++++--
 2 files changed, 26 insertions(+), 5 deletions(-)

diff --git a/Koha/REST/Plugin/Objects.pm b/Koha/REST/Plugin/Objects.pm
index 81cc97633c..f4e8be227f 100644
--- a/Koha/REST/Plugin/Objects.pm
+++ b/Koha/REST/Plugin/Objects.pm
@@ -19,7 +19,7 @@ use Modern::Perl;
 
 use Mojo::Base 'Mojolicious::Plugin';
 
-use JSON qw(decode_json);
+use JSON;
 
 =head1 NAME
 
@@ -104,8 +104,9 @@ sub register {
                 my @query_params_array;
                 my $query_params;
                 push @query_params_array, $reserved_params->{query} if defined $reserved_params->{query};
-                push @query_params_array, decode_json($reserved_params->{q}) if defined $reserved_params->{q};
-                push @query_params_array, decode_json($reserved_params->{'x-koha-query'}) if defined $reserved_params->{'x-koha-query'};
+                my $json = JSON->new;
+                push @query_params_array, $json->decode($reserved_params->{q}) if defined $reserved_params->{q};
+                push @query_params_array, $json->decode($reserved_params->{'x-koha-query'}) if defined $reserved_params->{'x-koha-query'};
 
                 if(scalar(@query_params_array) > 1) {
                     $query_params = {'-and' => \@query_params_array};
diff --git a/t/db_dependent/Koha/REST/Plugin/Objects.t b/t/db_dependent/Koha/REST/Plugin/Objects.t
index 1d726ce708..5a2b207c64 100644
--- a/t/db_dependent/Koha/REST/Plugin/Objects.t
+++ b/t/db_dependent/Koha/REST/Plugin/Objects.t
@@ -77,7 +77,7 @@ get '/biblios' => sub {
 
 
 # The tests
-use Test::More tests => 9;
+use Test::More tests => 10;
 use Test::Mojo;
 
 use t::lib::TestBuilder;
@@ -206,6 +206,26 @@ subtest 'objects.search helper, sorting on mapped column' => sub {
     $schema->storage->txn_rollback;
 };
 
+subtest 'objects.search helper, encoding' => sub {
+
+    plan tests => 5;
+
+    $schema->storage->txn_begin;
+
+    Koha::Cities->delete;
+
+    $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'A', city_country => 'Argentina' } });
+    $builder->build_object({ class => 'Koha::Cities', value => { city_name => 'B', city_country => '❤Argentina❤' } });
+
+    $t->get_ok('/cities?q={"country": "❤Argentina❤"}')
+      ->status_is(200)
+      ->json_has('/0')
+      ->json_hasnt('/1')
+      ->json_is('/0/name' => 'B');
+
+    $schema->storage->txn_rollback;
+};
+
 subtest 'objects.search helper, embed' => sub {
 
     plan tests => 2;
@@ -363,4 +383,4 @@ subtest 'object.search helper order by embedded columns' => sub {
       ->json_is('/biblios/1/biblio_id' => $biblio1->biblionumber, 'Biblio 1 should be second');
 
     $schema->storage->txn_begin;
-}
\ No newline at end of file
+}
-- 
2.20.1