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