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