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