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