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