#!/usr/bin/env python # -*- coding: utf-8 -*- # arCHMage -- extensible reader and decompiler for files in the CHM format. # # Originally written by Eugeny Korekin # Significantly modified by Basil Shubin # # Copyright (c) 2003 Eugeny Korekin # Copyright (c) 2005-2007 Basil Shubin """arCHMage -- extensible reader and decompiler for files in the CHM format. Usage: %(program)s [options] [destdir] Where: -x / --extract Extracts CHM file into specified directory. If destination directory is ommited, than the new one will be created based on name of CHM file. This options is by defaut. -p number --port=number Acts as HTTP server on specified port number, so you can read CHM file with your favourite browser. You can specify a directory with decompressed content. -d / --dump Dump HTML data as plain text into standard output. -V / --version Print version number and exit. -h / --help Print this text and exit. """ import os import sys import getopt from archmod import __version__, message, error_msg from archmod.CHM import * program = sys.argv[0] EXTRACT = 1 HTTPSERVER = 2 DUMPHTML = 3 COMMASPACE = ', ' def usage(code=0, msg=''): message(code, __doc__ % globals()) message(code, msg) sys.exit(code) def file2dir(filename): """ Convert filename.chm to filename_html """ dirname = filename.rsplit('.', 1)[0] + '_' + 'html' return dirname def parseargs(): try: opts, args = getopt.getopt(sys.argv[1:], 'xdp:Vh', ['extract', 'dump', 'port=', 'version', 'help']) except getopt.error, msg: usage(1, msg) class Options: mode = None # EXTRACT or HTTPSERVER or other port = None # HTTP port number chmfile = None # CHM File to view/extract dirname = None # Destination directory options = Options() for opt, arg in opts: if opt in ('-h', '--help'): usage() elif opt in ('-V', '--version'): message(0, __version__) sys.exit(0) elif opt in ('-p', '--port'): if options.mode is not None: usage(1, '-x and -p are mutually exclusive') options.mode = HTTPSERVER try: options.port = int(arg) except ValueError, msg: usage(1, 'Invalid port number: %s' % msg) elif opt in ('-x', '--extract'): if options.mode is not None: usage(1, '-x and -p are mutually exclusive') options.mode = EXTRACT elif opt in ('-d', '--dump'): if options.mode is not None: usage(1, '-d should be used without any other options') options.mode = DUMPHTML else: assert False, (opt, arg) # Sanity checks if options.mode is None: options.mode = EXTRACT if not args: usage(1, 'No CHM file was specified!') else: options.chmfile = args.pop(0) # CHM content should be extracted if options.mode == EXTRACT: if not args: options.dirname = file2dir(options.chmfile) else: options.dirname = args.pop(0) # Any other arguments are invalid if args: usage(1, 'Invalid arguments: ' + COMMASPACE.join(args)) return options def main(): options = parseargs() if not os.path.exists(options.chmfile): error_msg('No such file: %s' % options.chmfile) # Check where is argument a CHM file or directory with decompressed # content. Depending on results make 'source' instance of CHMFile or # CHMDir class. source = os.path.isfile(options.chmfile) and \ CHMFile(options.chmfile) or CHMDir(options.chmfile) if options.mode == HTTPSERVER: CHMServer(source, port=options.port).run() elif options.mode == DUMPHTML: source.dump_html() else: source.extract(options.dirname) if __name__ == '__main__': main()