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