From 6f45b92ac5f14723a59b1891e6ec24cd1a3830b4 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Feb 16 2017 21:26:42 +0000
Subject: [PATCH 1/3] fixEncodingRecurse function


---

diff --git a/koji/__init__.py b/koji/__init__.py
index 95bd44c..a8730e6 100644
--- a/koji/__init__.py
+++ b/koji/__init__.py
@@ -2870,6 +2870,37 @@ def fixEncoding(value, fallback='iso8859-15'):
         except UnicodeDecodeError:
             return value.decode(fallback).encode('utf8')
 
+
+def fixEncodingRecurse(value, fallback='iso8859-15'):
+    """Recursively fix string encoding in an object
+
+    Similar behavior to fixEncoding, but recursive
+    """
+    if isinstance(value, tuple):
+        return tuple([fixEncodingRecurse(x) for x in value])
+    elif isinstance(value, list):
+        return list([fixEncodingRecurse(x) for x in value])
+    elif isinstance(value, dict):
+        ret = {}
+        for k in value:
+            v = fixEncodingRecurse(value[k])
+            k = fixEncodingRecurse(k)
+            ret[k] = v
+        return ret
+    elif isinstance(value, unicode):
+        return value.encode('utf8')
+    elif isinstance(value, str):
+        # value is a str, but may be encoded in utf8 or some
+        # other non-ascii charset.  Try to verify it's utf8, and if not,
+        # decode it using the fallback encoding.
+        try:
+            return value.decode('utf8').encode('utf8')
+        except UnicodeDecodeError, err:
+            return value.decode(fallback).encode('utf8')
+    else:
+        return value
+
+
 def add_file_logger(logger, fn):
     if not os.path.exists(fn):
         try:

From e10d2ddccb282053225b24b38e37bf25aa93d6b5 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Feb 16 2017 21:26:42 +0000
Subject: [PATCH 2/3] fix encoding of loaded json data


---

diff --git a/hub/kojihub.py b/hub/kojihub.py
index c8fe355..dfc76e8 100644
--- a/hub/kojihub.py
+++ b/hub/kojihub.py
@@ -7297,7 +7297,7 @@ def parse_json(value, desc=None, errstr=None):
     if value is None:
         return value
     try:
-        return json.loads(value)
+        return koji.fixEncodingRecurse(json.loads(value))
     except Exception:
         if errstr is None:
             if desc is None:

From c59333ab701ff6b654a9dbe19359f25de464d480 Mon Sep 17 00:00:00 2001
From: Mike McLean <mikem@redhat.com>
Date: Feb 16 2017 21:26:42 +0000
Subject: [PATCH 3/3] test cases for fixEncoding


---

diff --git a/tests/test_fixEncoding.py b/tests/test_fixEncoding.py
new file mode 100644
index 0000000..ed5c2d6
--- /dev/null
+++ b/tests/test_fixEncoding.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+# coding=utf-8
+
+"""Test the __init__.py module"""
+
+import koji
+import unittest
+
+class FixEncodingTestCase(unittest.TestCase):
+    """Main test case container"""
+
+    simple_values = [
+        # [ value, fixed ]
+        ['', ''],
+        [u'', ''],
+        [u'góðan daginn', 'g\xc3\xb3\xc3\xb0an daginn'],
+        [u'hej', 'hej'],
+        [u'zdravstvuite', 'zdravstvuite'],
+        [u'céad míle fáilte', 'c\xc3\xa9ad m\xc3\xadle f\xc3\xa1ilte'],
+        [u'dobrý den', 'dobr\xc3\xbd den'],
+        [u'hylô', 'hyl\xc3\xb4'],
+        [u'jó napot', 'j\xc3\xb3 napot'],
+        [u'tervehdys', 'tervehdys'],
+        [u'olá', 'ol\xc3\xa1'],
+        [u'grüezi', 'gr\xc3\xbcezi'],
+        [u'dobre dan', 'dobre dan'],
+        [u'hello', 'hello'],
+        [u'bună ziua', 'bun\xc4\x83 ziua'],
+        [u'こんにちは', '\xe3\x81\x93\xe3\x82\x93\xe3\x81\xab\xe3\x81\xa1\xe3\x81\xaf'],
+        [u'你好', '\xe4\xbd\xa0\xe5\xa5\xbd'],
+        [u'नमस्कार', '\xe0\xa4\xa8\xe0\xa4\xae\xe0\xa4\xb8\xe0\xa5\x8d\xe0\xa4\x95\xe0\xa4\xbe\xe0\xa4\xb0'],
+        [u'안녕하세요', '\xec\x95\x88\xeb\x85\x95\xed\x95\x98\xec\x84\xb8\xec\x9a\x94'],
+    ]
+
+    def test_fixEncoding(self):
+        """Test the fixEncoding function"""
+        for a, b in self.simple_values:
+            self.assertEqual(koji.fixEncoding(a), b)
+
+    complex_values = [
+        # [ value, fixed ]
+        [{}, {}],
+        [(), ()],
+        [None, None],
+        [[], []],
+        [{u'a': 'a' , 'b' : {'c': u'c'}},
+         { 'a': 'a' , 'b' : {'c':  'c'}}],
+    ]
+
+    def test_fixEncodingRecurse(self):
+        """Test the fixEncodingRecurse function"""
+        for a, b in self.simple_values:
+            self.assertEqual(koji.fixEncoding(a), b)
+        for a, b in self.complex_values:
+            self.assertEqual(koji.fixEncodingRecurse(a), b)
+
+
+if __name__ == '__main__':
+    unittest.main()

