#!/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+Wj4D6lM7hdAEAAyynXgKBkDulG3aFdc8fwxDTwwKkY3HebbaYC3vZdFh2EKDBCZIgV39vcBSme9kYQ3CBlEIENbBIYdaUO4TO75haxVWkTZL73EkuSK8yu4xTzaRm93mDjrSZVj+sDqw6laMGm7tQWIvYOkmFvQYv/m7wrI+iTZ0lNhi7OkwxqbvvvIkbLywvQvrHbJKQLKdhU+hWcnWCDbnAofkGEfpHn6zMW0q/4zJh9sMD4HkB1LYgN+caxwXah0V3Y+Qr2KWKaUs2RGA36GxUekInibqwMUPFEcImhbzVxFep6LMFKDv3k3VNuoI+9xHATWGLKMJAJaFBuz7MQAZo5uLL4oWlrzoLaLbfy8qnr6P9iXvv/6YCFCOc0abbK0l3mzd4gIxU3O2LmUt/BjNPRpw4fpyc5/ld80j49H+v8nNtoRy4dCVrWk6H4Ik5wTou9jcJbhzdMprH9LCNmJ1ab2749Cd5vlJTmSLREFp6/7azL9VhjlemnP3E7udgYAbFPHPkzskDA5Ue4xj5FECLYmZrxWjtvoNI2VJh0SQtaVyMXgzV53oAZg0opvL82zTKHB2Hvi0leG1KC1ZzN+imqas03+4HkwkqKr5Oy0kXKFSGESnN5kcgEQ/5IlbAGZ871BEZSJFtGeSbUgALrgiGZQC/iTqR1mrH2fe44Sj9H0hy1nblWvXdafgJh892LPx1hIu8JqISpT+7FJlUe1863NTjwMvGNag6Z5SkPP0svjttEMeGHjJBJwg5QJSMGaYTtfJXBJV+XeF8aBijkJoXB0pakIlp5MovQ+Bbxz4tTwiBJgG/Tamr/zxTuV9jR/Bscyt0T2g0+t3YPtm8H0Bcd7+IKdt7/kLKAUXOy24C64Jc4mpinq238fjkYR+3DZOdw1Dbt8cEgvOLSZXAAufzxgytJu9+lGQ4Ytu39Yyykp4Odyeb58ZcDYCqiG02G5C8XgVVf7dsEjGRPjCmjxCwt++N1F7BvZbsblmd7KPYRR9iMzJmyTaQSrX/U9gpIWLZKXixfco2QCBhRVNiU1AnLtec9YzqP1YtBoSelj8APPvSQbQrwuEUHPxENnVpAqUnFDfFCZLO6Vky1Myb6zUfzX/WDaHPcX259IyDwngr3L5EEaL4HVCKWeUjcAzNtuzuNgMkYF/DivNX8czWbRT9+BzGYWLj4UWg1KxShmw+XbWBXru7oYu9I0dm/MGCMJlFZCZDPrvJOdT758GZZStijEDgPHJnzztZc7EaPQeTMef64exLgGX6KBufUuS+dxkUP50+i/ftDhrusJWzYHdBrBTGXFsp5dytbwT/r0yy5pF4vX2J5LMNXMhm12vZCSTp2mdYE4+hbNQLHWfr/61WVJ817yzn6Rn6NVWqRqTsMNDG9+qgXN46k+uibdhVN5Mo4uB0WDl7G0rDsBBSoLiXWvNNtxRYvFMWNhcb8hMlLmLT7qpSnXPSGfLHoHk4lsSNZfgoA9Hmup4PecgG4Pd7nNpm8A7FGfcCw5z1CiOgLiuwaiGUexuVtU76gQSloQTJPd626X7MTSfHejGC1MNRnQySs73lChXVBnAFHfDG4ct3wHq1j/yhj4geU7C2M6YrB5rDXHKmUAV1w9FEXtumdpntHJqntzT4ei7nlVIa+9AeKKlTn/NfW5oWeMwroDqjbwraMgyxGC1U6UJ9qegBqbSNFYkfpln00zsQF865B2AGUbsxPeGQQreicSJpfOtYf82mf74eJF+2E7q/Kb8GHJzdbyM4X2kl4kf3lfldrj5bt0IneZSoi56ib87XxUwUcBZnQq1SWKtv/MzkHH/jxjeYxSjj5VPKDXHde1B4IjfMGEI3INdq/ipYxdJIbbGd0rFBaLZwPRPEuKLmPjHP79mct/09H4WQ6UBYimNS/T0bP587VeHr8JSZx8WTTHihDwUnmfATYYzULRB5z8lGN5GVzFAMHNI6Q66J/bn9NvxEf6I3ysRH6YaGROBfeiiEs87weQyuq72OTM3AyU+VxQcorEIKgQWRdakXHhhR9GABAMvmwj1dk+YPgKDvh95dpgptpbSdeQt+XATtna/qOFoX+KG2gdbHC4EbU2hZQYToBk5/Aq29T3/pRbVSF9E8snZ9EDR44g16wg+VE5uqG52NEdNLsvQ5NYexDMQDEN8zJ3cC+2u7heVeJnvFJVAtCJgh1o3UYuVV5a8UGCU/IHBhRcvdlsi2efLspvuyIT7sJCtSjJizHhfqzHxqJaNRi492RRvIqKKGHPyGdFsmmQtZ/i8oRn/d/XOTZmS5+CkWAM0PCLtuPUOg9jkPbz7ldYVQPQP19cTzZXIAnCTtJoHnPPtazpKksCLLrVPLlEPc57bDEggYmwLAnz/dn1WMwPWW8IlPYlHgZgd5we7cNzZ31vOujwD1U9NOm2wCi+hxGHcVt6SaXt9+eKp51DRjKj+R+1B7moAhJunv8XGnzkPBPUr1eBckKyWJ326uo7kATtmJf5gPRu3OIqBanR+nhcnC8AdLM9ZlD3kSIKVhIyS5B6FBgbdKwFDGBnRPBQK69R+eq+ii3lnhZ/o9aWpuibX1Hhj9qDTfRiPvzwlvEFD+Q5tn62azx/5j/CGyRaAAr23z+Goz67DJg7AsHyLkzZdoJ2zOhrnRKo0yTf4JSumZXi85UvMSsRtLQAK9ot2OYVwsk8H5T/5S+HddcKxfOY7ZFyzJGIXXvulpFfUCW9ahkfoNzyL5Zei/jElqZZd29TZRBka8741W5ewr8lP0NBXf2cLmgj94nx4rqGxgaFMam57a6cXr/DbNrTE1YYBV6lNSHoA8DlzRdAiRSYbtMriVBlWVc8V9s8mwkEjfpTkUtY2a9xc7xqQyGhEAJRHjFT2eYaBE4guNU/u3XgN8Dn+gnDwtYUI8uQeT/xz3hgxn8p+lc6vPQ2tH5l1R+szL5uvlRL4Yi0qCtDSToJoLiuYaa4zeUz9DkrwFonA6xi8zbv3mw3jvEqFn5xqly6W2rIp6Q1zCeZhgmu7Bv/aPPH7U7Y+a+/m+7uYhftniDLGBBiLQd+QFhYW9alDiw0fFlorg+U/4eltgcusqiyZUlNrHqqxzWGVkBLQpYOHCMPSWgvylh7oDLl5ybEWHQ/2ys6+aZQS5cnwa3W5Jf/YBvbupbe4roe6YxsiZ2NVzet3+XfJN6kRVLxtEsJjaWaWGJ8wi4577mUKde+MU6jgksi5dYwqKIi8vTmkwzlDrtk6cd3Es4ayXmw3mPIQBRpwpoEw6cKoIyYyBvQHCFh4QHDEdcuGGbbyxA3cDx1Kz7XGEQZxGrwz5lDHyC2UEpesCoZU96rWaKodYwR5oo+c7nHZVCQqmAwvTGLfOZQvAaUb9YpF7CNFYseLrbWXb83VhdnV8VRi5gf7fng7PDXtZXlTt+fJB+jOE+1Jxn2RYAhncaJ4AVr1319y+kUucPM1COwyHoePU6hMNS5R1NLzy9A94i8HKO8h+1MRAShZDXUEVuLJY8JcSkpT59+SM5gu7lLWoXOeyhADEn8tbxabO2Kk/rpPoUv7mHMst2kM8GJrQHFyJUo7/ITaRc2Si1mdjLePxY7uTMD0gqAJ6ag+eZ/OF6we/dr31PMPJryljkXgYvXqJbNBUcKtMvxtExh2Xlrfsvye51bJTUXiMDit7zO/Ljq/rwQ1IfCpODy4EJOq+whgb/VQG+RtADMd0qtmXFASIq/qFQzmq+OQGXDgtFfBpg4ae+ZU7xn+DDPdX0ZeSEPfdJquKe9W6JrFnT7Mu968dpt23q+UPewvzxfy23h6LoYkVfPvFP5cqB9BUf90SN1dx+OqRG4iR6zJXRYhDaoJ/VRoByeVCV3DHenVx/6LmZLON4JnX9iFoPKvdk3arrgEDBZqKQxO5SdUNOdUtsNwFTDoSHwwGj83m2Dt4seFbgzN6oUSMVnPpkAukU3vAjBQwsS9xfVWZ0/EdIlifF6OHOkODe+YvMy5eImFvjgLEt+G7TwZz3oYlpxx+pV5DBch2VGVmKq3qFagz5LE5UD+PHaZLBkLXh7OUAtu5pHRJrwjdg+PSmqE+XjSweZNoJZIjB0ZWzHbnVd7l/2CSdkpBQEo8BOKfBFk1FBURYdPzxOZFTjoiH+g2izluKBu00eHwastQ6EVH9EZ9tMLmbwJMvd6ZvTK+epbgTkHRz7J9wcEgPh3XSLYWQ+i2QX62GQH+UTIHYSVRz7nMpZAtqRdh+zxM5PxP9nlyBsQ5NlKSdzFU5WQZvXT/EmkU7SRupYqZ24wTChcPyajtmp7Pr5CajyjzTyeiTFhi36gbqw3O2Qtsm1NBNirEri5ZNrL3fVWq8uyKMoDrUlgRZ25M3uaqKEDPX+fFUHPv65JDLduRDy8cYRPs73yyGxNMpb7AMpH08tN0qawyk74nB0SlXo+9VuDfPpaLH3ld1qF7tPLuKBrEAigo0L2RBooTfXL31fTckb6flrRfWlbxB6qDQUXHJaYqeHZqw11v1X23xkef13EIFZywR3Buupjt7ENKO1c6tXp3+eZhjDo9+BJNm4l6X0l3ZyhtmmRcFq/LLCHZEAne6U2BGg7sKmN9C5rGb+qBWGUwx7UF9BwS3V34L85HhZqR025QiU87Mkh6ueDy8XtbWA3/93HQsCFajDesm+P4cx+DKE4+8lYdwVYm68e8ucEg3GV78a+BIbfM4NG/OAwIDEYLgvzhgS9Rqa2hBhbKNdD9boZdcwXZN4GkYSiZY3H2URdDAVAcPzaTYxsTGYMxRbo6oMuq/X4eRLNg7Acm/BOw6nqiFrTRalhtSP7WeMGnnRjOZn9ElAgsg7boEqR3aaggqHyzde4PdYIW00bu5xYGYFfneJw7ZX7lze6jFXVKiHQSHaLO0tsu1e/nAeYh7chpwiBvAkCkjevyGarJMQZlTVy8sCpJ+PNe0VGjE+Nnu/cArRdcOmGD33XMJyurRb7h+WQPcRsbx/125SPkFDaBZLfvs1RBn1rBmE3YQmmaiZYqDS84+25IQ3cCj4AW/dNG3UYjwmeGk8C62/j0lzHe9W6fCMMC9lyYbwC7USwkL5pIrIWzE7Z8s+L119X5eXdQmg30IS3/r7tiP/Xl1kVTEg5wVC95vkxuHqMdLUQQictgadG7xLIBORJN2EEn8mInbKzGSbbUXlDAdO5Pyzvo0MkrfVj9AP7bc6YnfNJT401zdJfibItCkuUNa/F0pjcE7olyS7HHuFWNf1aMSMsPK7DIPDg0itzW2c1shELKcx2imXvXsONWQqN7h0PNVYvqDEcfNXcJPYGDtdBErIzuRjiup6nNpxd9Dez275PwM4jxN1rH4xXnN2/1w1dBGigMYzXa/UkjmQrqktpPOAFTSg54Ny8WjG8nGSdoMlseXqmGxcl7i/7Kb8HaA/kkFWeF7Zjeb5J9nWlfK8YUPFHM38MmSErlsvEKTq6jItsQW3LidQxYZaUYBsoMfO6KeQb9xXGAPZgGW9OArVkyf8bafGGhTw3px7eMptshyj/GXJpCDndtpJT2p6BYPRz11bcHoTfSg/V5yTdfQeP5ZJQFo17Y7MlsAAtZ5t2VV08JLlrCjunHLL8UdN++nb/D2DLNok5cDxfY3TlwCZX1XUpxmr/KbE0s6xkLG5KSzB/c0oqvJWp64HRMSMVxO+Fawkamm7XPQgcyXjj81+W/vIMEYS3bHnsofmuPaQnY97xTdVK0MaDgAPMyu6kzhxrTfT2b8tN5d+sSHrGnXd/MrxaC9X1uJRX240J1eJ3FYeXOYOMr97tLqurJkDVW3WsblLEFxNwxmTJq0aFFTuxBAZ1dx9C0noyryW4bdJQHmtXZJoN/jcmD032YGEcr0D5RtnfLzHunR7b+T9UmXxMUZTy2jQrdE+TeqKI+hdZrDfcMAwsra+MfDnETwHJNE0itggkc/8YM9NFUYvgWCFIBcflEgOYrJWV2lGdYfmejkn6m361KzmZF6FQ0FWWoZOOU5JvrSZHZsJJK/FTwL5J3aW6JYZvGr8Scw98MxRswAAxx4U/EJtotbXPgQID5TAz5ojd3GQvOa8T/S4rdzrlOsyGxnpRAgXt0oqCgH1/YqbJwqrcMdwdxXAIQPK7NRi/BbsfG6ZoYoVxlmursfn+nggzC4XN9S328zuBxkmaB+fgwKb+qzj42oFqoFrOuPaDaYq4daQ+8Q9sQ0VZptV83YsS0CC+sQ7taut63RxZr8mS63xJBgc/i2Z6RAjESIo2PgIzzyyRHu2d3vZ5MEKxRbIdYj2sd1/V8jfs46+my3SckUgqcJfArc+s4v5LxNvYN6cwv+WU9yBMHSEHEtEf1F9veaiPed2Y1tRZ9B4PPunn7YVsP9Ub1p9Ccx+L3ENvW0D+N+p/HZpPX2f2FIIacFcC9bcYMfBDWG/+DuPNzog9blEu7UZAinfnUQBNRlXmq5Bm/dWQzKTOzezTnFRJ+OFLOisBf5BKd+yz1pw659jBtyw8cvA6UhHRieAMoU/cp253n0steMj43PRYxajoiJ9h51lC9zfjiQP575V7Z8wDATQulCWxHq4wLw/6a/jidzmfV+92JCQFRk/qgLAVJvYiUaCY57FjWW6YhqpEkLSG/GBkS0FD0x11FxwvtTkHD8zLGqhouoRJfv2Ka7h64wHSvpgRMUHNSgdmcHHWyAfDgIb4kLXvS17Gnjgd9dqE/eVjomMS80QZxxRciKwInzyOwHb6TwiYVuQvfJL7amMc1F3tR5ThSkVRuCJ7s0hPFWcqQvHc2qwOl4MDUBy+H2HkS/C6ZZFMo12HNnuq7R0546lYWjCSKNFvQsmf8SzQr1BfGH0VxSP7G0vAPVeg5KDydm/lxm+IGXEp5pbWHl5jMkTIUQn5lyFFNVfiYke6CSDQIswqxzNOupgSV8wSjaMnfAUK4/PNOGkQS2kCoocOgH8K0k1gLpI0hf9b/dHWyDAC+T2PxIQn/3KyWBaGwUNFfNxRpUwiI/EcbJq8x/uld6oYGa5CfxLFFVJTw5uZxJe/pCRRg/szayyGhGvVX98KVYHgF4MfRs9KT2+osYe6kqfGMgbkzEdIWT9vcoCWJe9XjCN8sg2EYdBvsTUhPh8PWwO/MqXWktCtTq3ySmVPKrZKHPo6R2PeViOPberG7CXCVCPVWuwSKgNnEH72y1pdOl03FSkW29R/mX49NmKQNBXu39fru+IXUzjYpWGhLGf1Vd0nLNlV9XiY1+xVK0CXs4BlD4sQUd/r+XOR2OY6T/3CkZB6p0WI9I0Xnm/bHi4lnQKyXVNrzNxjpnMq5JnTKXoK0ojT1CRXoDM/0aIa4rghSve9pBz1ClsrtHD1DFFveZuIBWnaYnMmNrjw94ap14RUiV6b8zZf5TM6q42KwPdcQvDAkWuAiJVvo+fhYp+WHkdtmSnQ/A9p4oyZEGGMh41uaSGcml93WO7UheVsvzej/QQcMVi/vJl6v0wQEXIelHa08ljwfMGaD8IjxoT9iaEdDB60NlD2uWn3lswiswFxuibXga9sirb0hzS2QRxrOtjgQ388nFpQC5bE8mNoK7lha3E+eftpnKEra9pSuqVeLRXc9ks7P6c83RiyI8R7xE6PEdfmLK0uvkWjf31l6exKrAk4UEPfaIjcNldvRY1UezfdDEOSP9J3yPS603Din2nvJ8nNOmr07SZqHDA/qwa17l0WzhTcydQu/TJdegO20oTap5U5JMzYMJRA/f74R4wAv1oDiLZaoSRr0Bp/ZSof59QJrzexK68FpLwXBzJqpsj69jqBSDuK7Y6fjHz15ev33OwbxrraCM0cT4GQaF6andiq7rEzVne0S0PoEsA9r6aFqKcv+3APoBmS1I4JGd036P/fwD5W0LrA98NobNQdW+KW9Hizpj8BouMQ85rmcrtmzVlaMeoSct5qJdeiwezl19aJcTOeO0C5HD9HJxSV/xK9RbUz+EIUDCMZkMzmG8+snEFcZVcaD6BJnRSfq1eu2l6B/okesM3PZ4JZ4luYwotCuVh9ki1sTjLSNAu13tbIA2GisVkXYJHt9ZWqpQBfugjrTiu9lUvGGP/9mEqnFziDfKtui6s2IcI2VJgMvAltLVfFza18Wdy4zY53J/unyMz+/+b73+3C4J5gBKO/TZu3WalQQLWXUAN3/Y7ZbYUvoCrhpVaLuMlqEzvB3nQIEdlB4lUR5I8aQe1HZd1KLSyfybZhnteF+k5ZiH5Nf0nkUhWtu1QdhGXrgxSVpXMylrtaUMxQHCu4O4IbWBafKYp05KXVgrcIDsttr8npKmRRzB2EDB6aeETcowoHA8NSECUK/jgYqcVCOIg0kPHeAUWePh0RO5oYmfWqZOaJS5i4yTluqCisAWezGO7fPEGtoYdRBhx+hFFDQox/U4gJ3fPFaybHgicYJsMrd1oFgRCsnEKdfO4ghLHcU4sx+d0d04c9hpi1Z7QfPu0y3c2zJ5uF9JwNDNi0zPnFnCslNtsyFbOBoFkEzyMIyNK4a23SiRo57/Lm5NDSuxkVIfbUFSdQzUQc8sRiFeoQf64Byg/h8JDtNt7LZRQUL3p2dQFcUAJh+VdbX0/jKn7hETyV8pfsgXkIVG5giRer3MnraRFi5/Em9t1X1V6o2bL04m1mhwb+7o+Ppqx1SRkDag4h5MIb6MKSB8XSo7snxULMICiDr/DIGm38A9jAKOwym098E1VEq2duxZ+Asp1/+QfQh8kZyvvxgkCLH3h17rFYPFqNlpyUTOO1NYU4Kmz9pU8MZl8fNIyKG8WSfRjuWCAtXQTTY/Liv1qMNP++RQE0eChO5jcAbDJ374QY6MvhU3+eqSfHf4PvnTEzs1E4W1FbsuRm7aQNGRQydkxaNG8x8qAsHk9p26AtQiASOf6/uwmwrBE74qfpGbmaZVKq1S9bkEpwu6lfM9Jl9lT/o8ZoF21dmhEuiWnbDDbxvYElzipzbvgXP5W2E3uF1IxUIeqN07kVbVzQgh8huP7js8FTlOnMrqrF86PS2WkTy9H/xAHAEz6fKXqKyw2yVXua8ZzKxSQs5odN/7h0pM7+/k34D/BhiZmz0QMZ+kirz5N3AGfB8gb2zmaJEHvz7otNfl7LEGbxeYQNS86m210PEShav5Y87K0nVt9+uP3GYRl3DkdPAITa7X59V8xxK2DqUkbaGh1EAV2ZNEx/+HB/H8mURkwzF932RlVhpY7pB3ZucRTdaSMYEcxOysxCBDMDMocUffFD1ujwodSJx/jjRqsWteegyJ4z+ne0GGhJrc+p2xOX8XzHyZ6eBADOuN9rrp8BKGpcSYlAi4d97xWvhgX0mzAR02RJSfDMNFYKnqOhmmf9N6F8dChMm0eCkD9XNKWGn9vVvHy2H/IhWA6wpskTmKXfh7zKDMdYtnLmlefby78PcC3k+PXArWp6irXyLI6HFwoKn5pyM6m/D+tf7m6mY5tUYWv//F293jFNZj9CTcwTntK6j0vbkkJhk4xruXSBLvwQSM9NCtrb2tpKuxZJgDZ/jvhiCfRht7Ksbc1TkMhGZfHvFblbSfvaXQvUpnKV1ijSLuIT74qLReISieY5Ot5YVFNdGdKYleq+Vf9LpcqwECTw3UL3pm75sQnVjC2I3cPJCByFFT4Gd5d5GhJ4+UgG3qC1eqGOlWRgYTTYsxA3MGL0Vr0d+qro17dRHT7Ll+9k51XKs3Dv5YblmkyZNNyDlU8PZMVV/jq2KQlwighzu3DsfWV4T1+xon7Zb4kUT0VKveaS02R8gN+XvVjVsRsXNDnvxeJBBJD4PDPpOfidqAyxnp4h+BLWB44XukwkKLGNJdrcXwBeZ2wwlQozly0nNo6FcJz6jFc05frPW4YzGTIvcatVXFeGTPO/zX9zMWaS3nCyyyW8EN/k+HfCt8t8CvW5ZNBa9Y/RTQKEj+cwf10u9q3tPqUGOLM/jxuQHFkHLfkJgmK6Hylb6NchBBV+GXC0zQHxKa9bZiJ5BqkujXVZKIvjNnpJmgGIqyv2HzmyEoir2cDBS4sBdz1U9z5SPhBbR9l35lsCUGFrx9anI7UDINlyIQc7VZ2GKRgZWoYxlR4dNsOyGzGHd/kkA6PtieznbFxLgWs188n26Sgo+17o5GTj1QC42ypSOGf1hp9kbn1wIF4PYCkdTaAAXB7iQk3ZutNRnsA1Q/IsSOf2kJp1AWj2KrQMupQX04NIJITDWdGrSPvE6Fj6L9WwK/MXkLYN78UOhBQDWQRKZtLAqqk3B/jXupxyNrfrgS7E9dSv8+Rdt03wxn0MHmoClexDW9TONHbgj2DVahwvtr5hGJon3dZBlqnkvwEm6EdNqErIjlMkVL7hK5+N4nV2aKYJhzrJJdfvdIL55K8Pd23JdBuT+2JUCTV23qFvihqO88uGWle9bITRCVlrgyeYXkxedhUnhMBnkQsJpkCwyOCqAbzOfAkqFvdz4PyIyZ20dJ8Q5Ov+1JAo4ssaoRDh8pRSbo99gXiTRfLtN094VKgKHnQdsQKYLIQ/0xYD08ccMtN6ihyAEpvoihoOijl1b49EA31URAHHNM93HrMgmq7Jggm3d6upyszKrwNUM3kE/61aN/KSJDOGFTJR+QS02rYIzoi45epMm08L8zpAQaumD203hQOM2VN3uwEkiX5bAaL4arqlV+mK9lzl117k8OvU7BlVSFcvE6UjINds25a1tJYAfFVq35oi4Xf/KfxSffHniJK+gTHVJYmEYyYS0PYZrsq+mOH/00XNmFHZRdGR/dHXHS90t1BG/62fE/KBkoY1GjV+2TVQ97XEbKWdoiSMpHRwZa+7tWYsQZnm/ZsuADRjcRVLnzuurz+ZYFB0vrZlxx+JIU/GEAv0uoPhDb9Ckj+Md0l1Q5SVEkYyvODzSwtfybmNBcwtXD9p11FlvXn5MrmOAdUwidpLq9Pl5286kxb+0Lgl+qTTYGwE0aj09gvOLbH0RcI1Z6uG+st/kaa0wjnYpBcSrWfwiJyS9RdxhVpKEXnmvnq99TP7i58CVampwJWwZGTKUC24NdiBDFRoVd7nnAGxgvFfC+mbSpAYoC2jWXw1iXa5U9zs5eKnjb96wTqjkrO513ngBRk3qtLMKwM7Q3MTXRRuBws3kObYOGz9PSXbQHfNVw4RsywqrhgSfqfWbH2V1NYMKSSzLK2n11R0V6a/q4nc++NL6MmHrDHd1No9urvzhXyMe4IJRkLpsWrdip1K273f/DAr54PddCZeJxiFpv94o51C58gqCvnolJ2zv+tY9mpE0CnUTKsljcn2PqpGhgTj40QpwhoM4UZaVlngkBq6M7m3xuU+y+vicGquVpd6aiTHbOMiXI3QoYTXWNk1NJNGl25uTDn9U15SJGmIicP0+ou22oMF8x6PaWvb3Z0h1MEfSjakVR6Lm82xcShU5IrH8rSzNWH0wCb+vaKPHkWXXaOSzByEEsZd/B2V66/eZJAqH+AlvqdimHj00Y3k+stwbsCZAiDYiDHUWQDWqus4hrJDDkFRSxaCh7nyUroZXLV0DqKraLwqQEXPwlaIcDQReQnKz5vlkPBeul79yIds4qvDAyz63AGeS4q0ynQFJcNHjpFXvdTwHGAUvzXwqUDQUoXaRkllQriIdR7QEwJH14qcekAN1liRau7ErlvRznJovD9+uL+amJ1xIv/rDYemW6TDNhm1VY5UprORq/MG8ffKJU5iym03f+yp8Nk+v1vBiadlD8FQ/pg8AYxP42C0J+1Qb7EEagPNbP4oSOo8HnZU96K8bA0eQqYtS8ONDG2eBU2AgNoWEHhWcqXAdm8iQQIvTxs1IZoqyVYGLHir9s7Q7j7jqh8L26xv0M51Etce2GJOMZ7yiiOZz+FQQrr8y0KvD1gAImC8DD39ykolBPTJOJ70uKZOuoZil8LtCLh82N+R4CFr2+W8B/syTvgPE8U0ZNLJIRuTUxyf88+v2rwTAuMxpZ+Y/eQ/EuV8VIUqGpvZi4LGV9p0aT2DKtbat43gnwa30WngD6jeSruLiHN1wE+EvrF0iRzKSjfMaJveeBeYSiEwaRlha0FlWHtD0YqeHJRFZ6GSmhTzch20Pkwc6lCkWq5kQreUnYSt/15hvyTiNcv5IitPPd5/7Eeet+JIpx0BIAHRf4krijfghlYPaGh+eyVZZor5aoGJpV/aAKDRMIRImuDGAz8ISlNWsSJOiR3ClkFXfwxIQZnPde+5oUWZm9H14iVhscP7hu/5HyhBurNz5/7q4UH5dHY6uAa8sAFxLzsxSB+YHEcqSg/hJA7kGeefNFFIrbDEpL2kzhafCns2B19ETcoC6sJqGXool3ifmB1T3ds9TsK5NfiLiJ6jfGfA/McEzeLUqEWFHELYZDgiKfP+1s06A859yJu+wbsmOKJJCOFTS2F4jQ/scNuFtTJcFB0/vew9RUssiMX73A3cb0YZmF7G7Gvln4wo9gk+ENuCmmIsEVhbXJheiZy4NeNkgB0B2wIVIv2S/6bHHmF1uodIWQFUXJPtmQ2HtV44U13VhTGS724ORBFGRjPPGILQWYUO5SXLg7LNkN7opnaVeHYpQEJLoiLlqRcrORm4/H+wkd1tbli8bKBfxM7LIzbfok2aPOcq5oAG7C1ri9x/05rxxV1evTmmNUfs82uh15iy4V+hG7TvMRHH1Zu9TegtR379q4gv0rUr7ix6WnRZkQ/wvyO4OLZOKupM+3O0oU06SknWTKY1jjI0inlGnAV67mTCc3z+1MB7BNYjp8r7pgRsnZeqSoNpdcnlARazvq1rbo9tT9qzVZIniDx8eeKj3BTLPogUM/EdeHxwT1jkZZ/3Sz1Io/dyHFpwQ8+XzMd57U3G+3KzD/u2HHpfUIXrtdzOVOo08KbWVKdXNNja4mz2GuhR/vpWW+7yjqBCb+AKXs5qTpWmHviMWWzOep56I4KC1fK79zKwD+SWnVVQybuPwyenYvdTo6fmNipm9jk2UaWJwpZJMaZLOpSx5xzphGIT6LlZ47UFaEYedD1YqdO++PykrxpS3o9QQCpV6rigZINaS6V4vkqUlF6Ohnc3SaU8lXvxIu6urTo7nYocgHPJcDQtKvuK7dY+6U73pYqBNL/l+GKacN8wjNqbITMFCbI6kOBto7bV1NV6rbLMnTcywUuOk0y4LkaAMWx/ydIyJ+D+ffFYTRJazjQ8OtCJuhEGt9CLJu+59o9K4PvwS1WdKdIS0/sSPZq5XBmWL0oAH7Fr8bSjSBq92+ZJrdNVtbHIPbo0AVwG5d8Z4XwuO6IvGt66k+Nt3PFroYtNhupsY1SaFKmqwYsAXr8NwSjj9fAnI2xj5SCvvmF9V7bRVx3HFxyOf5TIhFarYz9dtwUbpHdkTuMaxI/6mfVmjrfxW1M57TZy9KejJcMhurnVFg8hzX6btMUlKB2odzwV4tYfYnOMmSDiq6piv3gLQJdv70HixVuJE1faNJzj4f+fPsnXNzIyAIqMORJl3irrpubs1yRurnaPkULC/uuu43rld/8iFmsVKEzlj+HthGkWeCZ/tEPbl7dJVDDu5CSTNhXW0DphL16eNKA352G72D9KTu1Sg2oA+H1ZZ26o5YUqpFL/JMbyMqdCgE9TITrLx/bQruLZW+fAw+b6F9prmNRJcKmh5GeiL2WbLvZ8gS/soYFt33gOgOmchYXj5LC1QmpQnUeB4H3lZz5zhJVBsVTXe3U49X57vjTyukImKlT42w2YHDtnJAOm4UhbK8/LKe3MqoAx0i3eb9yiigqrCZhoB4vTtM++4lGkYhOqWCKwinETWb0KUD30IjJ8YW2/WbU3wgioV0XiyUAbHO6qVYfg0QIshWmgsz6gZk8NzUa+JKl0hQCyEO7s62/Jj3257XAoUR2L0AFvQlcKNixNkRFA6PDG+l9x6aAtymLpVrPL9aUuP/WTGpr+9vmYPVHNqhEAMDn60OrqJTiDHI+RFqLXRJcptRhmKRc7ZrrfcPY0wGIQg61gjjY5ZxOSfJnvj8i6FMYqwB8AwC6lm2ZHN17S2jz3MUwl2DNCYRHDJC7Y1zdf6tmrSjTOmbZUlImsyRHH4wEHxsxdqtjpqPYQ1NO+r9LLXEXjDd0fUHTb/QKox/u4z5IXee+3O2yJqq0KOHUss0fLTDqIyBx1h+t4Tc7UnzYUODuAZx52/lldFy8rV093HG+7t7gpGYMjt3v8SsJoXO1EvzFhPRmOIv7aHtfYHsOzeBYiz/Gou/945/IBqaliUYdkNIH/EtiuGVKkNWNZLyrkD4C2OskkkgaTodWg+PL/ahCW16nVlfoJGzbM0gAoSPv0cdxs2DHPDRamBh8p2kuiAxz2rd6rDErZH3vviV3mAm62dzigYbji1xH9zoNvpQQimuSCBeKT0uRBP4r2AaEaxIkheGusAt796D3I76I1NWuKGm3vwWtHKIz8TTpQYmEYVLZMhm6Oxs5nKEGggK+8kbfQC/q6sqrJzirDdB52IYcy4nErf70/j8+m78SRMfMfRhG/ArR5+i8XhkCKtvTir+EdIyiJNEFn1l7XMD2munqyJxl+cv+INr0P2ugDf+g6Xh8Y6yVpPWKQVHVrO+dLYQFCGlmuWeS4sH6LRsnYLEhVVgHOEGUsyp5zN+wefbO3vVF9ocY/rI9BXoECiVCNjWKeJvgNXcOwNzst8kcVu6fPuKL4RZa5sC3d4ZPzfheEURWaCPXfjl54KJOqtzTztjRw4GJJbL4zTfpz5a+Xbj1Cslz4sfh0KMiS5Y5dTgmaSgM61G8dedzGBc2qJO3GUKQHZjtXoZY3qqDOsa+idHMFYWJGfbLo6VX2FSGK4LThAYl8pcWjgK4WUuuiKTXppjQDhoqdKrYrT5FCmp9O4IUFEwHMaCCtryTixLN9EX88ebTZ2HL1Y6NSJnGb0MnB7ZCeATrIU3TWCj4nk3xqJXpzE2xIyLsOkCYDDNPe6tAhhwELgmyRcuoevNFjGGBlDWTFpXMS/xmuziLr9//MamIqzea/nZBeBEOZom5pkrmCN80m9ECSvDRDRAekFko0w2d1+Qeo3jx+OfdmDMQ/Hlk6xQoG+nHmq53EHdr8tYCVG7sEw7LZJkaMOIdgdogp3ARJ6mX7Cp3cmWpVcnAulKBoayZLdh2/7XB6XBAZWDG1BU256SJvRf2ybmAtkpAcNeYwyHlZa2+nMIrTNxXkNwJyrCE4sM42SjJ2MxLT+SElaNPhBRtSDwUyTYbOG5ZRo4VxdeRAgBkbs+03ZuSkSE/+ZaRSAPQzjZmDIz8POmWNuyTsaiXr1GyeA6qTNnmBEWM/Jmc5VhZwilBeVNUpertOvsbiKFYaHYrT+qQ1nNUE9F7fn5TbJfqouptkNMYSHP7oLQm3YnKg/Fuhgvr5lw9rRoNwgwacZ+VwOMYz9EtBxQSDR4IyRhWJLXQMePU6k+mpeCwJgTlWaBRp+ZGVdBCs/0RkLootDyJD0kXdswzAeShQwgmW9Lt6njHuVRw7Vz9gUJkJsRZAkK+lgBl1EnVn0yH+3t0QjM/0q1SBCW4YLkV2I+HE16rTUi+IVf86YRoIAVsxwDH7nXF3NhOHi6OVNjj75XY/4hLIjAFPou96a4lpG99w8Kxa26jcJayakNhiEXJpgMAgRkELsrsP2uMLwJniSTms2Y6echvu4wO8Fk2XrPG6t8aOKUferz2frqGcy/XbCBOQktlGkgy5wMovLkE+vetSUJ26Y29IIqrKVPlujJIV17R1tj/1O5KNUHNop+fLznN4dtG45DQ7SiLOrhtoR8eUG46KTQAbWrtAqO7jpYUlMxztg7M8gsNhP8Gj3Bpd0kpFHobGF5xFynabHNPnokYyF52azyggG25bB4Cp7v/NxGS1BfhT19wrdGMQQzWzz/2gYMOQ3oCtPvLzIQp5OHZBefNuZqsWE8kiMhxvUu+z4hgPRpr6xaZRdeRDCjuws2S4c4KBVWCrpUSiHvL0jcfCrfTvnKAzcIDGaCTg9LBLtAN2CwqVL8RIkPY6UbmVGZBYBFM6qrqOWe/IQT/Ne9DA6RFFzWywCuk7gSzWw7rJjigPrAsFpSjNcqaKQrX90Obu01zQIya3mY19PBo3/hcOwrxWOqomYDEZMiCrOGMeXsiQsDUJCHISg0NcKqpE+FET+DDlp7L0MW1yUshXnL+VJGP6jGxiPqK7rQQZyp6gx/3SNASUUi+Oy1JO4vu0z9ujZ1Ccn8SPSfyh/pYO6f8J2fu3AafiAhDiyhYXTA9cH10S64Pw8InDVBwm+GevtrnlpLY0RaApxjVpqZx97BZDum9y0aJaygME8kjh15a1qrMKaEVy6bMsPGbyI5LAT9hJYrroffeGSBSCdYj9QpTimx5rQnw2+G/cgnRe78NxiSqaJzNihCqVLP0ajRNEYVqKkEfFv1yvJfOj1SMxaq1y8WSqTmlcXwEzcSmE9Fo54rp3k3xMMMu8rm8XSWN1zpGf9OTsLD5VS7+I26NohMUPvUlxTJjHT2TlekaneFNEP6RUWRIKmzPuMndTx5LOQmFIo6FPtlOFbLppBhvyY2p5XrJCkU+pJRTYfaoVM0GmM3Y7bGZbeGgjoDTT3XtRhiVrK+SwE2YiMmdYR70swEi+xvZU4NPWZZjXk1fX2ZPbvvigB2/YDRpTPDgzwVhElCemMDXiymlk8Hk7ehiRCtnJTkNZxF0hgw6jqHRJ+IHKwuRhitpTFioR8tlXICpyoJfReeB3P/RZtCQc+8dHp5Pq+MhtYsloZpcypIrvfr5pibovuFs+L4Jhy1Xbgh5ELnlbUGCIdQA08+Ka9t7a+OLCzd1/jCSFUXkhQG9FfjDBqK0EdGpLnweKsqd2z0/aHdPl3FsbfLNXShQJKtUH+fpSe1rbWiq0NblweaaWRObVXCwAqW6WahOUknApXs02zcQZbLq1ZYo7+zUgPC5uh8kd2V7amNvHh1ocZFoSd2Z84WSfRm10cvtKpPXGhrBLEqrmzLGb+ye4GvHbYMlNR2+iqdUy6fU6ErQt+8q+a+GMn+eqt5hO21MnrbRB18qOMNjbVRdhJ71M9nbFQyc8CbZPrDlnETxNirgJ+zCbFYY7gYJqWSo8BoCwDKh5AdNCFKKY1tlmeqeSSH4wlZ9U6417wblBJk4fNkb5VxIENMZc+r0e7Hw1s8PLERS1goUE/puTqMQ1hivvb3vxINvD8Z0OpH6CjktxmSDNSGfeaXPYszgreZQyHmBFZJ5GWbfhaSv9vdpGytLInO8nZg7D+CSYBTB19KJtLX82MzWB0X8bxFLkJo0a4QcmsvwRAkfWb1kdsK6OiwMxQ4zR7yZzMT2F+TQwGNBCUo+yb4m0hSCfXS56IRgjkVFhZs58BJX4L8MMJ7/l1IzNDH0G31pbDEkjHeik7egzd/kmwWIXM1UW46y/cnRL3zh/3KqHMp5nrDdSYoeLWkVaZthgfo7bB7pFE/HOBsIGDb+I4zoZRRaGd22K0xtQRxNafC1qW0mgSWO9hxE7OFW1be7VNNchzgJ2BWyvoiyoXhcZirwgb2A3MRfZ0CzdlKnYDD27ymRI8HyLpabtmmV/OH9Vzh00RXdxkQbYCdTZiB8NDtpOvv92K1Y5pZchVvGvBxt3x81W0tzXzmS6wHyqdH+94ALIZb0TZfa0coWiu5XY8fpd6Yh2CiukrJx38prmOSNT7lGJBctM4cp3lMmk6Xif95s6xob8QCrbmFj24tFbLBbku8lbeIfok9zXsOkeLaiyJPHOJZKgkACL6U1Yblnq0AAdRnpn0AAGOcwVWxxGf7AgAAAAAEWVo="

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