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