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