#! /usr/bin/env python
# -*- mode: python; coding: utf-8 -*-
#
# urlescape
#
# URL escape or unescape files, or standard input, to standard output.
#
# Copyright (C) 2007-2011 Elmar Hoffmann
#
# Requires Python 2.2 and argparse available from
# http://code.google.com/p/argparse/
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
#

import sys
import os
import signal
import argparse
import urllib

class FileIter:
    def __init__(self, file_):
        assert(type(file_) == file)
        self.file = file_

    def __iter__(self):
        return self

    def next(self):
        line = self.file.readline()
        if not line:
            raise StopIteration
        return line

def main():
    parser = argparse.ArgumentParser(
        description='URL escape or unescape files, or standard input, to' \
            ' standard output.', add_help=False)
    general_args = parser.add_argument_group('general arguments')

    general_args.add_argument('-?', '-h', '--help', action='help',
                              help='print this help and exit"')
    general_args.add_argument('--usage', nargs=0, action=UsageAction,
                              help='print short usage and exit"')
    general_args.add_argument('-V', '--version', action='version',
                              version='%(prog)s 1.0',
                              help='print version information and exit')

    parser.add_argument('-d', '--decode', '-u', '--unescape',
                        action='store_true', help='decode (URL unescape) data')
    parser.add_argument('files', metavar='FILE', nargs='*',
                        type=argparse.FileType('r'), default=[sys.stdin],
                        help='file to (un)escape, \'-\' for standard input')

    try:
        args = parser.parse_args()
    except IOError, err:
        error('Error opening input file: %s' % err)
        sys.exit(os.EX_NOINPUT)

    if os.path.basename(sys.argv[0]).lower() in ( 'urldecode', 'urlunescape' ):
        args.decode = True

    if args.decode:
        function = urllib.unquote
    else:
        function = urllib.quote

    for file_ in args.files:
        for line in FileIter(file_):
            sys.stdout.write(function(line))
    sys.exit(os.EX_OK)

class UsageAction(argparse.Action):
    def __call__(self, parser, namespace, values, option_string=None):
        parser.print_usage()
        parser.exit()

def error(msg):
    sys.stderr.write('%s: %s\n' % (os.path.basename(sys.argv[0]), msg))


if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        sys.exit(128 + signal.SIGINT)
