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