#!/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.1\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
