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