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