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