#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright (C)2006-2009 Edgewall Software
# Copyright (C) 2006 Matthew Good <matt@matt-good.net>
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.org/wiki/TracLicense.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://trac.edgewall.org/log/.
#
# Author: Matthew Good <matt@matt-good.net>

import errno
import fileinput
import sys
from optparse import OptionParser
from getpass import getpass

# The md5 module is deprecated in Python 2.5
try:
    from hashlib import md5
except ImportError:
    from md5 import md5

def ask_pass():
    pass1 = getpass('New password: ')
    pass2 = getpass('Re-type new password: ')
    if pass1 != pass2:
        print >>sys.stderr, "They don't match, sorry"
        sys.exit(1)
    return pass1

def get_digest(userprefix, password=None):
    if password == None:
        password = ask_pass()
    return make_digest(userprefix, password)

def make_digest(userprefix, password):
    return userprefix + md5(userprefix + password).hexdigest()

usage = "%prog [-c] [-b] passwordfile realm username"
parser = OptionParser(usage=usage)
parser.add_option('-c', action='store_true', dest='create', default=False,
                  help='Create a new file')
parser.add_option('-b', action='store_true', dest='batch', default=False,
                  help='Batch mode, password on the commandline.')

opts, args = parser.parse_args()

try:
    if opts.batch:
        filename, realm, username, password = args
    else:
        filename, realm, username = args
        password = None
except ValueError:
    parser.error('Wrong number of arguments')

prefix = '%s:%s:' % (username, realm)

if opts.create:
    try:
        f = open(filename, 'w')
    except EnvironmentError, e:
        if e.errno == errno.EACCES:
            print >>sys.stderr, 'Unable to update file', filename
            sys.exit(1)
        else:
            raise
    try:
        print >>f, get_digest(prefix, password)
    finally:
        f.close()
else:
    try:
        matched = False
        for line in fileinput.input(filename, inplace=True):
            if line.startswith(prefix):
                if not matched:
                    print get_digest(prefix, password)
                matched = True
            else:
                print line,
        if not matched:
            f = open(filename, 'a')
            try:
                print >>f, get_digest(prefix, password)
            finally:
                f.close()
    except EnvironmentError, e:
        if e.errno == errno.ENOENT:
            print >>sys.stderr, 'Could not open passwd file %s for reading.' \
                                % filename
            print >>sys.stderr, 'Use -c option to create a new one.'
            sys.exit(1)
        elif e.errno == errno.EACCES:
            print >>sys.stderr, 'Unable to update file', filename
            sys.exit(1)
        else:
            raise
