#!/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
import json
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 = json.loads(ppds_decompressed.decode(encoding='ASCII'))
    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()
    # Encode to binary, decode base64, decompress and convert to bytes again
    ppds['ARCHIVE'] = BytesIO(decompress(base64.b64decode(ppds['ARCHIVE'].encode('ASCII'))))

    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"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"

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