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