Commits

Erik Svensson committed 371dd51

Fixed add_torrent used with base64 encoded torrent data. Issue #46.
Changed torrent id handling for torrent_get, torrents_get.

Comments (0)

Files changed (5)

 # 2008-12, Erik Svensson <erik.public@gmail.com>
 # Licensed under the MIT license.
 
-import sys, os, os.path, base64
+import os
 import unittest
+import base64
 
 from six import iteritems, string_types, PY3
 
 
     def testAddTorrent(self):
         data_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'data')
+
+        tc = createClient(test_name='add_torrent_base64')
+        torrent_path = os.path.join(data_path, 'ubuntu-12.04.2-alternate-amd64.iso.torrent')
+        data = open(torrent_path, 'rb').read()
+        data_b64 = base64.b64encode(data).decode('utf-8')
+        r = tc.add_torrent(data_b64)
+        self.assertEqual(r.id, 0)
+        self.assertEqual(r.hashString, 'a21c45469c565f3fb9595e4e9707e6e9d45abca6')
+        self.assertEqual(r.name, 'ubuntu-12.04.2-alternate-amd64.iso')
+
         tc = createClient(test_name='adduri')
+        self.assertRaises(ValueError, tc.add_torrent, None)
 
         r = tc.add_torrent('torrent.txt', paused=False, download_dir='/var/downloads', peer_limit=1)
         self.assertEqual(r.id, 0)
             else:
                 self.fail("Unknown torrent")
 
+    def testParseId(self):
+        from transmissionrpc.client import parse_torrent_id
+        self.assertEqual(parse_torrent_id(None), None)
+        self.assertEqual(parse_torrent_id(10), 10)
+        self.assertEqual(parse_torrent_id(10.0), 10)
+        self.assertEqual(parse_torrent_id(10.5), None)
+        self.assertEqual(parse_torrent_id("10"), 10)
+        self.assertEqual(parse_torrent_id("A"), "A")
+        self.assertEqual(parse_torrent_id("a21c45469c565f3fb9595e4e9707e6e9d45abca6"), "a21c45469c565f3fb9595e4e9707e6e9d45abca6")
+        self.assertEqual(parse_torrent_id("T"), None)
+        self.assertEqual(parse_torrent_id([10]), None)
+        self.assertEqual(parse_torrent_id((10, 11)), None)
+        self.assertEqual(parse_torrent_id({10: 10}), None)
+
+    def testParseIds(self):
+        from transmissionrpc.client import parse_torrent_ids
+        self.assertEqual(parse_torrent_ids(None), [])
+        self.assertEqual(parse_torrent_ids(10), [10])
+        self.assertEqual(parse_torrent_ids(10.0), [10])
+        self.assertEqual(parse_torrent_ids("10"), [10])
+        self.assertEqual(parse_torrent_ids("A"), ["A"])
+        self.assertEqual(parse_torrent_ids("a21c45469c565f3fb9595e4e9707e6e9d45abca6"), ["a21c45469c565f3fb9595e4e9707e6e9d45abca6"])
+        self.assertEqual(parse_torrent_ids(",, "), [])
+        self.assertEqual(parse_torrent_ids("1,2,3"), [1,2,3])
+        self.assertEqual(parse_torrent_ids("1:3"), [1,2,3])
+        self.assertRaises(ValueError, parse_torrent_ids, "A:3")
+        self.assertRaises(ValueError, parse_torrent_ids, "T")
+        self.assertEqual(parse_torrent_ids([10]), [10])
+        self.assertEqual(parse_torrent_ids((10, 11)), [10, 11])
+        self.assertRaises(ValueError, parse_torrent_ids, {10: 10})
+
 def suite():
     suite = unittest.TestLoader().loadTestsFromTestCase(ClientTest)
     return suite

test/data/add_torrent_base64.json

+{
+"test sequence":
+    [
+        {
+            "request": {"tag": 0, "method": "session-get", "arguments": {}},
+            "response": {
+                "tag": 0, 
+                "arguments": {
+                    "alt-speed-time-end": 1020, 
+                    "alt-speed-time-begin": 540, 
+                    "speed-limit-up-enabled": true, 
+                    "rename-partial-files": true, 
+                    "seedRatioLimited": true, 
+                    "peer-limit-per-torrent": 60, 
+                    "incomplete-dir": "/var/incomplete", 
+                    "rpc-version": 8, 
+                    "blocklist-enabled": false, 
+                    "speed-limit-down-enabled": true, 
+                    "seedRatioLimit": 1.0, 
+                    "encryption": "preferred", 
+                    "alt-speed-down": 50, 
+                    "download-dir": "/var/torrents", 
+                    "alt-speed-enabled": false, 
+                    "version": "1.92", 
+                    "blocklist-size": 0, 
+                    "dht-enabled": true, 
+                    "peer-limit-global": 240, 
+                    "alt-speed-time-day": 127, 
+                    "alt-speed-up": 50, 
+                    "peer-port-random-on-start": 0, 
+                    "rpc-version-minimum": 1, 
+                    "peer-port": 51413, 
+                    "port-forwarding-enabled": true, 
+                    "speed-limit-up": 500, 
+                    "speed-limit-down": 500, 
+                    "alt-speed-time-enabled": false, 
+                    "config-dir": "/etc/transmission-daemon", 
+                    "incomplete-dir-enabled": false, 
+                    "pex-enabled": true
+                }, 
+                "result": "success"
+            }
+        },
+        {
+            "request": {"tag": 1, "method": "torrent-add", "arguments": {"metainfo": "ZDg6YW5ub3VuY2UzOTpodHRwOi8vdG9ycmVudC51YnVudHUuY29tOjY5NjkvYW5ub3VuY2UxMzphbm5vdW5jZS1saXN0bGwzOTpodHRwOi8vdG9ycmVudC51YnVudHUuY29tOjY5NjkvYW5ub3VuY2VlbDQ0Omh0dHA6Ly9pcHY2LnRvcnJlbnQudWJ1bnR1LmNvbTo2OTY5L2Fubm91bmNlZWU3OmNvbW1lbnQyOTpVYnVudHUgQ0QgcmVsZWFzZXMudWJ1bnR1LmNvbTEzOmNyZWF0aW9uIGRhdGVpMTM2MDg2MTc2M2U0OmluZm9kNjpsZW5ndGhpNzM5MjQ2MDgwZTQ6bmFtZTM0OnVidW50dS0xMi4wNC4yLWFsdGVybmF0ZS1hbWQ2NC5pc28xMjpwaWVjZSBsZW5ndGhpNTI0Mjg4ZTY6cGllY2VzMjgyMDA6b1sWIkCwfFPZKDXGu64LEFwHwwjRxjOwFaxDob90QfucJn1/675dX+lbmNEVUtd0j249Y9qNUWJwTacjADGWZ7P0WJlR7CHmo4VnnUXTPxPkyUV3uvQSbDVKBU9LXRTIEvxjASXSGXQFCknTIoSrYPwvbf96IDid2vuDVDczs1mNmsDTf24Oxg9ytf7oK1Xgi/iiiQ/GrCXdl+2F5s3o8NW8vFbu1DKl4fFaoCvAIMd1fQ0SKCKaqt9mxFPBvLeSvB/sIjMjMgl03saWAu/gOmf9QEw5skXB5P5wcrGoSoMnaUkBtPSzxmA6Maw0Yq3zFNQNDJP05/tJe0uat7483+p3yO7gssbYgITSLyj3DqRjSMCEt783XStms9nSpySLdlZpLsZTR9XDiO86rmZbwcdxWDA1BWOe89NdwZjjL5GV4uA/MfOt0bWBqJNR8LRQKf+BVGFKdZvfX1UVWOjcLFbPYCecbV+NXbr1PLO3i8aoZVCu8aMNYy97J/+2wI0PXHj+L5aNnfhqX1Rs9yeYlQw6XBEoEu3kgSd3ULrh94i5q+LJs48AP5omlgGZZ9j4e6IrqDOuvnuJ8s7EF2aveAiPJFYK0mL/aRr9lHxF6TZe3dlHMbNP1CkruuTTI0ja4L17xmO+XERfTZFa/qfmUauS5Z4OrQtTeF/4pVOqcUOXyV60i90g4t4HDsoOZibgd8bBnEpZ/Amiygpmn/p1hCSk/K7FFj7F649TN55skNx2bNlQGZ80pnBMr6jEFYqJnmQ82cdL539MqwPnKSOGF7CZXrf6EEPECnQQrquHz5QZPQaE6/MDqWMaSgL88bYGDzaLEC0x8G9v7qGTH9LXG2wVUWG5Bm052ToQvglz5uDCkO5ovXh4u1W4xAaOhgLC+CVsOFPYr1WvlqzS4NUgGuGC460dDVSZ7DZ2bzCt9MQO09Mr3re+uTqT9o3TfVO/24yb0G9JRkBtV/niSnwsejMATg0sEs+wfkajLvBYrA8Wkk6DwnGTUWfVxDZZXYiXOh+WbjnOTurecjlQlmGzmXv66Rz2MK/2vvd2Jp271wkf5QqTJxZFv6xXegxY0UZsIW8hYASFSq0eJSgdibUX9pwTNBcjJOnEDo9CgWiLv04ZF1XMu2uSNUGhX7I/tfMdN9qTrjr5c+97O+lQnrRacWzlt0Ub83gY9mPA6lxAucovcrvi1abwKCZIeCISbcgdDQxyuTnRThX3WvjCPSkzzYevHWaMYSMTZmh2kx+DydaPgv1oaP/esCrmEN8Bag07l/y+9D/2K/V1R82oSc9LS2KiLsl9l1ongV0PWaieq8tlGVMdVPT5P+Qlfrsj22xPlwhXsEYjhMbLUcX+spEgL8tBwtynREt2UC1vgBt1YmwgbMCwYNHpohPLgkmXDkZRCEAGt7+0PgHp0/KW7y1Hv+5hNINWJjZFh7DaqQdSyAp/J7SbeTLgm/hq2lBo24BjritysAOmZsCXa1P/VbNZMItvz63lOLqIkp71WI4F/a0bthCAA+qeaILNCxruJiasTtfR0L9jnV8/FNghD1BM7xI9RqmNZL+euvRL/IVWPg8tmMSfJntCIBXRFEX7Wz9s+pyCX8x5avVUyH2pTbhS3RRd1F+Nk6rz/XUZF2wlYLSxvzHOJZdeLzZcEtbm2xu+YZDwHcriUFdkgTbtvqNnDnx5dGtUJpUXm+LcwU0x9nGRIZW2bTz35QbC+A1k/ktxvJS1DHTh0EBqc0WNCRJf9D5m/UWEUSrAu6DT9cEyPQRAD5+MkZWlaAZtY6+VcBaSfszCzqd4sSNvTdGsH4x7ejtYjci//acAoQOWzKKE64wBLQdvNeK2Y7xQr/syJzx/+25F1lXsYdFuphoHDx3NQ7xN6tTNg/4TJVYJYLm2XjPx6687pTz82zhHoPIqZxGdrsnBZAyoWK3SWhu/LLwcophSpW4arMebXf/oCP5H4o/RVDENZjGYwFhfoltUh68/fhBzIQYRgZcLvNE1kqNqiu5f4F4ickccxhoRcyPVF3wzYu/kt5wBB216AzkwNPiaRfvilNvnJ5KbSNyBJWA0rENb0FUKz7mGZTB/enuJQSMOZZe3VfyZotOH/9VUW8z7IJfGeCcDbqWw2vH4RYBDAvLwmf4HUeYkAiNTbRzjZr0dg3Oatxq/fSnp/xi/qEAGwH5quICDrXmtngFZdTKdEKvrVKRT2YaU1yN1b/WAa++9ncGDkCteBuvz6VCnSMpvjBoW1hTAJU2eRcbAfRSjbmWxVHvm3GdSBuNWZBD2upaYvqEuFo9nOartRLrttz8DRZK4aEf1NBinZ5luyWHeXRBrQ8iqG+lsBPnX/XQuaPII75DNzy9nAD/Pkv31oi6NJszpfRM6XXcyoZPnEi/LH8dc25QCoSMTp0GsfeYxdji+SzlmcuMcoS8pKjsAlhc+FaC9siiG2uJm3sP1g6LfDEK/DLowquZn/+FqnyYooieal3W5KxF5L1WFR56iz/q8HK4l9OiWhp1xREiS4k5Tm3ypRueaa8+FvCRHZkONBydTQAZGMMihteKijIm8P5ID8wL8434NPYnRvNlcmNO6dzjr9T8DDrovaDtziagSWNXCc7ifcW+2B2ypjLJX5AaJAZ0+toSlXD+3Y7WmrRm+G30Q6Bn0SJG0RyKlcS/jN6hZXKVnMjJop70NNPfemlZ57Q4NRgndRX6g9BDcH07YYvL7wQpEcpJPHDXQ9fMxoRAmHb7XfpysDPv/HakR079lW6lDMUw7rbkWP28dTTD1xWm0AQX5xnBlkPsqIo50D6u/r7lTsHEKFwXxEJ886Ofu5yIJMQEqRzzneVs36hvnvenYKVcYk7rcFTLrZfa7VqjcQSRjPolJOISoI1CG20sAJf/1K5wMbrQInn6z3MsBeUFzi3MH7MwQXcv3R4mSClpvO5AaFU8gX2zzD2XYuLOMHJlknIgSuBTheCHPkg9Jm0hPWE65XE0oZHkLgG8JawM3+9xn5qnBii1AuJzZKAioLr51PCVS3CIyHZBo0eZJPeyqGxYZz7JtfixIEbYilK4BGUB6d2Bnh/yf60MFR166Y0866sXqvUDRtrBRjtN+eBZWuzEjFWDxw383jxa77ME0YV13h8edyEnJT6F/fmo6wxc+XNjlWaoMKUwgAfA/RIcc6PjRUZBpezYSrHvoO8a/kLN0p9ulG+IQrY8rdvss7qk6J3aduCDyw+i1qQ/mUnGN6YWI6/YDQxbT6I8rJekKE6pR9owM91Ued04Jf8NEOHnhpzj7mx5dkZmQp7Q5HhQjBCw5wtaD/lHXEPw8eyLX5tpPAHNOZw+JVoM+FjRDko+xVPSEWLavKp9xQdvUUCF+6mvsDoAWSnOuYVSxSFbKvQS6ykgI7yQaSS6w/nAgjfqzdPyUwZj6FGKf/CMxRWOijuNtdd1w9ZtxRQAYKv2SkNDJlZ8lmIacgf3kFDjRop5ZJnH+2JsD3Pvgc/YVCDvouNPY22+XUA5SBXBp9AWtFMxLecUjUtY0uKJ7AeEvuA7SdiqB980fNeu3wbEqZ7PhOk1yJBpO9VQyIucRbAw6FLPv4mOWVhLDa5TnbOd4bUa8dUagpnW1sAuoz+WfWrPm/F6wNTftWy3UnUjcu7R7IjwL2gl0l6aUISrEh1cYXCLkXSCazzfnG/pxltzIYOiBKdunxp5s10JcA/KUFF7loND9V9FUp9qZwzM+LqfivzbriCYMu0/xzPJUqGIfUuTIRFl1TjL5WNdJrTbGIybJXtaILMYlRXQwJlrKahcNsCIkgPAtCaA9W/Q9RZfPxxuf/o9s/H6UHut2VJJwYSqrU6wjPH+qP47YYDqwZCkAt7m1hw4A8sY4gcF+urA4lYgrvLbNLCquxMDzZ+keFjm9R+91wKsveG1IXSZtFN1KmhfhzDhR9buvlNH3CL81/aFq3uC7HnqvPcX3z1Z+Dp6WFrWA5ub9UIAbMQ1hKp2xkSKIbMOxUJTrGz2RPBUKb8UXoX0e8MBI+/t2H8KjGODbLZfsoZpVz/TGhGV8jDDJBsizhuMuK9DcKhzxY4pYBbwhk2B5vIeajLpieVdhjiq06GODjD3nKiOTfpvdjg5GqIVyxKBjLjmgzj9Q1DTEKgzvJELn42iIxfdoX8BkY50Q4MGwpwRDA8zusyLy5jPR/IjJUUwDCSnZ+CIjYTPTRL0ZANztVdJxIL1uo5BmpcNTcneQ7kmQc56C/Uu0SWOxnoj9NPrjpJv0yFLeuXEqVAwiu9w2k11OJkpSgkzhPUmuojro6Us064CsWHi2wQItnB1faMydSPUCfMD10i0l4kWi1be3TMx1gPSOCRXZKTp+OStVxzGHi+10mMvHLUlhMA2vm7IJlodZ/Jzp71NTlCyXuDtTpCS8GD//N/NnMbGXnQ/c2mVcQNzeHvzZICAy5aR/KMdHO8gu1rzoN/LqIXCwsg334yT/yviCGWzqiB91WmZLoo172R5sB/2It4q0DIJ+EA5GGmqklgNpRbhSb4kSijLAKbKIhX1As4QD4nAy1YiU7Nmi+utEnjfLCPH6/UsQPl7ZbdwF99eH79AlXqhGt9L5Fw2/8B6nGz1BrEz+l/1fZfZkqsVLc10xqqBxOuMSqhFH/a/CdHordXqSggC0l4HLOweKQiSPgvfouTsUBSkt9g3QHhFDsPPNCJAGPYU75GI06gTpgPIPUhv66Gw/3VlmMnWoW0mqYXYtDVO7qVrc0Rd2Iy5B+GyYMiVRa8C6XII8pRCEAowaJeFO4cf9PT9u1lG16kP0ZbmgzoyRd1bD5N2Uxj20v2knMereV68ILJ48FlS3RkMUhcf77t86jJce63N660HtD6kdyZJCVYOey3X3szXfo/CdRKx8rCvd9QhL+KewWA0VjOkNFK6g2YjHIzeBLiPH+XhWjB4gVaWjxxUdxnkgZ+pE3Aj+FFFD1j+uMkG55GCEd2PwzZI3l6TH9IWEQeByQz769Y/e2Gfy51HXNWkzSVz3gRrVYNH8RL+0jbotnvppChw34taf7WJBUIp/bkBH1MUCkryiG7E+DMXzN1MlJ/UU7ESo05YP8+DTZDmxP2yjiEbQ3fL4Hq81wmAnYVV8JVoYZCGYDMWunUsGtd1GopMDCVZeXPSs6H6saynrBqoEN7PjgEa92wxbYnQIyl1XTA6ym7G1M1+RxR6pU6ryKlB6/KV0rOykVQkgwCmrDmeD73Gu8pYDOp0V8rd6xXp6I7EiM+IRkaNw1OXLNrqVOmnbsbs+4spgEeqfUClFLLZcvlCLu8IMMb5mcSE3O5xKDEhYms+WIl4gholO3zUktNsfFgVAXJxwPe+y6FJNET4Q8g9PCokhoyU//lqVNCiy937wMxxNKeNtwEHXHBohwyZazNIt9RmOX9NJQXKeCUA50ZWlqIAAK5IYgZ9f2X1gBf/T45ZbzAlyg6w/6IcqzOhKEaDmckD/l08VPvgopsoo7FIAkjss6vqwOY+4EMJXvLFfioR6Vpojoj0+G2Uxj92FcxQ8G6OG0s0NBQSZ1r+tD2yyefWC66laGcmPFzhiZHIQfC9CpFTjuxR0Gnsa2hw1gaTGcCa7SEI2+/L+gRpjg1FBwGb7wV7e8kHKQw+juIZEgJVmzyfgFafgfgPpTjogMQBLY+0jLvnDcRcXSuU0fXFRA2jKNXGLA6oULuZAkdYZ0gWJNX0tr6gvLQSJzXHKcaMJO8lFmVmj48IeL/OY8VGuxc/IVnpmhz7HGaw+I/uA5mp6x2CefR0T/Fj0ZavkMBMwdsI1xgD2M4cv99ObpvEk/w9x1M/AfsjW8lRkDtQPqJYvRimfPyTbGhcfjaMvv5Bdua5qoylFtLI3w/yfCf6ZfyXU4LQd93G0QlBnhN5FTCxyOmOw0Z4yfVuerz9Nvz7DI3CZwlRdAf989F34vCYJWiCDJHBynvfW6bWLTgztFQLZNUqKbW4sbnSK1ijJofbnNNmC8rDtDgV8oXrCL/zLwUFkPbJJ8rVdUAPoZFCGCAAFGVME1364XO4TreCJBydLm4/qctEJ8DAogKBij8m22PGepjyvD+ZR3MEzgrE0d9gF/RdP3HQna8HRxu/rDqDkbKwJLGjd/GanbmxdRmGGL2VtzxksDGMFTq5oQveg/FTwkKvYGG3FmpjQujjTx7u303D6VKUl66yzPwX8ZE9U2vOMfZe+MpgHbtCwQGNpNfGTiqqZp27KYDgfeUcn445Xrp4aBDRu2aFuwp44DPAZmZ0s3M0CaeSHsGWzsmuBYGWBj4TELYnyksfyTh3FK3AWhvWOTaDFTkNuhrAk/hvctpv6B7vUI4Udc3X9APP/N58DpihfkfGIsAw/tEsxOBgRT9n7gq+6ghIkp5Olm0NQnK5/UoaHpm85XijC5/PVEJBcS9QVZxyOrrnDNkaYUzVfa86J94fMJtDAZ0azIOca+S3QUO0/Wo0VwShTBFmjCSPN7NQTaufPfBQBTNk5r4vZkH6UFaiYp54WeSNxX+Rgxo2+3OyPWZd7N0G+SJ5FOTo+LBwyWEcRJ2E2l9jSMgeAvuwtiYevNLyZw3ThFV0FAzBaz1atsGqO+2g4LUx22wjG1LXYQhdutjX5CXrsF6+IByzbR5RnPEp1BtAqj41iwQ+/Yt5u3ncMkwfvBqVxfKta43qKqNQuN2HzbTfsrBMFvOncxDRRf1tlcLifJAr1+DGL30nNYYhAWhassQJQiM+K/7NlSQMCFb2BeCk/4U7HO2dR88pxHiAXCcLpObtJblS2Ty0ebKBMnPE0EuMenNtLf8vCOVW/EO0F2ANj35kPHqsxOQZFIo7TY1cCVeGui8WfUAaTizWgrldtYRQLuiPgtkUhAyJlnP7ov40T178/WMhsQcFqIjoSv8JY3IKJuKlpF9tETPG1/hL571t5eZmCMMAmk1F3Aal+KmBeBLIi83q7ITOPD99IYjZ1emh0QTSOf8kit9ReLOgPX3EL9gerq+SH9UmiQLkUSNJ88cdsK53+zbHFggCmluqVi1mOfc/eeb7WVdavHKlnE44mLzbdDjs/lqMOspsmDmB0pyP4GSf/mK+/DD5lD+cDGSHMeeD1fmRcoHaa7/v1Zue2hcR3Eyf8eX9nZI96szvz06RGE5T9VUpZmmQW88mriMZa3a5mezBzvuGAKjsZ88AFNwWcVOP9K7pnfFn6o/hapiLFUzwQmcV6HLxGEjtcV82l6qNZLsgA5x/GYJMogj5C1jsRtp7964qEz5O3WDXSYSnRuGoLoSk43qBkQkYvXPUA7SbLkJgpMj2lj/BnIdXZPrjn0+cK7CynJOKKuf8vae8XhKoE026v9idKqyGaQSgMIZ4VdRm667Gg4CVbue2NePPv2YTGp2xKAfC5Vds87DTAqJ9+XpDapOqjZy74czh6ln4UTnyZF6KgDeg1Ijmz7yoPcv7LfGFQeejuytf/yi9+Gl7x0mVfcdoI8L5pp6wIkVQbMPniFa9NEpNv0lw88eJv7tJpmwaCzX/L3xwtzPk+cOfzK7cUODIEX8YytWp0sjK+I1aMJAMXWsh1hZnKeSqdc/fRZ2mxa2SJ6aTYUlIvV7V+82IiZwrjlCMSuuXA5ua2fiQsWWxTOeQwudnQNj81SbwfAQSzVBZTbraH7ftQATCMnL6JD4nJR4mUA/tSfbjNRbYzLKYF+hXpVAde/UiL5J75Qo93b84Y+PDUnEJB7hiF4TmdgROh2zFHt0/A4p5AXzLa5vNE29GvjmV1EM5zdogds7gxAsIZlCMBjhVyANxckAJ/OywSWc8khdkLLpo8YQVItoIQhXtQ7N1lymNA0TyicF637ozoK6Y5G7zs4v4Zxu7tAhQetCi3St2ykXRXU83sFRD4vLJ9tP4UIf0wuq1L/0MqwqKVqZxwr6dTpgPYOucpVMR3Ot6KMukAlcttdLXciyYa22e5CPC87RZYi4Berf+Oudmk9/jMjoEQoJbSHtXrSVRoLZBFZI7srSthdGN56zD7I5Su13YhrbehbbUJdOFKdJD8Mxh8SulQWt6Dm9JwgrNgKurgsc6irYl4cJKrc3eKWWUT3UNvZoC73V+HfHkV4ud93y21UEbL0Gmq/BKFe75qVNAgkVTyGxAaqGaFRvg/DBioUMU/nqdfWOLRozXEbIoP4QpTfAMiTyroR6yofUNOraT2KwEN6l6Xq5/3y/+fX3g1Fv3hwlL8G7fRfVz83eZ16Pkn8U9E7/A+rLP0hnXaL1mydy+CR7FLiOJhjd5ZyFUI/P0UxIiSp9FEHg7035d1vn+C+pBi5d8XMdAQUlR2LUOkhKFacVK8rx3SJ8hZOvipOZM3bSfkxQMT0ieRRx0RQDFBaGW8P6ig8YpMnuW/15r6wWCFiCio5CUZKBaSnZBL2BzEW8ysFcRxJNVegVRK4Qy5aodpwLL9rKBKSUH+8UVlrDs2tnqVGNSmwXg4jDJsstGEy9y2LCrV7WUj4I2W9RO464qHV4ySMiqvz+Q2r8J3towrORix9e+rFjbjKIgfxRwkpoBs4Ub8uMnilDPmFQ9xNPIMUIrMlat7OcnJZtrZq3J0O/IJr+4+K1+sxCdq9bt+/yi3c+iiOIg+v8nDahRTOR9/AVYysmW92+BX2BaVt9sXMs7EpuzHy8GaHxBZ5P+I44+StA0MOTHMM5k9YHw+s+rcauM2xMXBRZzkPHBjhrnS1OTrStZo34W7xYGruD2EmJUWhpH+QuqJGf7ACH3hDM7XbQbuVvVtIMniDHdzANk82P0fAZ86II4OSROxT8BGAvuzF0LDG0vRl56e1TScGIb6wZzrWF8aZNaycp+LmVoPJKnrlGBpU7iSbBovzN3f0LmMPRbjv3pjuQoeqeOJmXaHTiRgQcxRX5vc4fpT1VORb5KGToMiO57qX2Nm3R1L7NtJ2YlTnOBbor4cM4PMPfYpKouu3QFKW25g6ZzjgL52YCQEDaORwK7nDroiaz/Wk4/lHWwWaCSN6PZ+Dlwx8YQ0tVhSsAmn5IvLhAmjyJVH808DjC1Hn57qfZMrO0dWX0i1CuI5Bj2Y6JidFpL/YbnXA9Fm7mjkeUdpgO9s11pcycPjndsxX43ip+FutG2gU+Sp/mYwd+f6zDNIRkYX2btsZcuvYCqkrGdbTTQze1O0brI6n+iaikpIseS9TYDEMfjmq4Q3E/Yr1NA1tnQyatE/eV/1OenJYX81DnlJT0a6ksnGWc19HgnZo7P/MWqcXLWj+3r6vVA10ZVPKgR/QSrxOWrFPf/88HxS3ce6YdLMNMk7bCjYFHWbe9BtQRy+3zb0gAxulxKXCgTPNpirpIfKXGgsiG3D67Ta+Q3OQMnG7iFC2Q5RBTc9nLOfsdu8UVDjKUFWkiOW9mWJWgn52tPpYRjBaFP053qn1GSrBKqH5KKpsf+CEQHTTdoZLvGiLTDJ0AojYuW0MyS5CcjnOnyNdS2A/n7IWnn23XMVDvrYECB/MOAHvDlqkwMd9sujR/+GW+i5RTpFwuX3ijr6YiqLIMsQtZCzmHcZdmEDsgEHYp6MWu0q+QCjuw4uBcnZcrjj0qZoAkSVIJsGUhiILj8xdMpa/8wHpBFH7+VAXShzQgtY0cn5+HXf4gc5/m13YR0zOCNsUHCUpkrt5ZizX6P5HV3mWbWbXMyDeX6mfchBchXYLd2LbcvpzyZbwFPygPjRp4I8Fd8ON6pb65cx+tVHm5wjP/ZmjOSognFO/fvmmaiIWqoK4detDdjezCKcG3EN1fO+zKOQ/Dc2gxSCLJlal5dv0UzkJqA4LsMA06NRgOx7wlF9vBJWTwxl13TFBiYODNGJsHHPpodMwfcVmfLTTEFX2dDDQu8JSWj/1MowGMpxdGIKOwX6Xoec8fOvmjxejSaFfvIv7HK6MHOaBKryfLg5gjqIbiQL1KZePPUPsuJLwSrlDyQDqmrlsARLSDGDcgKyxByStbzHeHjDG3VRfdu5L46LjzgxJQzxAbhrK+toNpEWzWpF9GKoydI/k8LKpf+LmEgFDrfZmjb25fXoRVsGQnb+VbmWDFQbkcxEuW1KhbSXDkFRVvzBmwug4meyodLs6OeJmwSKNQE8gXDjUrfhZHEADGTnYy9hkEe3EA4wUgqWUkOi9+nyn8x4uFBCYk1NEzrtaN+OszYje0VGumkcOG5pz4aB02dDfzCyZxLDZIu8DjihwlBmcrbcr9JTQ+2MEcLW8Fuqov2h8OPT/7CTBRrVZQ7nojWRA+XnnAsawwybXRK0xuPFhlW67om2Y96sCkR5Czo9gFCSUPeuVHDc9O7I8qx1qLtPZRzNIaMlkdYtSQIvsrkDclDxCniMhcQwuFH8akW5oT+df9Um6kuLrk+AmYmp7lBen45TssDW+9yRxXo0w3M+bHfdP7yEeGS3ofDF8XZOUotXlIH4rQPYkSHytYjOomUQf/JYxMo0e7/JkXYhy/OZO0U30zD/GNa/SHUCdUZ+zIkAi2ArQTrsJ5nuOX9pOZkqFZxU7DUd82XV8jKtkqYRGCJDRJcnzQVlGk2zacacDsov95uJD7z0qGjvDQOm27LKgfDjm71HyT9PieiB5ShxxWNQ2DHyCr/D2G9SwrGLEwxGUTUiLxsVR4G3d6yxaVd6HCmKSkZPN2+lE2newIBdtg04V8efY3VkIKsfWEk2n2XjUcdDTtNpM5Bk+GHKRT6fkCYrF83qsGJ9hPJN/cbEa2eEzMpC+1kIy/LXskBx6sEMd1PXzVSB9TMXctB+RjZWbF5TbK55ra1WI5b40IHCx9iguNvXQMXwp80t3fylL2kQ92TwZo0Lk0XreF7et6aJYLlKLSoOEcx94ZuNuGC/JNopzpBzfKZgFYpg6OHYk5emsWUwYlbwfdqn4NMkeQhT8HsKQjvkHql90hjl6gr0NXDctOGyvDRk4/ozwNUnFKPkwAH3tGeikEg1bYxINTiz7o7k8OMY8und2GJEzwjAAoynHeOewdbCHskgJcQ2OQ64Osg3YvSw5Wv94X8KlzY8dbDVB94SAlhaIYx2RY1xCt82G5efzqj30hZF6mkDCKKBG2Fa2q1lsCrGvcbfDHAUYkhtjLnhaty6EYYOnnGw/0jcJkUAGMAVU5yiiOHHB+ZAgMk+YBR5aJD/KGFf4dXuwmWIG/uJv+nG1QYH8CcbGHN+H6itklZsDXT1hyw3UU3YUldd5DKXRmMfKU9fTZNDDE0B/FAmJvpvPzBHFfbcz9h8+ri8LDXJNpLNBuqoJn6H3x+OB1loWx9Kbb1Cxgx/UkrQF6isjSM0/jwK5Y3iAymdZogd/0N+7UJKfAVWyzH7MRkUqMqndQyWb6tRaAOw3JwYQB12WjdOfqRh4AgyLQy7pNHzMzIl1Sn9Bh5oqduI537Dm0oHdAl7Te0Bmg0iILL+TQH8lDHvbpSxX2hS+OBG+hDg7gjATABVbFJB0Uh7hsyUqC9bszcyr9etDycJ35gfQ010+UNhEa1DGLb+Inw8HWjFj6oAtR7Ynf1pK3/b4T83Z6FZU6BoANzSEufU5vpWr9u30vY41GLbLCRVjm7i4LzpKVEuJ0fnlNuNM9uTsj4gRfaeFEJmv5RpIZQB/wYqBzQsWVsJ/1j1xnzw722xGP+c1hxmh9fO040i4oi6TMXZ2U9KkewYMZdQhl9Djyh4lS3qVnL8+1LqnVMObOxmu68gQXJvLPwmeEURaRYaFfGeG2YNa9iWPdlidPzcDJHjuylBZE2O6PJq1Lvr3Bu9sf/TSJZ/quL+HCZFwGe1RNMFnwUf924pgmPrsqSvylQ65CocF9yOl+1c7z7vESfyfXEWlW+iVygHdNrmigGqxv0yTgBGdYJWWbOdMu5MZM5QSY+E6rVNKMMePxlLynleJnkMO18bfBee5DleejvM8MWaSDwcAholtqlm756vVz8pEBebh6MKCNJKGNFpGbHOIUTDQxlAa6VTCzm6c/+cbSRvdPKJXDeWecw5RzYWjNFvzFkA1TajMRcRMxbn6OC/QopfCJum4PYr+48defPRWJqZPcpTPWtu5T7SdcJwqsF5Vz9OKdrElHmSc5/qACPMXBPMj6RLLRhPrq1lJBkIMPaQmOHyG6tlr0/jwvC6KXh38kt6lJqXB1V9wMDyjlpcakyQ8fl4JAZSmrY3FnS5wDyd36sZVAwYweyFJ7+NeAA9PajARBPLRGAXqrtyvdNrJXtYwvcwSBBFJiHOFPHpRkDbzr2LIxc08+JYjnBuH3VRX5zdCnGvjNpuesxvrUcK84sw5WYtUavjZnZE6nnfmZkHgy2gEOYh3nx8KTz68m/VLsrkvycxAJCHZEw6hwWcMxJguLNTZTQSLL44FC8/ELVmx1BxoE81NcmKGEJi2GEUqVUvqWHANTkS6Sx9tRytQWZbSWQgZGnPCLonvqZLqdP9pwfiM5sCX1sqXSvNozatmIud9pz2Ji2siXcG4QwNhUleiqisJdCx5JFwvanFXH6QFPUd4K4SmGhkefs3+o3PgTst8s9XIqPh3C4Z/qNWpwxcfZcjQNyNgC+EAkzx+M3+C8EVMDCkUi4gAL5RwT7nHHIKNb87Y1OkYdKYF4YJ+oZ5os6bYpMBM0+PIb/qUA4P9wrEZv9q/mbeK/1M4h49tqobMgFfbdCwmYmOO3G8wJ4VedEn0MpAADaA3o4m7C2h4Y9733Af7c+3ASBcfRQ9i1PbOYFsY8x+AoftGoBoTHfxEdRfxyh9BYWiHZu4rp2H09iYSEgU4inlr0xf4rvdqkztq8DnqixqUduujBBDLGiHDsWW3LA4E8T/48QeOqtosT8LMCxkpnFhexNYhNuyr0OVWez3ZS1qZz7O2UbC7XuSd9dEO+CQqQM6iPuyf0UBLO4kfdX19qi919UgrvR3Nn33DJ3zJTPuxO9Wv8QdATr1W4z/r0TXCUFlWqBF82EbGvmQ9fYttECpcsvUuxec3hPg2o6J9snYCe1kr6TqzXtMGSxOmiyhq149N/pw7DZG3YHGTeK140uXkVGvhTrrXRqgbhiW7xXGhg6xa9dO2AqS99rfVVZdnGM7YbXduXKtasXA29gmrpjAvNH2CL6Jl3nxGK7zJUIUspdcV4QRWzZaMcj0nn5ybW97H14lWtoAI51y84xjfYuhAipk+7cbvaeBDRm23I1ADr4ouVooCTLCjUYhrE4IbyU8negKQzUv5hfI/32cME1XwtcsRMjYg5LcAGXYpTT/8BQ46AlXTWqd6hGKKnK9YsLmH0DjgkM4/b8BymZu1hhqALX6xoqYGzB9BUKcPK90/1MYHnqi28ffbx7dqO+TH1HO9om9UoZ90M2pv4IGU7pOXp8KpVx4WkmK3TK3OJcLYrADNBMvf9c8C9uF1UHUAmwFJfx3IzCKRPcu78uHJly3ktwfLJ/GI6GOb+RUFJg1eRPRSSlFtDea8sfB4SKOp2NnOg2HdncgKUXs91SIUNvT2kkPdPpwUcH2pChniAbliEqdf2zbVFl0T4hOTHaPRvCql1B/TweDvsIkNYuGqLhaS8Yz81J37jvSOeXiA2dzUzNPUdNYsy2uUOlw4RrLToxSfiO2neVGaqfUFMxTVrT6c3CC78MYMImL/QHolD1SfcR9pahyXd0E9gyDkp6nnmvpp8OXdjkP2DWXXHYnQLoC2gMoLqc7wZgvKOhONpyJz5/83vJFVlHIJTZypxd2IuyeTJA/mZwi9mankg4UHzYlW0umZqx1bIqFw8KxaIcQBdPYRIppeN3bTBqkYRDRoQrmyb9bsAgNvLA3iuvakRi+vQoB1sQaz31vqMtGQOVz35RZtiG8BfosPzltqBQuaCy/CNOKfV1TbClmkkebL9+VQSq8XUokBtYep8UKTC7PDs7h3MJdL2FfYw1PfGIfe/1gF7uM2h33YjwtJiSdDoSVCVkkOYbMDi3/kVVjwG2RB+WpAwg0omJGX7QVAeVoOIHknL/kSz7qesTaBeFhTD0aGWIRALrpzytrJ44mflpGV3Cx/mKQ5AZNfbFrgJJ+bYdMZIjl1kPlKDQVTF/WmCr0sqrrIzjxvi1626+kUjUoEG4y1aqCmVnYLiF7ZJ34uyhgBb/dyPlnoMJ13wWy6JQDgJQzJ2YfqSk8g0C2hkFDUGKOq+lVlvEpkC4YqZejBjqnAKhirHu1Di0DDrMC4NcgoX2LBPTKoLAAe2788WhPNNEWsjiSB2JM7PoDz5XVvemZcjNnCIcKEodNlyTiEblHhUNwFeyBtf0uO24QYXMHL56pTYFgVIntQ1DtdS20MOwlSEuirvFVsllH2J7D0HKvM+9s6DRs4uQpDIRZQutul081a/XCejjTnqQC+9NPxVN+kmV5qHHCnu4+saw+P2bLfHpG/6kggi8nYjCmbXxLWHDgskOp1vi6dn7rX6xfBfGYY7271wnSXIycN4SOkr6AlKfdyllj2lCAHOjgYP/hqprScMIqcHHEHygygbnS+nsICOApCpzLanOvIew9GOOgSu2bhqJMJ/bhG6bn2TGh3VEssePPjzqJHFUYuCEMHHBcNdjUsW8nD6DbmMFfFxu0rBIftiaa7Ge5ad0TzelV+KAktVL40AoZA6zREJExVbq/fwg/6ux0HvAfaxcZ1VPLPif37gqFoZmeesmLMMEZU8W8J8fgHQ13nuetIDYWgpNgFX6Qrj1m5779J9RkODTqAhnInqbanPUSbckiPO8oqNstWpoLN0zzBlSL5lXdgFuiBODGI5SRNPUilaDl08VxxWCzzo3F05zrVccrTGvgWBUtEAdPUFSV5JiXBNY8Sn34vrtnCc4c/0OSCnPfsk8tVApKGVFF58Z54R7HBPZfQyGl8nBzYC/3NcH+i/b7LFdsjDoYsQClUI+ZpDjDI1IhwKh8vy8dsrVnEebA5rMlXVgrVBg5j2gpYAyh9y2JqR0rHE532mHSdvz27JjLBIssqczJU5KiKCjBjdEQN1+Tl95EkoB7ynZmE4E253ZB9iD6BhP0EpLLiRxMhc5kEWD8SnHGQUwThsMYpwAaMCcYFn/izLtDi9WaqS0ywVDMHujxsHaq7Qcg6qDyJK6qh34ctYoj64ePoEqjpcdw5f/TpLF0pLm8KQUK9TCWpI2GYWTMBJ/VRDvAssfnok+0mHaHcaA1kyDrTlgR2yfS5ccGSXiWR+0+vXwJduFu9prGIBBjN/LguMBzwqzxx7CpJtu30bAp3had/re4FyvuhWb45YrQ1izaRZmbJ1cJiu2xQh48rSOESz1j1Pp2RIe+65BYEta94wWNfaabOZFlMtXHs2dmdK58VzxgT06SjXKBlXochxoO2qGLCuDhWaaGTsSn/kRR+OhUJsJKKUWTNz+UJjim7rXuIkklUF1gphYPI4z62ii0d40p/2ZJyfTgf0KlohRCZ2uPMxuvJD5Kok2l8K+oXyjI/umOCYbJSSfmwuNLuW3Ve25G1rGg7uQZmN42F8xEe7OxKDzUwADZxIToBjNG/nXExAPKIVs3ldxxiv6CL/c1pJhPFRFlJytFsvx0XyYMZ5kdEPrDf/9cN8IwmhnolToSOkoyTrgsUpn6bGbluGVmAJ9ShpxdqUqXb3uoQmqDM/3btTjkfeC3j40AY5s093wl3paTioeO03xxVvJ3zepYT+dQzd/XPHR4JpezcVoHtezMPKgZ7Oxy28bWyD0M3lTNwKqZXBDzSAAFTVF6p8zGS3r2Ae8Vd+kIGUHS6tSMROnPrm0SGTQoNVSXLiVhfqiuselo9smijLD+d/EOQ9SbAUYiyvt4yym2vZRrzzst/KKzGu1Vx3Rm2r1csYJfxZVGilgdsnin8pWfizWlVlmIyLp22NDuK8F881Y/ADg/8TpyQL1hOGgrRwqGkuCwQgFNP9PQueVZ8GQ4v/q4nl7qnD1CXQEztJ6sYDBv2wZB3MbKstKcT2q8CJbo1u0l4Ueyi2diuioFKoH1lzw9VA5AU1BlSP/+84jOJUot+aNw5KGRtuCgErQygH9V/TzVYofIqvByu5t+fdMYJHdwgcY9/TIVoJQLKYKPZgTO6ULaE/txZbA3aLtb4obWztEc8XPWQ+cJbJwxJLs82sQZXoqnvRqaZqbhA8ABiXtr0zxjQcOgSdXvdWWA4kGDbHh8Ye3FHwW1Mj6ecSFVyyuuyv1SBG2xCwZNVlf3OKLg/ZRZG22wsnPCYBgtQ1yzApQCyIOXsuM0uX8kxUEbZWuqp7I19nhcbXw1vZpqGxH7m3KTZOmHuzuvplleLPWszMMgC01ZDMT2aQe6Q7ok4OOyaHbz48THFQ2apz7LZQekd1JWiGx6du7WcYz2HK3ro1iiHHmyrr0UPG2xqrD38YhmFi1NC5/POIYtpQAO/xUylgPc9zK3bF/p3O1YPF0mJlhvyfn/0jffYeWWRMqeti9R3bc1JSsD5IvTYdHF7H9SdoWUsiIQaMgf7XlCDCp1HlOt6xvvXk89us/CXP++Qbs+3xPRrDoKLuwN+miJLgL5bdvqDkSlpkji3oi+wqHuz/QHZ/Ji0YqcwVaysZpTLDeCIUrFvyPjPqPzNUUWf3PggwRNmjwHR8Zqydch1o4OHkHc+N9l+65WsUxfIuuEPla9H1Q5bP7P12ct9+Z6UQ6ks4is9XVz1x9zZ/mpFqtEa+6cBINUo1WLh42v07//HFgcCFoXZucn6xsgFZ3DXC1C9AmgZJup8WU7QCQtFaR08pZeb0keH3H5keH6L+hEcN3bPgwkanaNGfx9KI9vIfAZPTzzb3LOdPQYuE5EJzbCYtIS3bwzlaJNsdJ/ZJeRq3E6fy6BgGvJ/5KjwFDiJIo78L1LzADcLN0Zgacy6S6dwBx/6svrtFoCRa4GWkaEsfPBkdVyxjHXKFFLQmcZLMmEkn+p+QnidbSUYal/B9Gr1JQbhnEBQ2o+e84NEiFgsbPD/lct3WPj/HQKcot4GaK+7nqBJ+iSxk5U1pL4zILY7d/KCyDC9IBrgLeD+t1EMAtutWfCS10kQwATliv01KZD4nZyH4qdWXno+EClYBYOLG1XcGYNk2/6BK6FytI6pYHEwc/LAyiCulWxFZ/eE1MvSQGOQl55Vw/82RRohMncTOGIAkX8+K1b3Oz1kb+jNxNM/yW9Tn1eMrZj8Gr337o2LKySQ1mFeI0skv76m7ek+euQd0m/q/AiPyByzshoYnyDXV5qkQnsedePHg7A7Z83WzDsjATZw+aPH0WaSfkZ0Xlw5nmBW+CxW5lQtUsY3WAOi3Jkaewx4qi8JJVOLdSDMbwotavLhWlzUooETp0z0kgIyGM150ord0Q4ChLiwJla8r7XRVMF8NB1ak0OB7xWEB3mhunztHO0TDPj0NuGvhZ5EE12l5mZKZeSOA35IiiDJkRU+HzTY/mJq4xP2oBlf971HwBGdKB9uQdAWCoYLY2dWlvjDdmyQ+aWitaPrYakKZhO+hiUorx8FLf7ifvqZ8/5unZt9/cnKikB4OYI8D95rjTKqmfTc+XZlr6yrZSgVrHH0GhaekHEzgybEzpO8tqqX+nE191SEZYFoTFWgtN0oLTC1UzvZ/ew3ugzt+ClCfDywTUYBRBssLc5O+4H2R0E/Yiqe3RcQfL6wVMfSzae2bWrGL0PeW7i8I6VEpowYrNVc8UxIvoJt1xHZyrOZ9PEHY5co3Ga8n2IuVy9gLpdcJw44G81JghrBaqmPGx2RENQhPSHzY08o6HNdzcR6iK/6WuJoAKHCDdllV/6IQHlG6JmO8KChcf0fYDo329DCJCCnJJX24ImCgbhVMhVPTahamW9Va2X+FGFrM5eSoUXsmRjqa3WTnRYNAQNeEMUQo/1+r9K24yEJi1VuI23mCN0Fk0QX+aQQjvFmZS1YgNw/2fk5OMOamloswu0JFeJl1YxSgn61DjK6Zg7NgNruiTWzOzDaYsWZN1OwNIfItHHs8hCHx11mm9sXG1ZSyRzug8Dh7K8gD/IRS9gD+DWqODBtBRD4SyTp+XwZZ18HQaBaTcge96G3HidLGa4L0NpwHWS1OtY1IibcPuOTry0XUMDkj6zf8xj1RaD2T4oOicfSCAJ9lb+DDEafR3LqCcaKkP43M5knGtk0xHcwAP6BncudaMGbzdB+RIreuLLh22vfulqqU2iJI8D0acXs8wtXI33vblAlYOWEVxIg4tce7hBYGuEx1xDFAcLy1qo2HS2dyHraanviernUc3SnvjoipgoKpbf/yMhasTwzDpxCdnyJDrcJnNv6LnDVR0yx2FPIOgsiB0M10bbnNz54kLv4utX2yUNoGfqcSdebfEczvC5Mi+8mFiSN5HHcsYWNo9vRBAKZWIxrkCWqCVgRZqLLMAAajwJtvlOETAc0DjHcIZBZvShqKRSJ3lo0LUKa9UdtTWyQOeW5XtufVZ8CdD0njtZZNXvpdCYi3482hHjIn5vxsX/KL8OmiSvFMckB9xCI6zo7h37hzFdoOxa8jVa3C271XVkRVmFKZfad3kgT6q+ElKr68YmnJWyV86Wd2eAr3acgaUDKZ8dxQ0X0qRwvD4UY5046bTbb1gtH4Kf5FzlolUQXJlhihZ9XsBlWt5IRlRDv+hq9bprj7JWnh62Z6IkZeZQ/pA7FWc23khB880iVmrI7L4Q9gxuZaOmbvmrc72N92M9rWXqDsdWZKqGx7Q0KmIHByTOyNL9h4V1ACiqlG0TuSrvSrHJAcEPiU5ldc1fz08PMTSWDPfeRqtLLQ/TINQtJ88ArLj1FbWgRUFzTxVZA07jOIpfKrB9QbMR5qeHoAiYkmmMUq7LwWE56QMETUe+QDLqryC5wPCXXUgsKfLvByJV9BmZeWU5BTQAWeKbdRiKrKGD/YmSzmsGfR2HGFldlC9rQp+AGTdem+Kcjj+EJGI7cAp+VGYY+VITep11j8ZPEzDtN6u4o+v27UzPX01WEtuwsUwf9JmbDr8Fh7MQ+//GAHnpuiwvKU+OvOLmO/6tEBL1P91PZLP7S+kKhres3wK5srEmReZUA9PIBCAu0LPFPcC1BswbD4n0Ru6VO1/b8oRdUd20v7MTRJvEi/lMAhEIFihb7VLU/dAemQ7tSn4kNsD+Yrxe3zKyLYMfWJ2r27rsPsWpvJMqggMZMEOgi28gC5r86l/uZ2Y7mJHKe3jRtdRSh8Wa0GbPEjce+jG/oLQJvZdN6t8gkhi2rAJN5Gqj9UcE0XJjoSMWBR62shuUtHFWtSvc79S6X24hox/fDwHQrK/5EvumclcTpv4riXUzcexr3/WjZ2m3WOMLrhbLevjaGMMOPCiGrmi7OxpOAg/p0wT8erc5HDYXSJWqXE/ylJFN2zwBqoOGG24ex3jITiD58PsqQV/pvYtYPf0ph8b2iDWS3/UHjrG6kk54sMOgV4JooKTWOtRCOkxPVG4h73m6aMYhVvgeIBwrszvWHIlfHliyFICCODX6QR8FzY24DoIp8MXXtMHpZlWMcW6Uz4bZS7Uaf9tyHiodenXAe1ZlINKqQ1WvcM7ew6+MMKaT+mWYOulks/bhN2Uz2VizQSWG2R/hD20DATQqbUdxs3h1AVHqRWtIhJdRoipzibQXftVLu6XUTKMaE4J2SUDpQ2r1QOXcalOdgiMtnm4SlPv+5yFT54euIaJEBhMOLdou6usDM9mj2ihHdQRgXjYDRqyFODDYW4cB/0ArP806QiwERgYv1iSHyROiK61mF98wz9bF1ErByeUe9/0RykGYV1t2y59YDdWgLbSY8wdhDlfEY/QLeqj8lgR8uGQ7Li8eQt+TQ0NsSmWlh1lHkE8NnXN4QbyQJkGfRlMu5aB8hHcRQAhvV0BRbvrQqiajRW79W4epKx0JO86U3cTGSiOYfmK+TV1TODV2V3kgHQoNihlK6tVFCth6ak1vLhbECalXfHfMShQZ81xU4sjHKzfwPw57nQ4j8sbp5p9HFjL3jN7KxbPtCbXz0tszzIsiGPAbp4s5ZVpHOwiNfyF9cAa8ffJYr8w14h+ZsItFsVG+AYtMA9DSRYn7WD0KeY3bYsRTK7PF7rY/YDCFfl71KMC31Q89eYD2kifaShpj9UdJMth3AHDvc1xMBaZhH/Rm5man8gjK0WHfXEak1vJGxm/uMhOOduehAFeI3M+ChUGBwmcQPnEjMAuD6fTj68kr0WM/hAWjWgQVKIf12CpLOrWgdh9A6HXqpvyTrDBGogsL2kH7qRyUhTbDAl9eLL3isw2d7gP8g/97T5wAHW4MZzETRshDzfF5ZmSYdzFB8R06xuQm31CZPtVGLf6Frahu/ymKj9wE9Sk0oYIM9BmzLZyYpBNcCYtWNPQjVguHHEyHL7PqmmzWB/S6Ori36ceHtzWKPlay0ACDLIfdWB9gCMS+Xk9EdOrOU4i7rPLeizqAJ8vM5LB0lPfN9lckwHbJboViIi+mZjt47oQOVPKNH/uIIjecvxXx0MsgLBmFHMG+CFnp05KFjGJHLaZ+a8DX1FUrT6yfTRThJiUc96N+HFWTnsYk9RMhTCDYUi5nKzDQCj7lNVeVQh+rKGJ8ylsWDq8ZlEP1fmTwruSSl7oeUpn/ITj8dj2wiHGQFsrty7n4pVWWlB0ICzIuDkR0SBwB6ZGm0kdLHf4+YiH3VyQF8Q9tmSkJaa7YeR7IosD1m9Y1iNdLmgVRfqZ5eb1VEPrBfPrXeoi5QJeGyCfrx7uIL+NwbH/pqdKw4xF91HzEvWcXkFQClyL0+Tiw55MEg22F7dUWqKYmQhrGviDSML6Ii6VDDRGJlMChBS5ZLViYfJ6Hgcm16rfLv4Q7VKB4i+MBWVMqT7TQ+QBnlrjAFGJgvBvhEh9SDIZKfx5e0uR+jdIs3ptS3sH4an5AZDSWQxmtsGq5Mf1AwKXIJ9TrUt7fNlel/GmLPND1e0jnD0qftCUsur0zph7HYIwRSHKGFPlnJIgZ+UcIiYtSuVS6MqsA3Eu/oKOiFsnEqJxetM2AjHZj5JjUGvYZC899tM7YTioZEY6ZIEMH8F2RVPk3kZEAxHd6RZQRlCEASgi6lCuyhRSF+2RFyNmSO5O2vJ3YfmZuEZ1S7JzHDjeaIwFyq7NpDut30iiS0GSPb5snckytwYfeI00qzV8JsR7T1fgKkXedu1lXsKSKRua++UWlsN6w//CA118gX14+bK+J9SzVXhUslyXfVsdqHZ51NoLaXuM8zeRHv0MBNb/nrsgjyRwZIb9oXjRI6+7AADNKQzOhevIPNKcC7h54ry8r+X8iMj60yf03bxXxMJoegbIpNUvOVXaCefue821U7WQAAt39U3zU8ni9Woj8Pbm9E86ejbbMZRBXezlnF5oCZWsh5QkdWNZe+kTYpDxPVzbeu1R//Ghm64vehtFdqznstzkRSdvRiBPj1aTrDTcrf5s1ekHX6+wmv54si3hc5/uAG3qEhMeGOCeiX/TRXICPklnRCxHPE4wM3v04J1k7WFX0NM6PwYx/LuEsUwH1giXXxjWMbnZ9gW3bjY8DveDOY/kYO1zVVDO8V4rP4I69am+WthAOVzdj3tazRRiTHFZabPJy2H5+Mke96A1aOWZzJmye760sR3m13h61OeEV3Me1Bznom55LvEAmUyYlvVOsjhsvfKg2ciCM+wxm5kgWyVMztqnisvUmI49idmk3S+jy3GcBQf7oLrOMEFwzRM4WrU/b+K7WYrtAWHoWujlsZ86ghkhc2JGz/riuXpIdfwmJoQuCnkC1HHBp5uLsaqR4Ej6KBwrinRBBlXc4278PZSfvYRcjSiyrGWxkKOh+iaABjz2vB9P26frSXK1a9+rtKCi9/T92uALQYyfEuXjZ1cMcOZ/NllL5cSQjcczfmWKNjYB9xJ3hCk5BR7Pfeguk5pH1+R8sUDoC1oTXErqcZlldlMSnaOp2VWa2NQ0I3cT3YBFfpBpQyjNKf78IomA0mcdM1uKdN7f+q/4dSXLzeh33YVEo1aZY/H9avN0xo29CXoe27SqDA6HvmT+54rberizgUGvEK8LPunHdTuZse6JWhhVX8d8AviwJbBDvxPnrf04rNhWCIwn6HP5Mgz+8EhS1ePqeThFzY4b9jIOKqpbPSQZiaDFsd6iiH2yV4bauh3KDPdAVFE3sdlRkUzZBoMLCEssz5sHAR9c2ClrIJIg/WWxelI8RX5Zy3lIbw9+bY6SiEPheWgjhj0RlzRu5lVduLeEZriRJHOxjQFzAPBPxq0Hdm2cuBB+PxN84XAs1xqx6FYDpGJtMoVa5O7x8G4cacVVsex0/HYMkwKnSuBbQxQRdTEw7113zbiom202YnqeDVgG6hoDf92zQZFXAiVFD87+/PXzW7MeuzRlbnQIQb8qVA+brnr4rBdWzEmhUHm4ZW1dmQRkjSn4a+YviTViA8Rohkj5HvX5qCSTbWP+KjwFOg5JIZINcOTSWp7Iaw9JVwYF5exLvKrODk9M8eco2todnePwI4sGRR3AZ2okfZs68DyYB1QTkZKEVf3o2i2BxSFWtWvnxcWAh/QpAByStNSRKh15wG8W1rSZ+suiEyoDrcdye8zkqbgqnKnI7k5jodHqNK6NqCkjz2nW+svrAKXFuSrqPX2UNmxXASuQoZs6LnTPShtep0DVAq/k1SyZk1BOgQXy+iMBhcXD4lgt+I4kH1QTF5UddFHnPZnpdiKvP74EQZkBIlgR2BKOx7LHWX9Q83gCkvRamIXmIM2W9hN3Api21mbciLKNm/408w/sbG9tinG6o59tA+zDu6mut/8QUFKQZnRhQ45GDLr18182Dwxa05T7cvx+LQwDhPnBxUIlUW2ruTd+o+Yb/4NPvPBffd3CpL1UxzjYYdMTitgN72XV9NCbLRns/w+doLAnMj5BYsEQxaVuGWdCrLd6T48wf6lRt4Rl+EmzXgxJi5YQ4AHC1DdY6QUTmv5dpn8aSAumK5n7rs1HgdXV2GIyGuDDtXfx81WdtgcFuczVgkOjpYmHQEvEGf81JdCmL+R2U/VmsON8+mcGlXC68z088yfatKO/WBD7LZD4cRQE4DCGRkYQxj1PVZOiQcC0L7DbWKm7+E+GDym9JndKEse4xLt+ua8eA7gLs2oNXa3iQqYVgNwGf/bgGjXm38hRojuvsQaCovTnKafTFlnkKTNURwa3GrC1wy9vz5Xzr5+/3aOKw5onHz8zcTLsYtHWrIM6LqQFS9E6u0clS7BS30lKPW1nf5Zj3FSRaYpb7V7pSF3crvkfc20/OD3uq44Ct/fTOA4pVW+hOtG04aIqPxE93CpAS1xGJVsbSkpF/4Lr3ZCd2M6JZw1t7+yJDlaBLK9VSvSA+PersDfUIKJ2bRQbvC8JwLrG6CoWxNRw1k0Ixtbds94CYsCNN4n8UpxYzteQr7dERnbtjjwRU0R0C/6DdIa3TtWSyStyxLFll6fADZEmZEBsB4FVNGLRbj/LCkL+QpRdozpwDbQGEr6mTSw93e9IUqjiPFAAo2HmPK7p3TKZu1KTgYccCFXE28qrMdcmwe3QnhuZLAuDvrRTAZRt823yKLYyXRAK0kSmB/3vdR7RWmdJ3Juywp6AytYYZ2xuCsfsTvA7KIrQOtldp3epqfrptSnl07JhuV/QVre6IhKkXTkErlfWWFyYo5lWR2F20fuDjbpq6maUiFDSONchOTTMZPPVPwZTkW8bAMruLFOVFFujpJOJBU+HqFilFRaVDeg2/pwCCFGRgV/JqUjrYjaOyzkPp7emdYelvT1FtQMbf/5GO8MleRtBlFHbSiHb7UTTEtdRWKbK/Pmq5Mx5R+i3EnxWkCMmPiLD/i8RQBZZd1zrXO+7m0W/+oTr30xJVHNKhzsX+J2ucdg4YPwzMbNTJevFV+CcMNCm/VseNJTUl92rjMNvYEc5k+t7c2jYM2uLRt8Rr66WhKVTCsQADBIYogKh+45b/x7xzY0DyfqY1x4MaK5JnbEU5nJRaXXXIu8XRR26wQ+ybS2ZXSAFmhiqxmjyoAOEyqwto5EkpcBOLJHKueuUvMrFqkSY6G8+pUvW+oy3K6rLgo/ZGk0ihv1jo1xmQ5W+FjL/vXSBDNo/clC4suHosC8szrzJFKhEwMZn0OW1kSGRUKsiRrr6jXH07ThPOmifiPn5uf1dRCBFJ9oPGzE8bgZJ58tFydFyzjf7AUdwhwKqLDJFC4gqkYgHoqFT0NJS+akzh1v7wjARihvQN/TneL+eKEUJUcY+XBEcSDlXMIphF07+Yod6IArsakAgxv8VdrvK0t5GHAJkKL20i7ntwFiHX/SMJrM8NKEhnp46pLKTqCNJDrN2TImgwFMQPO262kz1uhJu8m58uw3os8dtM3hLnAA2zr/fpGgUiFt5OW2l2gpJNkBRK52xYiiURlz9qFTKqPuSBAnif8P2zBR0AQRj2m4GNfxBagAESs44VuqDzasG8blI8OVp8zUM8npSC9655eY8GEjk9n8otEC2qj8S0Us0aKOPbw0noLzZHjrA7tsHVfq1g/xQaa5/SNInPwTpXUlzaYLlnQTkKzF7gSInTfFcffeJoSCBjtK5hm5W1og30oeBgcUpSXb20OE+mcxNpp9hm0bb3s1DefkMPkZeS3YPybHxPSD7MqXNS7UCpTj00UT7XI6kmi2BMMC/CKYTyLJ3zM8LJQorZF91pePLv4HzrsjuwyhJlC5eyAifS0zEwSMJvHPKOFmSEUWwASwiftNmjUrZpK56kpBoGkk0M/Bt1Ne6191E59ZJwKaP3bl7Jk59lM2JexyGZCYjwPUo8ucx5vWJD9njca6lFHUfjWmFGcgWsfFquhgwnOU4udwuNeUUSitPy2JfFTrYRXVRTckGXGPUfJI6sQm3uN5DA/Fa1ajMEXXYe2dDEDBG643siaFwrEvT+JRI1hLGUWYf2Op/eN1o3NZKxCpwiC4P8dZviRQOsnPZ6yN4wFH4GSVhP1LVbEnu+GNWXa4WJV15uPsHfZhF6THRZjGYW1IiBQWYxwITBimKqmXz7OHm3R9f8Turw3uGpHbX7mpZBwc4RGQ2j8tKFYskvbl1XL4hlbeI9Q0zPgoHAinF64rVhdxk0hPRcX4areByLajALN/YawqBkaiLKVqCKjKfEw0rwedw0Xph1twGxW84z2aQSNozqphuzwTuF8WrBfV/nWdLGl5kHToZd04YIwvVsma8LG0EFuPNbAQn0NpeWyn5vfV+oj70o4n/NMi5Bd3vSxWj4eEpcLEoKrIamx/h5/X/qnX2CWHQBWXPDVHZEKD8xyhi0lNYM45UiZklbPReWMj4iRawjtjyILd0twmeJR13QtVUzdFjqgZitK6BfjMn//jE8uyiagNG1Eyzi6tONAZuS84M75Ly7Bh34DZZB+puRpWkJw7w3dN/RzxUbXo2OhRfNJHnye0Y3yGUFxxIOhTauNGhgk/PpcXaSjNvOa1y1u7kEmqSyEDp4rbJUrwdwWCV3iRekNiIcPq773GTq61L5HxcpWOKLF3CMNVKj+ugVNhlNoT0wOuxUk5Qzbb2hh8PDgbu9WZUVhwjIqrjuCOdWMLJfbXdBYhlwn569u9ytYW5SDMo4BGpDaslCbQX1Y74niJj7VyniJj03L8l4ozexOrpo44VCpErCxCLRosEKC4/LNyzYqNnfSMING+8fYxW2y8tRq5pxl3pmKIiIdq20hI3bR8STmOquJlhRGi4lJcCxq/R+mOzP2gwaW6qqVg2X0X/7PohmosLLys77q3qdFYhZAzIlugb1gKkMhbTM1pWOD98IIRnFEI9uFHx5TKEUhZvRc5STI05KoPtYLF++6PEqHQNtfLenxN8BOKR9WFIZ3vIssE8ADdeQyP7VU6+GAA9UE6ZWmG0xYxEodjZHh/7MtY4gNR7fxX6H8uqqxrQR5tk7LBDwZ5OWlyrZW/vM+zvd21P5BNXGJErp56mjM7E2F/NFCYhfPxhvIkNPJC9+gKOcYgx6fbGJpQrxs8/Db1ktXkpteeGlK6xMKJnSpHvqwQegNTal8TIMRAv/i7tGTYP4Rxn9NN60cIBQEnBJd/x9UPwJy0KL6FWA+trRWeFpKwyZVqigR+MbBzVjLZSHZlGirP6LLNAO/Ew+lDaCTL+B6lBm4vqWTDGV/DgyOob7D652KK5FROay3RDmCHlwnIcLprK3YJd7LtHAP7B8GwcKzVdddlszwarVJPxYJz0LeTAIALFj6Q8yHZOp1kv1XcYDZjeNAtAykfnWHltdA0raglM0kbQePEQW6WxrVY0oRS64KEBqlTjekQfNgG6d1f3JJLvkHHjYkGweMDAXhazao5EBuPdxSwC4YeMfdL9KH6mgZPHx+C8nDq+vodYEQmDetXhvqgbg3Tvc1YYB8neQhummNKdvouv2AXEpcFJVPZC4xpIr7Q4AxWFa0meGn3PQWL4e5n5VYwiroBjFSzgfLK7Wl9XC7g2nKEY07mziDHoQXO7S4VPbDUgWOAnv82LyBx+asUmvf1Rtww6aK0v6BsNcrx4zUcwO1AWv7vl6vEvTwZyys11nSGgYvdSJrzWRi1j7jE2Z0bMlw+A3jw/76TnOpzkj8DuoLpQRilc/bVjpUtRgmc0Um3QV03B7wN8RFqMu9C+HCnFKAo30LA/PLRAaKb7N4t+F8BaNaIBDkx9J8xc5QWiHfUteRwEsCw8pSEkmFL1nLuwRmjQey+tspQIsj+DBOioqKNKHQXhgPR0hwLnxNhy8gr35CoKhbKugByLMMQmRO4pa1ywV3Jkrj4fF4BGv3D2+/zhKwwAq/guNg2BCRSNrok7zx1jRhJUyW/Ko7t0yRoaqobpkraJEUT4z0J97uXK6IRX6Kf+FNBhR9FGwSKHtHCPWF0eTMPzVHY4jbZAQqX00C/xsbJFKUhkGTtoRqUXrpmBSmUX55YCzh+dQDaCC27GDFzQck/4zJYu+kIs0tLYwEd/DyR9m7ALSJwvEqpJ9JRzIAO4yAlWBwYQjIRCXBPQvjVrz9u1JdmKvl4Tvq88c823NH0LNAn6TSsEr3TRN5V8voq1/4GrGarskNduHc/HnHuyBRhJjfbzVbnvIzStQCuTtt6E5zawlYHGP0cEunVzeKPO2DTujb78G7nW8W+6e5ay2i8M2wUMYZzRcnuh+Jmtht7dHFFSUyjVDgqvK4OBDgk0JeLkwFcqOsIJdiaghJUSpTtn/GVkAwEEyt1Y1k9mJV9TYazm6VAWZEAmoTUT8hGcwsgRmQVoK40k5qlzEFAvaXmSvh3TGuRV/qxCJnTumbpJc8NAH7l+1Pj8/1zgz7oC2YbmoHKwpcutZyAOkv9pNAM7iQeehK2OHlBGjui76OL+ZZ50RrxlFBXSwHZ0p36gDjC8m3xHd7lsQm3ZpRhxscN9JFlRsTaKslcvpKT2U16xtaDPI1KGp32yqOVk+4B++PvFv/4plS3U9Uof/gJgYIw2EoYIcxR2tAsuHm5D2ivwq82e5YtjhFfuz+lA66Xwff0skZzYUAVq0Ct5JrYlzLlIxgAkqvVdYKosoJGAvkTgP9AlZNKtb553nF2NuMH4x25hexlmYEw8Dm+s3x3NjWCkYNR6SQFD2YUFp9w9iGD+kWTn1zamQ0XdbKiWh0wUhHaA62hOsxc55bOp5vNv6SK/Wbrtk1vP1wO0Ee6jBqcDBUywXF8BNN7JERw2+7kT6HX2J9nXVVquWdD4Tq0m+Cx2BzljJixA77NZ5q6KSDCrMiPO6M7Laqt16+pJUq87KDtkpqXI0KrdfCy3hLgOG3JJmQWo/+wo/zYNfwDo/8K47I+wL+2xYkpNLz+8eiVIUwY58eslfa+aVsjf47RoyKpHhR6uB/ne2AklvJvmFgWiMu5s1iSk7teRw1Sw0dRnUxwYI48jonOU+RbPCUwA8/WtFZ2WtFNqHXD5B2pj/7kkkyEW4EGwB/Cd78H36abe6wDZzeG6S9vUCu7tfYPuEWn+zvWUoKjJQ7UoFza2JZMIDhsypMAdQzEOwMgGEDT2EnPxN6YjOjpMd7KpUQcdbEfThGNior9vD7F1TZq8M05fdI/vLHplcDf6g9MzOwQQH0myqk4FNiE5XwthmPpQ7iI5sQntQ733X04mt6AB84jgqjidSCZyhnGoKbyqF7c1fzd8A9Hr/DI6mRCh3qi/GypdeGhBmrkAm8ny46toZI1flKxGCz4oXhhcq3cIrb4HyWh6q28LKX1HVy48nZGLfEnwcBX7rOjbsHq/HJD8nJANA9zFLe6AdiIkU3KbBs/5xYF892DEC6JEB3F1iKS3Y6qXQbE+Zo1uT16n3wyZC+0aCp5fbr+nkevZQsJITap4L+VqlzifrFweQHbMDnFpVmRbJrwpsRYA/OKhGna9exywbv3tSODwLHfm35jVSUTausbyyXPK3rZVPJZ17xnuZF4Q3fWJvrtBF8fYqlTDeFHL1Xkfum9SJQQCAvRTnT1q9fUUeE9RgTZO/py7zYjfsUuFZQK7sMRTmOrFVtkyfTznVfCEWBbPaqGVUUwVnk7dy7rcZUGF72E5zXAfVHfZyPx3Wm+M7PCeQZSrBWQ5Llm91t7NJrFr7q90HzJbq8pWYLdxWo893G1NMHoRsCAFWhil2/jNqyOT+wV3GHUlL8ENYf2n4dxAQwCa9ELVhvOnwmyjfnPIn4fk3II+xL8K1vhbRZgUF+E8g6gVVD89L8P66eZaSot05ze7/eSZxhqVc9r82LP9Q53wOh6ytRJMeloq/U+Da1q5kgrV0+7jx2MgEAlzDfupZDvBoVX44AXu5YccHih6DIDCSERpeV2qKhsJHycKcgniEIkH//D0/MFv0vcDDLqqSXSBIETx8Qn9Qd3p8bbVzw45uRC6SR4avP0tV6MdnUqE6aORMgezTg8gBbL8CBylEUd1McryZPk2fxVCWMdZGI9J18LW9oEbdOsSIqX6Zv7ZinQx/E8OAK/6Nbz+aEAXuEJbq2bSiiZYcJGWxMHcaWTPAzoM34fYi1XpIHkzdLYLOE6jMoZUVjh4udeX8j4p3xOAjV2AO2z7EcUDKa/vqnMlXJ7Drg1AzOZUYIGBfEJ4JeXuEkel6K5H8EPRwXut2/H3bWuj/2OtwbqQ+azm885opIlIGHrnWiIHu5MWmTuU0FdXdold53dBQ194g800UNJ9j74lln9Pwr4mhhVx0iidy8X5PVSLfPMfTuB5y4J739srzcB0Q+nKLNo62TWGkCDGlYe/8jf+D8TnM2EIZ4kyxj5EEaO+tEpjlDAXb4BoKV6es2cT+SWtkTBYMRvIi73iF2K2gtnuwXYnohRzS/t09PBh4CYd/Ux3GLyZ7o902SdiwxjiapOEgidECg8v0tNv6+fmwPYosicLDZ80aELQxvKbcJN8lEwgPY6tPqxb5ZT/2xLEpQepz+63Ih/xfyNjZ5F2+udnhznj9bSd1esJFfdswicWSCt1VJNitC1haoGrJOir4dRI2GTPus/3/Dkp/ojLqvJISMTDCoU4iK2ZuOAg6Ju9BBmqqB5RQoVCFN7LjYVHZcTRJVrvGKZmHmi8LHNRXkR6SDzbxWUwuYPjtwrblMZwwQUn+NSHeP9cUG4Uw9OVhQyqXuqTy7EPqgCIXapuFe0q29+G4C47hny3IzKEH+S4/jpIEcDJG5wmVW3YhtfxlC9bVRMYHURzhVybiSEZFQZygh+vBKocyzeAouW1CW+sOr4BNWnznskzjZo469Tz47MNAccaP05Ec3oSGoneq/GA7RoO/5P3KFbGhgcbJXVaC+eRamn5mxISjAgwKwAUwZ1+WW9AftugWOakyKMXgZIkiUpklg2TWkQ0CgG68FxiRvmfacEBKb5tdzZIFihwiMxNPm9FANO9E0zqe6pXBvEGkWDCgKDGppVRbCjPhqTJJimgj1d/E3to4LxIOBeiFozIDyOjsT7t7HRIVXuPKNxyowM2TuEgo7i6NpzmQFokNW5D0Kxga5mOY6Qc52h6NfNeDDG3zSz5SkXMizyYsZvud8YHj8hIYDNLh6t3RvunmrKAm7cO9yQQEM9JNV2pVifXYel7Q6cU6H4C4qC2YkWPYsEbZuzBaB6KUSPDRIgiCEw4RaMJ7BL6K7te35SV+GF/vVM2vlUu7xGe7alTeVIwIO4aVmGmXe3Z4jfexuyL2pua3m0dlHc4wmIy2KIKj9RDi8I7PGSkRQjJ0qlAQE7XmTOSVgbepgnnwsJK/k4bztuH2+I8cA0NPOI9GPME6OP0AruAqwkjZMH4rpnV2Kw0KIpaa2cpyem8eL+v1+o9a5UAeyHEeL3t+UGlrNFQfbMF1VBL4IOWXJ5aedgYGuJWAwNCuBuDM8vitG+I4s0SpVWvlqV2DWrW49QxuZ+rQkIwZgBYGIWyQF58gcTKNTEvdDMafUmAPVmu8evLMoFT5LtHLHJ+Lj4Wymhi6uyqCl+hfjMSFTR3fQ5hbDUlNTl5Te/OGm0yV4DoOawtQ8/bnvFRyTrw5hrYPvCi7sEPpuBIpLBVs7x5kC+iydnesGLgdVlt9NTVEDb2sSugwEon6NLCKnWJWf9cUK9+9XJ/t8NeLo3czVTeC86fwXowscltwkCtalpQWS5xpHQPwyNvyjuo96A8vcdBCulQHHYo9L3pGjbiugV+kl1PTLT1mFE0zigVZxWJT83QkC+dGOJl1pX/5nWcsrcPm1Il6lGcQPjnKs29p3FkHet0FjfR1aaAb+q3kip8yIzcNwGUdvODJxJ/zh3jGy0mgRfG6NkNyAnFwspmE+9JN9CycNMw54i9Xmbcw/mHTgUMOCvIFZPK8gclSQxxpDEUqeKuLaVSTc4gR4O5t1+zmzp1t0wjQoxyDlzHbDbe9mYM4Uoo83k7rhRRT6Q1noeyjX9JVcOO0tX8PFStL0tvq8B6mOl3sHNvld98uA4nYhupYTLOFfd7ilfNLUFyhlCsruRnVID+a90g/Z5MxUc6QSFwPJgEw4KmfMcLm+xgArl5e5iiLhTG0gXPprHtbU9igt6KPz40+FK0EDoMnouJZvmbIEh6T/dQw0UQhsfoHxOP8k7hpIh4HFUiWNxb1C76XyS88yKWnNA4NbhsdIpltWdt/uXUDvoS5sgNt4Q5QA1kHH+sZDclweozKmd0zjioCeH7q6BEBaR6O/1W4n6Su0R9FkNxCERWGWjDCuoYDHxm7wnK6DsMM02qkDJK87itimb3p4ZlDMUX8zoB06iCGvhce8GwYw9neKKEgnL7xfuEqM7MxyYnS7PJdhpiXjG9f9R28+fBli7EDrkD7Iyy1kaYH8r/dfgDbAeU7oB4VrK+C1uCWbv0rSuJovB7hFuT3q8HMwQzWKsKn7VM38fkEy/VJc9xTf9SJJBfDtdJN1R+OUwbbOxiKZEwM5XQgQ+4xoGxPvlIdAkJXgeiMWi3001xWM/lPSUzIDXT0IQyWDSH1pKQSn+VQCDP2dG/50UAEgrCFuz8Mx7Ofj0k41/ZVHI31LWUpAbYYdmZ3Ib0k3dTYWLYn2aNMkbeHp2xZ7X5DWLcUdP3hGiTu8cSWicXyYcV5Tzk0VE/GDCwD44R+dH0Wf4JnD2F7hT5GxcWX1QQxfHHJ3Z1ptw8W+9Zn+I5XPwrapQyL9Ix9EvwKaXim3WqPshAkTSSLhlKcdoF/II1zotiCKACCUnGeZj3Yw9mX8Jgmoq+k/VtzZ3TB1WSJctpCWugs/tBKwjwD6ZwadzstVI9/2Clj/tegYBVwkNafaFV39gJUIo0nqkvmOADhHjglHgqYUT/fusGV4G+dzupjKrM/Z381Rm5yvcnGPBz2fjMUihxoOjWOqVAHg8oywZ/+zjrWKPhEnNMX8JkDEaJtdetiSeSFPSDGpcUb9FTmOrtvtoilNfiyChanE93BOllNEhTmutI3LYkkxL3gnqE5Ki6Nqm2OL6AOuBREv7toQfx/Md3M2IWdd4UmtZI6tEM20w6U9d+S0BhjVKwSM6gl5T261Sm9mtqSh/9cYyzkqLGW+tthaKGFyWk2VwXRz3LPSNamQrjrFINm10pl7GI/o/peu6fSUF3QkGauVSDDK1opCqW+bdtB9rOtf1yckedJxsHPVt+Fmi+5WGURnmaFssXUl6c9oZTF0NTS5EJ17ifBjTXzDmz1CP/uGleqda7fH3HzFAtxyFcIl0FfTNfwTKVVeVHa59bML10sM9hPJfdiNNvpcKsjqHEwa6IuVhegrD6ZgXhchUuWpyYc+HUy4hi4doIHjdwJZx5WuoAykMBVnIOixf2aYKn0wrNz9++naxHeC+T+eIezGReWDRZ+/a1vc+zmdBzSHatSSeMWdKuC4vmZw6PXUMOyWCkIqgjpstMFnMV2IOD+HOdDJNjjzgmIXkLp4qzLjXAcVnfIE03BFF9dcmAmuwwWOLesmuwEftenajE77NT47YZkHHEjhGF+cmqluOTOgQOmQzO55hODPlVfHmvLBejYrpl0KmCnQfCQ10N5VDMrUIwsWCzRjB/+Tp4sDYhOd2h7zQEidE19lVzkHzM8Yv/ky8GgbxX8O0+9QmNRML7lQGppjlcGkdMGmtWt/jPEuAjHwN/Qj5gX+zblrX6j+EFzdJ23OIcdrEHreOl01uwcpeCy1VH7YGSS/o3TI4+WdCIP7XJuS9azhKvs92QI22QIQVOrhcn6IRdgNpvZCy8CmkzUe4STXjBtdgRiu8/KALOhRAzO7u/RLq40pOTOkYU+idG3jsp60U+uS+0BuggSDeNUHlHo8V6/8/L7vEpy1ZwFbjlUueTw4Xe7Ufaz0vB6SpGdJXlFspTfasOmo8zyWgQzJS5X5tClL+KF+QuiA9ZUgRcQloJW6F1CqNp4b6HWMtTK0FaM5kmtWkWVJcdcH6GqWcRRREYAgc5sNZLCyByX8/fpMRALYUkHFSZtSgukvq+2tzMtLuhNw4Q2czlK0WGFTpcCqOj8Qv7KKVr07SH7feiQIejsTywCXEIZP7epMj1YV8AMlouYE85DrYa86WHwY6g6iAMuPiauCU8HRLlEOc1ORTWJnyGr5DGTJ3CFru5hbdvjH7bEqtzYeSfU62zqvR1gx66b+u2bFBgr8d4Hvj07DyBjEWHGsdZidn20Ydf8cdP4+FAdeYqXLNahUFMlfb1RgIq3bNuQr9hr9EeWiadJayKZQI07ej5A3XA0UfXRUelf8G3mMG10M7ZcYkFm/Xch3LQHYDzZtcirWTVnKl5et2nTgdyBPCIOH3uWATa42srlDCDlswaOhVkV8Om+wXbCqoKq1vKOl90hYvYGiR9x0YvOdU7+XGYbn11BgFC5g6SQA1H0SHLB6RnkFwSvGISJdomp0bNnZH/Fp/L7r+EI6Y5JZYqvwemmRq/mW4G90UMFsVQUx+EbAtt9EBYaBhfWCkTLKCsb1UocZRhKrZXHtszs5pJcUL2NZHqpfbMLIhxQvNxUsiyP1JrDmUezaW3CheqKo6ul0kRumP1BPcWjaWAnZUg8E+wcA/lHQEXlJE0czlG7OG5PMlLj5q2y/cD0P1gr1JQw2CA8OMkbDXtOuFiG2b09LLHreGOaxLgeWvPyk2Ue1GVW8InFqq0zVIJ7ib1MNkoF5wHMjPJbgojx0G9Zj237otnTvOO00rKhIRRxalWrFubBXe4rHLJK9LkTMS/gMangfgWVzYDk3gWwEDwx914oAvyipon3SzRX5xCmn+Fj/8XlR26rXhZ/FvlcoceMezuJgYf7DCFBG1vA5nYD5KcKGZzjMfXGj9fMnCuhd0w84BwMmaLQxl5hoUrrjw9HdfvkGFVGQ6ImPKE62iFsWJqIz4DJeEu5JgcLVBuqW9A2PH+KlPw/fqTsR9LTAUNtzKNGF2zFN+GKhkrTPI+4Wzan70/VwP4lib3wTrwlvM4zqsX9rtbWqZRXje+UNcH/WHum8vAyht+xgL6t9sPOCUMvi35K6w3EU6xB/vr4pI+uyIQt0FM9M4ka1QmKnUe185J/8DAsXCU9grpGpYZQuMcMOl4Cv7gEXqNDHhzdC2Q3I+SA/S6RNaAxOyncwDH/h1m5Hqd73u95A+E+92pEjS7p0gAJwXqnBlIMiybYTJpdoSdsogL4gHuLsQhIOImkasrbom82kE4UIw5O2y2K+GOxx2pSHh0qYywm5TuD0sxLDt7PweaMalIeHSpjLCblO4PSzEsO3s/B5oy/1QPoigSGtSI0a4UwnSq1f/BoN5fuNqYOqUEXdpJMOnSVuYeJJX0Wks+64b58WCNhpWdNVyNPHj/hRhUtdX2Qs0ZQB0nG5Y7Z0Yvjecl+6CGmL4GYPyxjbC7RXUcQM7IX40365iCCbUX9QLqLo6QmuBIkiA7qXdI5VywLL0RC9Z9Ne0+l1ZkaZVFOjGhQfMMSaKln7KdFh2Ol5iEPJt2UfdS4+WEu0Fw7baMNWwLcuULpXLUeH2duZWXxh9TdZO94eqMJmngHLpTV4pKN7AdFv309W1E/Sn28ZGV3H8PqQ71kr64N8BeHfAXSFFef0rtKkU8HIxDKgriw3ya6a8YdmJpai+t94GvrUq186aS3hgt5acLGuOBAzfNUSNBEw15yIlg+XN9hWc8+9fKbAQ0IoqZmMiyVsA2DI743MPiiRGuJoI45O4un7rhy361IpgGx2WOiUQGL9eEvP9cESfYTkbAA2uwxpKvjRHMMKwsvzScUdQQCjJqvFpNUBIKjJyvz5e719gbS4d5SvvRFICrPjLMcksrGvQC+PquZbuXLXeEcu19ENLdRUILQ6/PqbDG4QwlBP6MHhXgvfdXXvpiN335BofEgYv/qpzzvNPwLDh/MyecXgt7ohEnWXQSOsv/nPawC/HOv8/gdFib4+JdFFwVwyOP3RU3qvfVh99iTht6S/7TWMm9IHP1q31eFx7BiPtiEu4Z3l9PcnDwv6RtTRxhfTcX98cw/uM7okaZYTWJYSS0BPPjoegAstJZ4J6KYmNxBvc4zNOfDxzDAqfQbu5iWE8GX7VwvfulWoRT2q7NRALb+BJv/x/8i/T9F07bsfVJWpCms9z71XcDUKqpElKkPO3b87CviypRQUkigtNXRKgVRycNsv70qNiqdEAuFdDghEUnCHYWHD2hc58rrJf5clZ0h7xZiVQuVbq84KtgPgXcYhLYN1CHfi0PdODAEAlmyO3IuETafFVgazCygpIVxLx/zlBYsJl1MtyYr+qoUveudIEB407Zg5X2FAJYfNiErWbAVt7q35ijtNuGcqQQ37CaIADTLaIICXZ8uZCmcftlhHQNwomzTgH2XwoWLmU/Rs5/yFD21fd28xN+uK7B+8XeP3nEbNcMHy8b2ck1Tgye1W6yTRFIAu/ICCtfRVcKW56KN+YwisPq8NhU8b3qcrjqPutmOM+RVlblhjIm9wdYWzzPF8BrrMB8iNZCf1L5ozry28ARaC9/LM+a3EIJy00v5ZZddBasHBTz46LD8EnhyyV2AvxWWWhUnLrpNkE8Nd2ep9qZTorMOAWgzdwzyhX94brHd/ls74GhxGnGS8ONM0UtlYPY6AXXZq/RrP0yMoPcsoGByDvD/OfaEIIx/AAF7u2mL1mnRA1f4s3EE+sahB8+Y0WCzLk+9gNPiZAZ+ho5Anb2OZsxzzhQSuU6p+qW8dytoBSZeWj03QbbnRmbVR+SyNSUIRpui76LQ1SiSee2KeT9L4ewAeoi7J/dGfVeHxHtV55N4L4AzHrQTJLlEoPciP4GkYtOJjZdSQGIo8rdz3HkJq8r0vB/D4hjK7v4DYyDxbFu3wGiTastT9OveTOsE8VvjRstdTQeH/hEN/cyydrsONr9me3M9saojb0VvftJK60QHSMPjqHt1GHqZLeuZ4GaJUVYUutAjd0/f/okPwKoFma62Sk9E7anyqekuPZAS96FEHHtFGhlSP4Igvc0XignIwU/xPBHQJg3sBlExducgkqlMQDMKAirx81sz4ujqBTXA2+t1Y+w7Zg1x+Ah19XwQdHRC6kM3c5AD0R9lni6KHS7wKUnPPHFOmY1wAWCUkPsQo7F0LPiGgNO734ABnsNIjU9hAuTZjc3Y1oK1wquFTJXA08M0e2KMSjoE+Rr4GioBKeqCxVKuA0cJDHD/mQEvUFvZLxFhQNbAfTxyRpwd9mx9B9ty7RqLl/N1ekXAuXIyh3kbf025O772lfNhxr3aI5vgB7ladb2rqSovX8ptNP+IlExubszluISmyQ1e7+/ONIHU26eBSIGOZUeOYFnth11yO/kH8MspAWAyI7RUMqTJai/y0bCHoksvTX/6O9Tjdb19QKC1faiODQuWsxVPRrXqCJgoIOX5poA7vo9HnhTiwg1FA6mk854BaMbHTtJxT3n3sCn8dbRrB28Rcvp1hdXJOuzZUIaKdaZgYX+Ro6Ck1PvPPuYj5DceZErWBkckmO52fxK4CDyyWgz++0y43KotQgTXpIb8WP04gYBIVhBA1nYVcfJsSzRg6hHVphsn6N3p5Dp/nyBRYPxAOE+vxqikv5fIcK54AgOUq5l7/FAFqraZulH0y1wEJsoiflJd6nLLrKyoGTov4gRjB7C25ZIOO5EWGB5yTsEY7zM7a3uCerP5UxWKVV1tST7HkYgnaubcwkFn1KpQfGH6Wz66XUFPH9az72kF5cWXWr9sCyeln17V+grnqZQG2rau3vTsAVI439cfEVBilj4wO3a4JaVMdW5Lk5ofLkBcpkqvPafRR6HUZn02EoCsHwYqu3TU5mxRRzEwQlENhewZRC3CBf3DdgazDJW5h7TzQDDmdh41GSctiYt6dfIGdZQeJrqluhLo6Wrhs2WPyamdVNINqWe/ydON6snHMvK4gdIzdyAIiKB591Cl5y/hp6LNzXf9N74FoK4epdbxw8a2FZX6/gR1SS7akkmbdmuePVqpVXJywQeaUshJ3F2vp40odie2CQoa2mkLMgkKQSt7pTHU+p8BVSjhlXBxDCZyDLkKoYgWPORQPB1vsCx/YBKhPqp9GSZegBKpg8OUrndogYIrWYHPrN88TsBSLPWHTuZmqyi+r+L0j2LRJ4oV7BPydSan64W/6YzT12VbTve2h3+7kPODl2AtT3A8NJn25hJOFNHp43kN84SllU+JrZ7dS6i+IaE4XI6QP3QycQJl9XqccaPqXxA5jKes4nWtYzV6dTdTyHby0glJL446IlmJ8YTTO2IMnlDdmg14Ip051+tLT5OiMfA3bTRz71O5KkIsWPjyzshogrBMEP/zbF0Izav6moYE6cHZ1pzAShAm+DKqbw1ghqRgmbLi3tvRxKsuk496cy1M0QEiJ4Oe27Y0Acsz+2ph56gy1osyfYIF1VhWk4LG9DEESapQ6TOTA/hyBOQ+Zht6DzRgd2L1Iz4lXV/zbOxc2NeEfs0GkXfgWnRY3G39KrTv5YtBvQ6hqDin10Mu974HBUoIJft42R8n+nRxinA5cTCU1g9JY7zPUjTEGqyNhiLim3aylogWAky3id+NumNtUWZRzsPZQ+LHLUq7a2Yy3I4Okr+21Oy4Mzie+VJeqB46sigjBrybqPM8vHNDDpy5uqIIvMec6hCMSUWh3w4wseAikjHGnNDnNiMWaor94VgVciPE4KhbhaiZPIYP1R/85LlOlk4oOJ1d+kAUKJy6o7/OIthcUd62Y46I0NrUXr7ueDXto7OJK4H2wgzuIhn0nieAsr2465pXUL8fZRVtfPWGpqLLpq0Kd/yrbw/XxFMikaDcrtRDMkOXHDREVz1nvr//SDY3ZZv0L7Jz54zg6ZH7qnvyxzalF2pyKRplYsmbal3LDMFwNVFUQQjq/9LaYKBKQnlTyZIW9sr9dHYtOxeA6PRVFjzjPDOGe7twa/bH3/vFZWU="}},
+            "response": {
+                "tag": 1, 
+                "arguments": {
+                    "torrent-added": {
+                        "hashString": "a21c45469c565f3fb9595e4e9707e6e9d45abca6", 
+                        "id": 0, 
+                        "name": "ubuntu-12.04.2-alternate-amd64.iso"
+                    }
+                }, 
+                "result": "success"
+            }
+        }
+    ]
+}

test/data/get_torrent_hash.json

                     "alt-speed-down": 50, 
                     "download-dir": "/var/torrents", 
                     "alt-speed-enabled": false, 
-                    "version": "1.92", 
+                    "version": "1.92 (00)",
                     "blocklist-size": 0, 
                     "dht-enabled": true, 
                     "peer-limit-global": 240, 

test/data/ubuntu-12.04.2-alternate-amd64.iso.torrent

Binary file added.

transmissionrpc/client.py

         )
     )
 
-
-
 def parse_torrent_id(arg):
     """Parse an torrent id or torrent hashString."""
     torrent_id = None
-    try:
+    if isinstance(arg, integer_types):
         # handle index
         torrent_id = int(arg)
-    except ValueError:
+    elif isinstance(arg, float):
+        torrent_id = int(arg)
+        if torrent_id != arg:
+            torrent_id = None
+    elif isinstance(arg, string_types):
+        try:
+            torrent_id = int(arg)
+            if torrent_id >= 2**31:
+                torrent_id = None
+        except (ValueError, TypeError):
+            pass
+        if torrent_id is None:
+            # handle hashes
+            try:
+                int(arg, 16)
+                torrent_id = arg
+            except (ValueError, TypeError):
+                pass
+    return torrent_id
+
+def parse_torrent_ids(args):
+    """
+    Take things and make them valid torrent identifiers
+    """
+    ids = []
+
+    if args is None:
         pass
-    if torrent_id is None:
-        # handle hashes
-        try:
-            int(arg, 16)
-            torrent_id = arg
-        except ValueError:
-            pass
-    return torrent_id
+    elif isinstance(args, string_types):
+        for item in re.split('[ ,]+', args):
+            if len(item) == 0:
+                continue
+            addition = None
+            torrent_id = parse_torrent_id(item)
+            if torrent_id is not None:
+                addition = [torrent_id]
+            if not addition:
+                # handle index ranges i.e. 5:10
+                match = re.match('^(\d+):(\d+)$', item)
+                if match:
+                    try:
+                        idx_from = int(match.group(1))
+                        idx_to = int(match.group(2))
+                        addition = list(range(idx_from, idx_to + 1))
+                    except ValueError:
+                        pass
+            if not addition:
+                raise ValueError('Invalid torrent id, \"%s\"' % item)
+            ids.extend(addition)
+    elif isinstance(args, (list, tuple)):
+        for item in args:
+            ids.extend(parse_torrent_ids(item))
+    else:
+        torrent_id = parse_torrent_id(args)
+        if torrent_id == None:
+            raise ValueError('Invalid torrent id')
+        else:
+            ids = [torrent_id]
+    return ids
 
 """
 Torrent ids
             arguments = {}
         if not isinstance(arguments, dict):
             raise ValueError('request takes arguments as dict')
-        ids = self._format_ids(ids)
+        ids = parse_torrent_ids(ids)
         if len(ids) > 0:
             arguments['ids'] = ids
         elif require_ids:
 
         return results
 
-    def _format_ids(self, args):
-        """
-        Take things and make them valid torrent identifiers
-        """
-        ids = []
-
-        if args is None:
-            pass
-        elif isinstance(args, integer_types):
-            ids.append(args)
-        elif isinstance(args, string_types):
-            for item in re.split('[ ,]+', args):
-                if len(item) == 0:
-                    continue
-                addition = None
-                torrent_id = parse_torrent_id(item)
-                if torrent_id is not None:
-                    addition = [torrent_id]
-                if not addition:
-                    # handle index ranges i.e. 5:10
-                    match = re.match('^(\d+):(\d+)$', item)
-                    if match:
-                        try:
-                            idx_from = int(match.group(1))
-                            idx_to = int(match.group(2))
-                            addition = list(range(idx_from, idx_to + 1))
-                        except ValueError:
-                            pass
-                if not addition:
-                    raise ValueError('Invalid torrent id, \"%s\"' % item)
-                ids.extend(addition)
-        elif isinstance(args, list):
-            for item in args:
-                ids.extend(self._format_ids(item))
-        else:
-            raise ValueError('Invalid torrent id')
-        return ids
-
     def _update_session(self, data):
         """
         Update session data.
         if torrent is None:
             raise ValueError('add_torrent requires data or a URI.')
         torrent_data = None
-        try:
-            # check if this is base64 data
-            base64.b64decode(torrent).decode('ascii')
-            torrent_data = torrent
-        except Exception:
-            torrent_data = None
+        parsed_uri = urlparse(torrent)
+        if parsed_uri.scheme in ['ftp', 'ftps', 'http', 'https']:
+            # there has been some problem with T's built in torrent fetcher,
+            # use a python one instead
+            torrent_file = urlopen(torrent)
+            torrent_data = torrent_file.read()
+            torrent_data = base64.b64encode(torrent_data).decode('utf-8')
+        if parsed_uri.scheme in ['file']:
+            filepath = torrent
+            # uri decoded different on linux / windows ?
+            if len(parsed_uri.path) > 0:
+                filepath = parsed_uri.path
+            elif len(parsed_uri.netloc) > 0:
+                filepath = parsed_uri.netloc
+            torrent_file = open(filepath, 'rb')
+            torrent_data = torrent_file.read()
+            torrent_data = base64.b64encode(torrent_data).decode('utf-8')
         if not torrent_data:
-            parsed_uri = urlparse(torrent)
-            if parsed_uri.scheme in ['ftp', 'ftps', 'http', 'https']:
-                # there has been some problem with T's built in torrent fetcher,
-                # use a python one instead
-                torrent_file = urlopen(torrent)
-                torrent_data = torrent_file.read()
-                torrent_data = base64.b64encode(torrent_data).decode('utf-8')
-            if parsed_uri.scheme in ['file']:
-                filepath = torrent
-                # uri decoded different on linux / windows ?
-                if len(parsed_uri.path) > 0:
-                    filepath = parsed_uri.path
-                elif len(parsed_uri.netloc) > 0:
-                    filepath = parsed_uri.netloc
-                torrent_file = open(filepath, 'rb')
-                torrent_data = torrent_file.read()
-                torrent_data = base64.b64encode(torrent_data).decode('utf-8')
+            if torrent.endswith('.torrent') or torrent.startswith('magnet:'):
+                torrent_data = None
+            else:
+                might_be_base64 = False
+                try:
+                    # check if this is base64 data
+                    base64.b64decode(torrent)
+                    might_be_base64 = True
+                except Exception:
+                    pass
+                if might_be_base64:
+                    torrent_data = torrent
         args = {}
         if torrent_data:
             args = {'metainfo': torrent_data}