#!/usr/bin/env python3

# compressor.py
from subprocess import Popen, PIPE

def compress(value):
    """Compresses a byte array with the xz binary"""

    process = Popen(["xz", "--compress", "--force"], stdin=PIPE, stdout=PIPE)
    return process.communicate(value)[0]

def decompress(value):
    """Decompresses a byte array with the xz binary"""

    process = Popen(["xz", "--decompress", "--stdout", "--force"],
                    stdin=PIPE, stdout=PIPE)
    return process.communicate(value)[0]

def compress_file(path):
    """Compress the file at 'path' with the xz binary"""

    process = Popen(["xz", "--compress", "--force", "--stdout", path], stdout=PIPE)
    return process.communicate()[0]

# compressor.py

import os
import sys
from optparse import OptionParser
from sys import argv
import base64
try:
    import cPickle as pickle
except ImportError:
    import pickle
from io import BytesIO

from os.path import basename
from errno import EPIPE

def load():
    ppds_compressed = base64.b64decode(ppds_compressed_b64)
    ppds_decompressed = decompress(ppds_compressed)
    ppds = pickle.loads(ppds_decompressed)
    return ppds

def ls():
    binary_name = basename(argv[0])
    ppds = load()
    for key, value in ppds.items():
        if key == 'ARCHIVE': continue
        for ppd in value[2]:
            try:
                print(ppd.replace('"', '"' + binary_name + ':', 1))
            except IOError as e:
                # Errors like broken pipes (program which takes the standard
                # output terminates before this program terminates) should not
                # generate a traceback.
                if e.errno == EPIPE: exit(0)
                raise

def cat(ppd):
    # Ignore driver's name, take only PPD's
    ppd = ppd.split(":")[-1]
    # Remove also the index
    ppd = "0/" + ppd[ppd.find("/")+1:]

    ppds = load()
    ppds['ARCHIVE'] = BytesIO(decompress(ppds['ARCHIVE']))

    if ppd in ppds:
        start = ppds[ppd][0]
        length = ppds[ppd][1]
        ppds['ARCHIVE'].seek(start)
        return ppds['ARCHIVE'].read(length)

def main():
    usage = "usage: %prog list\n" \
            "       %prog cat URI"
    version = "%prog 1.0.2\n" \
              "Copyright (c) 2013 Vitor Baptista.\n" \
              "This is free software; see the source for copying conditions.\n" \
              "There is NO warranty; not even for MERCHANTABILITY or\n" \
              "FITNESS FOR A PARTICULAR PURPOSE."
    parser = OptionParser(usage=usage,
                          version=version)
    (options, args) = parser.parse_args()

    if len(args) == 0 or len(args) > 2:
        parser.error("incorrect number of arguments")

    if args[0].lower() == 'list':
        ls()
    elif args[0].lower() == 'cat':
        if not len(args) == 2:
            parser.error("incorrect number of arguments")
        ppd = cat(args[1])
        if not ppd:
            parser.error("Printer '%s' does not have default driver!" % args[1])
        try:
            # avoid any assumption of encoding or system locale; just print the
            # bytes of the PPD as they are
            if sys.version_info.major < 3:
                sys.stdout.write(ppd)
            else:
                sys.stdout.buffer.write(ppd)
        except IOError as e:
            # Errors like broken pipes (program which takes the standard output
            # terminates before this program terminates) should not generate a
            # traceback.
            if e.errno == EPIPE: exit(0)
            raise
    else:
        parser.error("argument " + args[0] + " invalid")

# PPDs Archive
ppds_compressed_b64 = b"/Td6WFoAAATm1rRGAgAhARYAAAB0L+Wj4EDFNgFdAEAAyynXgKBkDdmW3aFdc8fwxDTwwKkY3HebbZpnbD40VFdKWqM+K2Sl3SBGnakMyqx/PqQiI91AxNsvjlKfQW7XUyzl/ENcve9xhFbma8GHHDyh3kJUZOHvteHWzBbS4fXp5opc9dx4nJ5WthFLngn36qwllmM7h5EwQPCEfPE4lQzlFx7gsxjJHaELZVohy7HctwrL9dSSU3duuiQcSMfVoI/FrNMJ/30lr5EK22jS7Ax/HHkka4L9uSG2PDKtOwXJ+/Hb2ZIORKePTHKlgre+gpRsbUyA6ehrNlB6d5cAlym0K8Q7HgbzA6nZnMqoBI2NAztZao+1enAYz5sdQ7Ru2Hb1plouUHrBC6FytckXc3CDNNhn6h8xODZV/pqiv6zRMWwRJWoR02Q0GY+h52HkjwWlhUWlps1+4/Dz45ZbOdK+6pIy9SgV4Ng9bY75HHM1oYuZKtcIkweE7QgfrxDPoU+Oj/qLUacqcIAaOnGWQrKp9Gm4IAf/vWatNGFFMxjaYpucyYpBVf3lpv//7Md88JfeCfAVckGJ6G/+BmTLiDwE1WE+SJFtb0seXUHQPWlu6wTzkShiJfB+gHgV2mQ1Dh4AqL4gq2kZvSje25mP1GZ7AXe2X73DVReWKZQto98m7pxcDTCpxcYCnHOHIY7mPLb+M1dNl3GmglaWxdeP/Cgw8i6Z1HAY3SF79HwZkIxL67BL6erQ5jCqpb59vrKi/JBwWNBQ5OV/5pWo4If9Tw3/E3O8jMhG8yf58wzC2/2UPDPZAV8djhjqEMB+uaT/4skgpzBHOQb+p/C2EnZnwg3OPt18+0lALk93aDkQmfG46uKvyCifMsGf6nBn1F2gvwPhgoqhGaSzTbbkS0/ChOmwEG4cxibRl7eF1NPl6THNysjZgbvTrzjSecCPzEfbxDHs41hL39Ik5K4JA1C5PpLnLmRiKdS6YSYwrbuXNxuPSDI/jB4nhbD74QCY9WlKiJiAI/vTY5QbByqotKelQIYB2JkcnXe2yIXSvYAB26tc57AAMNdC2qzsVUZAnFV0FudvS1Z8PRMO3fayIWwzCxFJWxmb2TP+W7h4XtGHWCk8665gnm9dz11B9JgwoKwZHUYZhDrRIPvvVK5dtdTVmd3Wlz7cDcU70VCwf3uiMUD1JkK2FGSHZY779T3J/+EIzKrCixLnCX1iym24zsaLN9JbdrcB0JngBZf57eSv+o8iGXAZTIuIgHNntbUb6in+UGjDOA3cnY5khmn4oT7rirp1inCt1Mk2NUkm+yJZrIGZUWlWfFW5MynpgJdw4/in2IoI3R80Wt8ohNu3+ayZsysFx8qbB3amQNvHM6yJlrcwYuUvFnDe8j2azhdkHm5eGzJKz8+THgVFV4JcmLIAAP/h+MQesjS42Li2VwJeK0paW3i2EjksVH+IZXut4xB7zfsIWRLG07H1N0FDeUcW8GBFjsT9pPmyMN8D/kKjHTzwkp2cJ1agPiUEVrYx1C/Xr1XBisPrJXtVj2uqqbbqlbVXA/wpDYRN7HmQZO+c2RUgersepRfEpKA4QfxHzyzg8GLd4nKBrm+LEFuvjLAev+NiSAW17jib+2rpGQP1+Q2FuRe6a6EgIyDnz/Sfklf4cLx99ZcSLmcEyrpUgl+aBISl03VD1JxDvF2dQ9F7dDSf26XgNpIZ6A9ApDoBpud1dA6cBiB9piMbfZ3qvdtlnDO1OHuHHFWzwdppaDm2F3Dkwv7q21bRkY+HCmohdHu7tnOVn4BAidFa+c99wlIAAnR3z1s5rxMmo5JPVD0Bp7h0SPtWR56VYB8KRQD3eBFWKgjoozHgOeqj33DpTFelHY+k/5tPaBiZlxKX0nw2vEFGLZXyhWaa1jEmlLI5ct0QlkaT6osSjJmvtB1tWfOUHXVF0LtzQ4EdfvGbXQYCPknG1QTaNbYmfMZgVsQvd0UIGQ54PfgZ9gTGWoM0jrhFOku5btsC6cbRHe/dP4KnDLwyASyjKz1L6kNKKSy7S0iiqnTa7Jx/xZ72ncfbdiJVSZOYrpZtGIXg0xiLpxAouLnszBxqkP7lvWbpujJUMN3HRMiOvDmOfMCgWBvSRbiya+AXeKpT0qaQ5TJHXYLYWZ+VxNbIidzkXXr6lkgKHI2Z+TG2o5Z1j2f2sq6iso5FHL6FbU/AXDx6CicUUSWPH6zDFt/chrC9JcRCZz+iRWAi0D8QY163giu/zqG49af+vtYQpa03aQPjIU61jzYJwn1T5x3DvJTfWlVX05KhJb4y8xsmoFQbIKIrhNSxHBWjg6KVh+LRDn0yWzpQvOCQrd++6ikDYwaq3/G1BtFTRFH9ZpciofuQIHAL+grw1EA9Vn47Rvtj3C0Y6p/vRSw9RF13/CThaQHKfgJ6wiq7PVV2IzNG2W17Bjqgo8r8geI/CJntyDrHSVVA1VU/7PL6rYRxEnVHFSMLQ3N7XR6hFvQOChmTuO6KPoc0vpMDCEXzMRRM311Zx6m2LliBh/f48oYOSqIpEd08HgfhZs3QQ9UMgi52dvRZGh8uvrcmxXQD9TrPPg5mQigLSiUScUSLEi6PQ7EDYgm/cxwMwdLBWdmRmjvzhH1ABAzN3NS/FyIhzhXYYN5PZhhdx4MFIlga6ESN+zVJgMP9hso2gkD9w+YMkr5dsElPqSnpK35oEo0R7nTb9Hc8J7HqBJZFZgT4rsp9QF8cMOZgAaTQjJydQq5sYbotuCF3bDEKMiT9klI0qSt9daHg8wKvke/2niJOLZvESAfJtijq/q7Aj4H8b6Xj6IyWQC/FA+qT4yKZEnBzOsMgzwUxWCxMsNTrJDbTAfXu90sL+WBQwBZl7DsMqaJTWb4jvEbA8qX8ghGQNF+yWTc7J5AM0+RmAuoytZZkoTxOPSQUuWmvozZ+ICQMiXy1oXsHOZkIFIgnXEIna+ycWkhne6zCPWK/lnMZszoQhbd4rR26BH3O/iWqkkyur9s7T25L1p0JX3j0veRncLiM1rdBXSIWrsjD+kI4lekAsVNqkCrMXyV3qYPHiaDd23BKnmHV+V9rFVVFN+yWsabZfeqCJ89w83sTfkJIfsn7hoYH7kygTHtyvq1e71YmcaRhKL/cqPhriB6fy8D5NmbG3NllQCD2m3bLtTKLQgUTTUWjoifXMNmZoNMDyTQm+NKcCHiKxSoqlXAevOHVX16dxAk1OmFtmdUErw7tRMUVUkg0VtDNsc3wXl8SJHF0H3Mji5hUEMUXmrNO2kbBwvJh3SkUFeiat5dSsoOg1EFpzDDW+8SsKuM3YHLpncRazY8H/Zf9l291I7emEpC2bx2eO7hOIm60/i9nKmfDaUxsZeDq9J1ELbo6jPVD0JPkFi//lyEL0DCi1BwBRrTo2hosRvIYrONRL+e4lm+VCbfejQDIFh8BNViiaj/wE6KicC3hjMmtrnFB1GNpeF2j2Ysay7ixcD9xGrqa15/ul8mwK8DngHnmGcsGpTeFvEKTBuzJk1Xh/tlPiyZqvQ2vP7NTBGWQE1SkswSZzf9ertlfj66uMmMcO2VBvGQluT/KlNZTIHYGi21p7yp4FOtLen+ybeF+FJcVUxd/T2KtTgnyPbklgbQHGwVnmjOXPWOLGzLtMFJHRlLtu5NCbGMQzsqJdH2I7ayC58QVJrQqMomAQbMTu4vdP/2dw2nKZKzbeuI57m29f/PLAY2EyS+3SBsYxXRoTHQP0fIbjs0wVf1wrI7NgV2LJi/Vsd+xXzL1no0MY62/8mpyBnz/u/OfHwtdbgBcyxfA9vrfMJPtG4UkdWxIHOx8sG8eS8/3nI/0B8I61nItUgeZUSPJC8QJEyifcw2bxJwXUBJSiu9i+aRYd0T23lcM2ScWZ1+nIHy684gerWSxsG6M7SxmbMCiJKVDPWlU4FHjOaRTKya0iO4zgVK3sJh0yHQ1lXX8Ul5QA8S5d3EAJBZPOIRZ/gWXXVBJIWsgSyZ71p7IlVaiFKNKABVKXN6ia7U0xCcn1vYyTfxc/kJIL7a3wkjF6b1jdpxMBZ4cQMMhU8BPwDlPRo/T/enHp1XBNQfRdf5SWWluI6gDnRRLUm/YsNCHerup6Z+c8kMQa788/RNjeV6Fw+JxoDETa8+VAA/c6SyT9469Z6cQ/V+hAvZ7+8sUGHnWKUv/ySoCQP7ZvKmRTpvF0oDuNkQYtr3FGEw82G1Xp9ti7G7twnyFyzpgY1cVzq47cNnthheW6z6EAceWnBl4wTMCSlbhjoNeh5qfUMIf9mHfpzZQOLiqVL9fNSEcoUXk5MOQr1qQWo9Dov90MP/1P/lB858bv7WlVFMH93JHYoXfRppaqXyh1J+zGfOhNxiBSGQ3k0CMr8+pPyAz0ZI1iqM8Zfk5gc8FR4VGMfC40FcnCUI7Qp563xZAOlYfEiWwUr4W1ug8uYQIn71VIf77EdxOSbpgO0vVRDGmf9XFIj0uTQXZE4jruVbEdcQCiEMMAqeNdbPOrOoC+n139Nwhr0B9/TK3a5Tddp/cR3oBaLiSTgkg6UmxaeAUVNVfeMTb83MZKLFbMmkB6OrNcZ+aKmeab9iPZoEJZMhiNQJwNeOF/5h07Z4Mi/G8iBrWe5gGxSaoskXfwaU1C7U45Za9NdaSRNvhkdzXv6h+Aq+j922qy7l4vY815vHq0NcsSZnde4S1aPa2eZ0tJPDf/JzYUSqvJJPLnNMS/7zyQYO2LfjROB/YeJs8BOhvQuLH98nPasYndH4FxBMjkXin1c+TTReZ8NJrbmaCQQX/IETyTjKhvVKZbeRU6Ku4p3glTwDOdUFzFwT/O6O5pxEHJKVXkv1/J7dm0By6YG4l3zFqAMHDKVxvda1q4wu7U69mrdpCdtjrFcqDYz3pYRVBlRUiaj06WCyGkSiOKZsOt5jDCr+wyBTvqcbPfq9EKjPzYEQDRJPlLZr+tZ3p6wxr+ZaNBZv9BOW/IXCaUbCPKbCUl6rditKTPJ/XuqmfnVUoMpEvD7fO/UhNpgtdnfHg1zEo4/uTM5/DOZSAA8efSPCCNZh6Y5H0zfJHkYP5zKSNWNImKYsVJ2/3ySGyJ07J5l18PxEfp4BQlVJN33Ri2ZPwcVZUS8QCr/8C8ge5i5tLdES7gsMTgRQ7KvA0WF8blpDqLAiDNUWygGoBIFXjrK9OQ+y4YHx09g0zBAR1ZRSKDzDt6QqRNzmryHmAqP8AJWKuxq5hQPiJ2tNKoVtnTJ8jF+wvcuF569cM08F3/f3QDE2JSL/4qk4a7ZBSku2jONo2lGFG+ItbSWCC0pflFEHrJAWNXVzGpVOMSgOKRjOjXcZfR+K+B9wR8PDAR4VKDy7//sV5hf8XsO0tUTVHxAO2LP658uHUJLZS0ypME9JZQkeux3whTOiztTz7h05EfHIQPXD0MtIKBtmA1/I7pUv72FtES0k47khObnkOvpLJdwNdCmmkpraoio3TeDUXQL7yZhlFVFpTHOTRTJhrG6X+4sBwUHYVYaEQ2glUpltT+mBJQ5FMzndWUCA/ULQ/P0EE+aJXGiqwEMdZdffANddMCNjeNmuulFxVqfAZ5048qQsiKqcTUhZYwdGx1p5zm1RBGlU1NhJ/O5tqO7eoHmfSL+5VszFCovOSIpKpzsendjQNcIOZ5jz3yEVhNq6XKFGVRyI4sUvY+ak4CoMRz7hWjFIkZLVUtv6RJ4pq2IPHUrIhQQJRZ/G9gWO95z6vNW9dE8NMqVUrL7GcuzL/zniZQGHovhVa/aiZjtHpOXvoed7Wk3urn7Juhj+Hmm/hWfj8w9ODYgFqDKPHZ9yKIirt4IOZMmN8Nyb2uU7Y/0UgUqXttx0XK9Ol2bbM7ElbAT6Nf78J8dnDVY8ey+2B6+vBaVf8DBDOR780hIjkJzf3vx7agtX46kcm3RRvyEQaOYwui2JYvhX8I3rH6t1ghOp+u31ZCCZhfSPG3nyGkDXyMKVBmasP5L+cq/YwsKjwnRhLteFV5MLs6OKrFSVYyHZY/3X98NKqDjOOikMZua2JnwBIe5n6vCk4rk5s+pce06UAoqmnCH/Xx04Om/VOkercnrrLL3ixZ/IrpVR/ezAbNmb9cIReuuIFyJmydN2hVSTN3ew3LQwOrUl6G+trKiBAnemi4xXeZjGinuzYBwiu9CyDdbWkOs6I5cGOIy0dM8CvyzXhVhuohjpk93Dh0oiozo4ZpNBXvtCvO4gUgac0zVr6w+cbD0Gji24q6QIwdGxNYF91BTUS2GUN+EV6HrWByDEYsalSy9RZAxlHVy0xop3IUgQf/pElC6ORBqFw8nTFU/aY5/CG08AChbsTdTiM//ZF2svPzfdCzBDd1MX4I6KY9ZEv4cR09UTzN+BZPr4iJVJjeDqG3aMdH7awztHpiEBjoCNxr6spr/dMgZKYz6tNBeIqxdiSOPbCJWPI6uYP3A8TW09Y1IvXK/SbI+iDyXy5TGJtrMjIJOFQtmfvZtE6NLxL7yxXNy3fsow8pnI61bQJsaDkSnQ8fgdLJe4o4a80pr8Hl8EtyWXfmIaJu4KM9jIV/cRH19XctCpdtUi3NsrftxFH+15YGr+7okmEiDMH2IJgoNSDL4rm3NP61rgpdc9tiS3zVLVWftbWkkycTbsazuYZ9HS5iSivHelW1ztJYFMq2+QSYmRL+BQwyksMrLKDPz2z2G6gG9dvznHg0SYkNTVnf4sMByxq60FE8nhF6E3XoN/amHAbspvDFaHbppyr+T498iq7qxrgfysK5q8f56P3B0ZoSz9pbLJ6gzx4dJrvoJIkb6wrVW9XsPFnM+TN2i+BK6TcZGb3tdPP36/j6kNDEbrn7cCujd1isNlcorK6UMPy01zeXN+daBNw6rmnfgDMTLgIWdZTQqWwjMXtOy7ntBHQW8n6vCxj9xMjLZRVeCg4jj0ueUfYtaNzp5QB3xNoGbiHQXACvUiHqgiU3OaDBxUgXRsKyH6Of5cJgiaEn1hA7frzLBRSfcjfk6l0g6dRLUKOVDoxJafSM8AA5tLs1r5DX8zksSAA82usEyS+xxwO0rwFJB24CEUGgUrPrt/lZXGPWjmYyhTFb/LwOsbTdV+fqoF2DJuRRB1M12fj2I+SnEGhVV3P/FwBkEmgRsW+Nrpw2Wpc0TydyBnXOa+ebSN5iSjDl4dw9lX245QBfmZ8/8Ncer/Qonk9/XtUJ/m5eWTQGUN5iaVG9pPIn7b64kVis2g+1ghOtseqzHlULEOx0JcSlF7tBT3yxUj0Wyj7vQvgXs5MUQX/YYSVxWt95dbgzLIu5n/CZi1gVwxEh69GBEYSTNE/Ow+u7cYaem7PpWYoGVKXF7opBCijSEl6W7nDVrxO4wgC9b4CIBA76uu78VWSrQ0BotRJZ86NSHk5idc0C0b+DSAn6Oj/6IHqcF55f3UJ9LKQwDBHyZSh+1zbzUYzo1KXWd7WexlOeftnwhfF1lfjf4HbhphCCsh6V/4vEBCIcVImIC81bu2c54Gpfd8B90d4uJy0CdrIhlJbpttQe0KWEgzOTmB1YGizqWn4u+vcRc+u2eKK3CoLeMVako7t5wjRsW+geVn0YNv27ODT2kVvlDsiTtjH9awtow40BmfBIG0eXf9OMNT0dDqc7+lF6g35/1YmKq40qd9lvnWgyCHshwA1lX+gpyvZo/LeegxWzGof/lVK1wKRUvCGOo02BlKEDI4HipvL9F3gYF3t8vLbssHv8PhGLtZt+Yzh5S95kB30ZDnVbq0HQaGfg1rmSo/OLMKjUmfJ64LWjkDGp+U+n5ws9qaU8lcVp+O806Tb8dHy4WuNxIJrFJqkQFHM8S5wHpROCHz3NkxwOvdyoQRrwms4uJjoi+NmFyc8Es4gNI467ySQdTv1u+R6Mw11klhzLlludmzkpeH9gEBNp+TS+Dm4SO6GruQZMdG+qGAeV+uz0446zzU5mdiMRtsKD1YLpGJ1wqs7p7hrSU1RWed62Y6bd/CgQ3B0vl/MmjPHnff4D6cC9uqRXKxxzSSUSC/Q1qGshKACU5yFJ4asU9IWBsBTc2SuW+B+xYZhTIrLfvntAil9y4Nb5HRUbHe3uG+dn+ULAi7Fo1XrF1LJFU2sq15Y04qt4IaXZi1cRl6VhXD5uiVQvdK/8pUuTyE4+OeoN42JtQ7bOGUflB+K48TN63eeyS2/UzGOZoO/63b7xlp/fbENPJig2AWB9IYxr8Uj8YmsUZt3htYW/zVPmuPwo6Mwv5wqLhM9sFjozdCSXF4e3olG800t3om6tMXDFvIoqj9W/zT1wKau+YaIzRo9nXYorOpIHKXaRtHN7RTzqxdAo6KXzf4xViTqT2K7GjRrL6UkkGqgf9Fc2i3CMNaVb27aPOaWAINPq/h8X4xZp+tpK8mVGp8xsONXGVyWc5MnMlVabeUgnOeauMLuDG6IhE0Ta5Sh2taM49+SKoCRwVt5Wgplf0teE29mGxWZ+FWIGcToBvfAJVl14ovUmGLGPGqa59ZoCsmtTbg0qxoQSYti7D48AQ7C3Zy3vHDJoMlaKzkPFU0xT2pPvzJFzrBmnObuGhLuZw/RfH48+bHdcAG+vn0fNPaQzO+hWoYepa/P92RvOtAqGE0CAvL36vQ73JIBXXHxCFHhwVYP9MnIHMx8qRDFL7lSjhX+zDPeyQUxxct1uuVA1waxeN43k6wKi0zlj7/oV/+sS2QmhZCmD9BsHETZ/A335k1LSRA3hF2GWdB42+SocdpqguWIv0da/SHbG3NnPiOgDzXf04wrIbBBBI+vyZHjBU6motPao2JrjNTgF2A1gGFQHMLyvKi9fRmfcgjgksva9TOBtt2Yh9YuKfwel51FHq/wHUAdVEUpGvErveQTYsE0jCpOF5pevl1PruHK16Tc7Q7+o0cpd8Kns4iHAMt33ehdjKYdFktJt+4oQDURRoCFGHNl5wknpPdxHFEAwG14dBZJFXPsHXZ6Wk6clQblIKocysf3OcNGYCJpeLRio/R6IEmFSK/d8iQy/tLz48KEemk0kBKzBm5BcgaqROC/jlkRI02f/Ndi3hSnpY6LWu99xs/6i5UWWTSqFeuyfRHjQuX61ZwK0QPkf8OcKzNi7uFfm6PLhpZEF+nwnVRXIBRbEz7TWEme0rLJ2AjSUPljY0Ugc6++0sv+NGda1jEB1eteVyHKpFxdheuTUgodop8ZdEmpbkNJ8CEsRsbIiOLnslJb1W2VF6dp6tqTReYjzos+h2f5SmWPYjq9xzyoCKAgMNF4CydxwoOUAUQMW5IDTdTBuBBXLaY4uWubHuu4qdr7nLhdwcb03yM8KXZlBTxnLqAEw+NliXJUX9L9l7RhfT6IYJZKdNs0qUOd+bnKUGUx/OhGQgGiHQzIeY7y/zip9lmDscuWITkyVzvPALK+ZWjLeyYpRJwANFtzQ3T28KOiGb/eAtpL3GC39Q4QQBxqJvo2XV9K1XCbJACDOWkYceZzMBk2ImZD6RF1KvPyKeGUdJKbJsuZhX5mD9KSOa2Tfvdt8XOOc6PMXV/hO00Q/TFU8DcnDGkXMmLa28/UdyamNiMjU4BBfaSS41Oaq08saR/mSiBIuOKY8ol0sotNmPw3Y/vSr5W5zD2mCG/ryHHf+/Kv+QQ+dEJ6sJADcW32J+UeYkz2TCo67kyrufW0Gyg8h1OxdBX4Qp76X1dWiBq7zf+73cjeaDi4wE1ex5Qe2BhVSAoUNQaOHQhufhub1y7bg8NHipFDOBSWJ4NlkZX8zgXFqiRQLH/37EgLNNVz3AQNVEe0mfF2NIJO6YD6hMi/w0WyxnRAR1KBGko9VGS1Zp2jHX9bM6wvGf3cm8e+0IhiR0tT12a/xohoOCjFZSOA7YPITrli6RXx0Z+XutiYLag2uOi5rFcE9W1Zv1VL4iYXnoFS3hCpkZQ4ZnzyOzokyyXsivrxD3MnQ/tw4SzDTyT/WmUdiecUscfQv7A0ZFtJUBqwUA7pll2tj/hJT97nEHHhVAoCHQiqY5Xv7t03Q1HlUExb1JlgpmVojgtpR3e9H/DM+rvFBNPry/TuiFd1GOMkO5WTrW5VCj6/+GGpqSlYsntnsP4H6pow6/f7cQIcsUHtj/gnd22Ows7ncHK2He2PrJFNjlr6xXtFmiGgYGcyexozJ28QiecjgE9/z2dGjUGTgFH4su3NqEy1q8I3zHcKieR6gF3kzNAJ1TbN+1kcopQ2JrU3XZcbYSYi8Wc1HfhAcBXiY/hrOWKi4z+nsR4oBr4roiN/ofKiwipDwle5Kv3K+jLwRZVPLA8+08aRTdGpB20D2v0tsQKqoGGvgSB+7MkvoVPjQkR2gJPEWZtNe2r02l41aFaMyZIW1f+J+uYpkQ2WhoS77pdmEqcU6U0j4gPk802XpptseaJksxF3csKUwBAeZstSa0DKHeaWL9HsIT8Sx9o19cSXyPU9lJfAFxHIKk1WMZWP0ScbAPuBOBSni2TAl+KC/RaxweKu1Esv3plwnpNKoEzah73V2BD/xe+rzSxNSpjvPztoYrIq3zPMENb6CkXlgZF5DGkYNeFeOBmwzEv2It3NfFOGVrZSxJn34HZNP2QQMrOGer+7+I15Fas4ItkuhGLB4xuuk07Sr9OMjf+Tv8FMP+RGjOtwvdST49Bem7oJfNVSL8dLg/DNZ0lkTvEIEEBKBPI6Egj2UhmCuhk5sI292UBEABsAmk+QWnH5nqEp4a85WgIjrOPbgDaMRnga0QryP9Y8i8AMJahGkHAU1TS0/UXpbhJb1tEzZ+bHIwfIBcw/QMHXgWw+/a4PBKjqBIBGkc1JLrWIH6ARxnxT8+kPav4X324Qak7Jv/2BID+GX8s2LLIUg9p2/efpf5Ltai/Ptt86zFdAxBuv4tlsZZSfcYmrXz5Jenr0ILgY0klRfd3T+sVvASmTYlJygNWx40cPHH3v3Vu20wXS+CjxQBouVYuSrLxe1bpSCkt/QzIU4/z1+I5P600/dXWCElCwAZVwiAn3pMNYr0GpL+y1QukTxEtJd0yCK3uSqxuq0HmXHCnqUO8TDkp7pGlpmBFUYJUslQiPY3vb5ELcrB2eLLFoPwcBcspUH+zwcHSKTzACjVizA2+s9FaWvhBjh12kyaFpVZDzI7u1FQY6yD8d4/6Junc8HDeV/YBYbZp9IoemIaLCO6kZGf966RnjH7j74bRWZpBQtwGH3JSNa4l5cxvWD4o3UEw60KkEACnAGDRlcUDxdl4H7YT+uyEgFMeKM8BiI31sOCEp5TxIYYWfI6AAWL6lCQ6RTdmrUJ5sqe2GE4Ei9Ja69GGzNaqBqOjBlnz9ODZNwBe87A9htJP49irmHF3hKTQw2oaZ3g5GTKX6wV9hMe0RB5c3mXyplytwcDLfxdS48FwpVA8lhtY7j8nRpDOkQmgVEUx0axjdGPwpWuW2iOt2Y2kyGvxzwHH8jgIgfzxj2eqete92kxvK+ZoeexhoeawzarvWObj4BND+o0GFascqv/7qgJ53M3d+6c0FXl1yDRT0PQHYRrop18fiXmWRo2pzQQVHJU4zWgaLFhNEFGnzP7HUQxjcYXdZ/I79Nue5YekydadukMP3XDsSJvBWFmbQTxZmOF3oF4Jx0l47A3CfsGwq30D2HuMYy+0Z3cRx88lmUTM6q2Zax6xbmACGA1KDr4RpzXw58hEA/H6TuoeL3yRV2YOQqhT/2fqwgYq5OHw6xPB4a0xaCRRc2qYTtIY3a7A+snglTiTyGTQGkmQj/lUM2cxUF1LO1T2g5NGXMNnreAa1MJ7VvMmwfwAxpkLWYgSB1/IGIzNPO9Co9EeqoHzak11JhX/qJ9Tdgg1Dk9YGbcKTgmtX1lVbZsRaPpdVFkn+ngyE/jdkq3whyKQTayMV3Hur/2tuGm83WRmp8teuXxEMGJM5atWjwmST1P7zr+rLVIcepM8ldcwd6XSUEw7+9FrJL6MQJf4dKCnPYFZaqR07L2b2JTIDlKRJl6GjcU+8LtuYpfLejcsthm6lBQNYIA4WSzdEKpCd7yIEOM9lkZ01O/djYqOty/v8BmHEwxD0zRYlKtgihpAT0eQ51GRMaQEZdvKxiNwkeZpkGFeNj7kvQ4woXyZibvPJx6s0JZ7B/DI2ZFL2tw30pXO2MLP+7kSKF80/iLpXRgVXDIxJ/6v19F4eoO2IOud1Wk8PAVBzYOjkdejSAOmqfTfb47fh8wZsBYRLm4UtI46K3tmnJJPm9nd+MkVxGDQEpTKOFIXUE6MzWtqKjGe8H/ChIAao2ejAfyvva3B1dCYYSoTE5+iMtigCdkRRS+PDGhuXp/ByrnIYLGgZS0B562HOZc7odud36RJmh2n1UyjNCNPjDmcoP0fbeBmoh2q7+aho1zilWUcuZKkG+/8w0DOFbXZXsczwhNq5Fk21KZt+KhHHYDK+r/NtuX7dgKkFrsnRz48DYidNDBfXdqUlYJPFsmoxwa6O0mxolkuF6KLtXqMDQzow7eXlKldUYcHQevXjlvJxdvIUmETSAUC8rDP7K5rVEsk0diA8xf+67hMap0MYb0sEiDBAKzvaQIHcrLXrfdIuKzDQnKjVC9vWRPi9ATaQVrOI+T25RG4FdNvxNBBnUH7LsLwxA+WvPoxXqPA5wqbx4EmkaKvkkB++1uRZMRFkarHpNUj5LHIEG4fzQggRP0/QXFF0IRKAcRs4VODtMTAgpVIVE8OnIXbcUTge1+rzsWfI8bJVVw0E/rtV8FkkIdy4JIYrTy0luwwAiXbB1UODOP4rtjQ8+6VmqV5EqBuvlWRqIPUV3FtbBEPQhmsxRhSqCM+gLQKiX6y1AjdsBvHpkV4jRM61zDzJGyCy0bGkY6T5khrAfifnhANJGicC5XqKns/axa36Yg0Vbe89UH+D3KIV1xM9lesS4Ah/V7lFW+LnrhNHr7RgfBHWtHrYbz97Qp6MGBFQz5eTYI3QjsAcNoBVLYSXEretPGSDry9pQIftQx6q+BlQtly/UxFtTEnHrFPa6xX0a0/taqfsJYLIztxocCppiZtneVAzEVBi646R3+uT5eM4xhzDzDNhDCiI4JXxV8J0G0mJXJ31RIhKknx+N2y7eDHyEuslGvp9kXVZaSYg6Wt3ZbCsyJlvxi2HXhB24Ns/Wl3iHemL6/7ojoZUFgWXdspQQ5KOUxhMp4aSsHq8N14dqahsMQpXzgn1iW7MFxllwLZS2aLYK9uHRXZzaEau8aJiN7U38osqbbv0D9Q1srBEnJyilDUjVlaDtDKzNyM3Loqp4blfYL6Umnz+UKvZDdSLqrMttZnTtklLVuV+yOewxVI8ZZAYxabPucsWN9/60qcUAkYQHUjZzzBw6Al5mP6V/jvgyR3YFsNGytKHxOQaKhPNQdH/T+0vKenHsAH/QfwOu1EdJgG9fIxZFanVKM0+qO8SNW1PuzuYRkwobAJovQcuFIrtQVnwULfZtQDBfg9ITK1hDXT6sVNxOpiCKski69QxcM79Vv9z1z61MZWm+Df2jmLOHL5cEzmRrjtZ0d3EW4i0G0pJ2KBmNhBSGBWvFkCf/B5lx4Z3uW3PQQP8BUQK5cudIpO9jL77KNwYZYQi4Ezbskn5LBHxKfyUYKzD90RfksaXLfoyuzzEGiHHJ6VD5mS5BLLQyzs2NdVCeIFiuCTP3L1+vGJ+NlQtyVdqhxVMJe6MJPU8+x+dmOI+K46ptCgUDeUsoUOVFh5qb7HwfmUb75Y3XUkMGE1iVFWn/IGMZpxYUYb8oyu+waBa7StLA6RMkavaitHM4nY14431xP0KLOqrfS3Ype4IMH7iJEgdsz6ms+tVZ/LRU1+rlqk0S9cKzyNLFBtkDc0qunVB2tZO4a853EgNuP/dfHsY06PB5zTsqfXkMLGfztgAn1wLh+whRN5FYXZxRuOlfkNL/x4xBd5Iz4rLGkIm2KWjqK4dBEghk5SqfIGg9ha2WKyqX0Zyl3z9inyJfS77MXJBoxM2mSme1AyeJb2Oc65Bs3oh/7jhu2t/OTio4l1nK1/Vb6QlOf9F/puUHPEpfMWsXgLXNjcXMytOt9V7qzV2TKqT2Aao+tvBry9dyx+Ai0pv0lBGonb2B0i7UQrFRDKchE0LxUzUtiTrDORPbaktIGROX5NHtHLr7Un6F9ucIJBUW7y6k40NgyCrel63asBb5Qr+j6f3eUZuUlmb0SGy05cAwMvVxrVJpjoM9Q9an111D928PnQ9IjPS8kqWmPhgoYKl8tUi5BBE/HPGEcCjY/OgVYN4ObQufAmePWPhcyOXg7PUh4s50CBOwgugohktU5lbjJKa9AgaqRDVuAVWg/76SAgbAthabgZUmT6vvCAg7XsnJrzlsu+xmPqoeTRUQBZ0UfU69RoX+o3T+D1oLF0oxzuocMvpIYzl1YaGPc1KcdK10C5jwI5UvDH3l5a/QyXONGvMAFWJD29dwVRzu341MkAJHZ0j2nccvH7iwE9v2ZCMLIUjXXEJAY3FSvMfJvL562k6ZuocNoqyT2Y+WkKix9Jj+OxXWa6P8bj9Zkggoi7JyG/jn9kwQUWB0Hx0cWKoPj7nzumbiQMHnsEPaNsytl0D33CQcNVqcbwqcDManQWGTSeT7Q4ViJRnsvjOR0iX+UAdnlrmKjJWeviell+coXFpa0TwGj22FawgbodDJxQLzzG6AkTAPhSfTZUqzMcgMnYx0SYIMDwJN0rmh7QVH45NljQmAXGwpYt1zVnlL7aFh+xhQI9yh3asPX8OVfaCkN4eSCDKNX2WSGFKMXjhS/eYsUNZh3cgfi7bY2gOA26ByFKKgfpj7yIWRHcxV3DkfWGBTJfwgrO+UuDhit42/tZEiToIih45KknGfWEN92gVi9dfSq4i8ekhcTNwRD0F6QLXwVDjXug49irSBuzrP6kmKRjc5nqVcsKPY/nbG92ttEJ1FYntxyEPEDT1Ory815cBW75mVwmphsYJxTg1NirqeEQTt9iciKNxFiffSfFpzxKmD0Ai/cnxbnI/ZgAHVCc1fxxHVoBXlYz+GhKyoNcIjC7ZnySQVWV/ful7Nf6fqnhtr+mHSrEqrvU4lyiHs3WYfuFVxd+O/xQuL1G6WC5332LLwDas0jVeng3ITPDfZMKUtmkleM9N2gxbIcUccHrQjpbxxVc25k+hfS3eFUlq07r6Xg8/mTVMZZHhQQDs1BuC1iCfEyKN9/+yN5ze0GejFOUpOUfBT5CYUwHkJptli17c3QfhDU4TKyTBeXiO6zrOuz8VXtC60UQOO7tUJjfCFhAUorREK/V53eZHZ+PSiTvcLG7lJ/FSuUUGpJcNFtFP3/wNgnKeYRdD+uY8DyDZv85oC1HAESxerYxG+wFPujoBetaVXN0bP9Kn1h+89+nIsT6WkQ0Hk6g5d8657ZXI6xwYF7RNRJ2QjeMbtbfiXfnzLsK2Y9rURWsGOEZfY4qAiHnVLktDS3k8Q+tHYFQxorvWH/ewPHKeNQMw4QchtH0+ctInyweuY4wP+p4U0obK8iqo+icMEQd3iIg5kHuMSyCx04dOr0mHtGpNYqWws5InWfwjUSaE5qQwDHzWfLb40C/qS7CpBLsaBogEOCGLoj2HT50soqHkrnpNqdNu5Z3iEI2Qnpf2gHQ0hmNnmfGCH4W7kKG5mbRTsFeyrPI2FAGQG8cCXbN//+iOHWQ4sgMR52h9EQUylvdMy/iudbJEW2MEF4K8nmUj6pO78lIgu2jDFCi0KD1pcuoyDKtQRVppAXERVijx0A+f6EBGteWbWI7KgBIgW38PwFu+mUz49p4kOP7ypjH/PoUloKOmsZM96stjdUafFA/cRrx2k4hUv9Na8GK09U3+jjTLODtab0pvWOZkAzMB/xjsc1go2XEH5SSJDe7AuxxiEXUD/nda8QXNQbQttH0KA3pNvwPbEPITdRPoYNPFpgOvZbMyl63wSEOJfFeoHfb7mnMoqcB1G/2CkIrLKIxr1JWJb5pI0W//OAkbnpHlS+69Y7kbkwwj7mbTwhAGJWLK9Hb9rut2olFNXFn6/Gtt+FOhBP0uwsqKQnKZcjoH89k/IC1iIBsHUfLkTr+NY2F20rPb7CnkXjaHo6YaIaHvlMeJZN2kJBkdzJZ+u2xQc9tI3Wglx4DLAghkrTdQJLYzOs/h0+S39epxfGv2VN8hkYM49YDqvkrDJaAKOr4G3KuTU5QaUgiYjtigvP1/PzWUjeS2tOSHib4QYU0MGiNlrw1Hcg6vgMGaTlrT3IjqWkeciJjlKDyV9wY5vOgjpe5y69UcETOnvY2reoUUs1x808gsikxd82W0N5x70nktUEDfRK3iD24NxpiOifs1kWu8BuvFEj8K4efSF/qX2aOwwFGf6tcXFtyIDzQ9UB+3KPf5QQqf0GScVgpv0QlcBdg4yfWpee4TuF8iYIzgbqjN4Cm91qcbI5ONxnDEvvU8/SS5BIPElVgaUZHpZWT4MYA+bBEEOMUtrGzA4m5hrisVXfAKJCZfUhf/RJqf2m7yjsEq0f+x/wUMb7k/wRhd65f4Cv3rEFyzkswRB0BdU+TqxOofPzcUigWSkqweB8a3amcUDv4Q29QC7TlJLoOJ5LsTqw+Xu4vYPVCIFLtkEDmYymviGpNQXCfwRSy1NYueVojM3Aj+28MtiJnlYzsfQpjmpB0K07tnH+9FIEhRYBMkhMZA8VSL8PcmWvttZfVtbLPt3Vz+ulXXjBHkN5ogzakCROINFJ9cCIDpkus2zC3iwRIyyyqJ8AtgQMxbXjYemty8a6lxhkJsJXYLmz4O6AFLcSgrs8nzp8z238wHplYNg/Atvtvtx9h/479CWnIxDoeSY6sHc1PnmVvGv3wrCuqXbtz24ngBc+dSwmVsGqUTCX8VRYttzSfdRxs5lI189Scejffe+lIHHXjPw8eVi9ZqPO5r4BJroB0ff8k/mZD8YzLYR6ARufr/X/55JDbUDosoqOzdGEECXDNCqM/mppf0kRVHfaCozKoFMZ3BOBTTC+D0RWLYBzIi2E50Vm0rbzNq9frlvMRc0nafBuo/tx4jw52M+u+mGTrOki5AbTZoMiQdwoPzuyVYFn516VM0VIOmJHKWVvk7m0JusF/QF/v7zCko39PlcWSl4ECMs2slmXj3k7NnY/OKwQ6i4Hvfj5jhy5SEagyhAdG8fFNxTzi3TShrjQvyD6Qwbbefu/wSOmoYoD/qGchKMToJS1f7tP04tJzpkCq/jgryzWLw3Y32bdYxpILe3I11hRYWoWtamIyd+jlhIRooYysqFI3V1vcvsYHAz4+2vGdjQnOUb5JXjd3etSC5Gjcy77nkvTfW9eJr92kVd2L3k+cKHAy/yDrcE5JaMJTY4e6/D0lX4fDtQsgqdTLSQd5w2kW6uhUd1ncsbtIFUtA7B+IepHSufKSkBJP5eFSkY5gH8ngp8WqsjltCMajIt8eYtu9yjJ5hMGu1Fn+kdkmNULAKO8BYFN1wOSjI5NYLRbW1P21NYWEP+gJMO4Oy+726JuNKTScRN/jBe/2aEywZ8mudWl2lZ/E7MpigF4YxQB7cDyiSalVTRjY1h8Qg3OtfUA20EAqYkROu9+i076W1vwscdCeEjLQTsBjhSqWt3L45ts2Q2aBySVNtn+8rTvlPc6rbEniTUWX3zH55VwdxlDe/00FYVq2OxtIuIFJ+FtTKntqsOBt992tK07oNdQ/Ws8PldeseP3uQMfwJv1iJTx6MN5YyG82B39zXcQjXh1+2GeOhB0MZJDGTwy4ZCxAY1yMb3rlKa24DWM1IOust27mRWCWlER22hUHvv4sWZJbWuIYMM79xxfHZX5yP6LSapwqy0VEDnkW8XHoc4LvzN+3lAT38hc44U+iXCBHJdTDOLjWUk5h7E/WihbnnJjoGviL/XfnxHeG8xp+VmPp/IvetNqczounem3qOfVmCPLkDgrv710hcPSQVD0HS4D9GB7m3PkMngGyNrdIBYGxA9PomYKSw/hssHtkQ2kpkuBIMM0OSIsuME7xI2g8xTIye0eZlXg2ncWxSO6/NZMtque7Gz9zocP3Ovl68/0f3L7u6SluLRj5rMwZleuJsODznOQbFgh77KaOMZB+Bhy1T1DpNZl0upguZcr5JZH2ggCuuMuFiFaGidfQYXq+sO/E88/GucGr4NP3IJ22sXXJgWItg71QmLQVcINnX3sqaFW6d/nuYjiU6s7Z6idl1mpy8OIhAati4pFRZp8EOo1hluHO1xVILB0t0oQJ/pyox4hrqWXPjq5l8tq3nPWHKNJ3nWqqIOOD9Qt42tFw4Y7cxNkq065TFfZlkGHZnPGYKIq2oCCDkN9UfXYU/bDlMX8cl/iuJ3d6XfBD5/Cwu9/a9ADgZqxK40AIY/z2ujwPo5AQuq3rI1zgR3ZPM/r35C35LxZGsZ/Js/OZteee09u+TFPPf4sA3yOvc0HArdmpVhSCL1ViRggu3M8rH2C83gcuBmQrvbawmm2vAZ6/2phHrB+8KsR6GIKH2FtLAU+r1Y2+qKXOTc4TGOZ6D5E+T5O2JGDoAAAAAWkpV/UQDa4sAAZ1sxoEBACC6pZSxxGf7AgAAAAAEWVo="

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        # We don't want a KeyboardInterrupt throwing a
        # traceback into stdout.
        pass
