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