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