#! /usr/local/bin/python2.7
#
# Copyright (C) 1998-2007 by the Free Software Foundation, Inc.
#
# 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.

"""Dump the contents of any Mailman `database' file.

Usage: %(PROGRAM)s [options] filename

Options:

    --marshal/-m
        Assume the file contains a Python marshal, overridding any automatic
        guessing.

    --pickle/-p
        Assume the file contains a Python pickle, overridding any automatic
        guessing.

    --noprint/-n
        Don't attempt to pretty print the object.  This is useful if there's
        some problem with the object and you just want to get an unpickled
        representation.  Useful with `python -i bin/dumpdb <file>'.  In that
        case, the root of the tree will be left in a global called "msg".

    --help/-h
        Print this help message and exit

If the filename ends with `.db', then it is assumed that the file contains a
Python marshal.  If the file ends with `.pck' then it is assumed to contain a
Python pickle.  In either case, if you want to override the default assumption
-- or if the file ends in neither suffix -- use the -p or -m flags.
"""

import sys
import getopt
import pprint
import cPickle
import marshal
from types import StringType

import paths
# Import this /after/ paths so that the sys.path is properly hacked
from Mailman.i18n import _

PROGRAM = sys.argv[0]
COMMASPACE = ', '

try:
    True, False
except NameError:
    True = 1
    False = 0



def usage(code, msg=''):
    if code:
        fd = sys.stderr
    else:
        fd = sys.stdout
    print >> fd, _(__doc__) % globals()
    if msg:
        print >> fd, msg
    sys.exit(code)



def main():
    try:
        opts, args = getopt.getopt(sys.argv[1:], 'mphn',
                                   ['marshal', 'pickle', 'help', 'noprint'])
    except getopt.error, msg:
        usage(1, msg)

    # Options.
    # None == guess, 0 == pickle, 1 == marshal
    filetype = None
    doprint = True

    for opt, arg in opts:
        if opt in ('-h', '--help'):
            usage(0)
        elif opt in ('-p', '--pickle'):
            filetype = 0
        elif opt in ('-m', '--marshal'):
            filetype = 1
        elif opt in ('-n', '--noprint'):
            doprint = False

    if len(args) < 1:
        usage(1, _('No filename given.'))
    elif len(args) > 1:
        pargs = COMMASPACE.join(args)
        usage(1, _('Bad arguments: %(pargs)s'))
    else:
        filename = args[0]

    if filetype is None:
        if filename.endswith('.db'):
            filetype = 1
        elif filename.endswith('.pck'):
            filetype = 0
        else:
            usage(1, _('Please specify either -p or -m.'))

    # Handle dbs
    pp = pprint.PrettyPrinter(indent=4)
    if filetype == 1:
        load = marshal.load
        typename = 'marshal'
    else:
        load = cPickle.load
        typename = 'pickle'
    fp = open(filename)
    m = []
    try:
        cnt = 1
        if doprint:
            print _('[----- start %(typename)s file -----]')
        while True:
            try:
                obj = load(fp)
            except EOFError:
                if doprint:
                    print _('[----- end %(typename)s file -----]')
                break
            if doprint:
                print _('<----- start object %(cnt)s ----->')
                if isinstance(obj, StringType):
                    print obj
                else:
                    pp.pprint(obj)
            cnt += 1
            m.append(obj)
    finally:
        fp.close()
    return m



if __name__ == '__main__':
    msg = main()
