#!/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"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"

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