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