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