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