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