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