#!/usr/bin/python
# EasyScout Backup

# Copyright (c) 2004 by Ryan Kirkpatrick (scouts@rkirkpat.net). 
#   All rights reserved.
#
# 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; see the file COPYING.  If not, write to
# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.

# Documentation.
"""
This is a backup application to download the contents of an EasyScout
troop into an XML backup backup file. This is done via the web interface
of the EasyScout software, as that is the only practical method. Command
line arguments taken, all but the first two are required:
  -v                -- If present, turns on verbose mode, which prints status
                       and progress at regular intervals, along with elapsed
                       time.
  -g                -- If present, the output filename will have '.gz' appended
                       to it, and the contents of the file compressed using gzip.
  -U {base_url}     -- The base URL of the EasyScout website to backup from (i.e.
                       http://{host}/easyscout/servlet/ES/).
  -b {backup_file}  -- The name of the file to write the XML backup to.

For authentication and access to an EasyScout troop, both the troop name and the
troop full access password need to be provided. They can be provided via one of
the following command line parameters:
  -t {troop}        -- The name of the troop to backup.
  -p {passwd}       -- The full access password for the troop to backup.
  -f {passwd_file}  -- A file that contains the troop name to backup on the
                       first line, and the full access password for that
                       troop on the next line.

The troop is logged into to, and an export file retrieved. EasyScout provides
the export file in the form of a zip archive. This archive is unpacked, and XML
export data read. The XML export data is finally written to the given backup
file, which can either be uncompressed or gzip compressed. 
"""
__credits__ = 'Copyright 2004 (c) by Ryan Kirkpatrick. All Rights Reserved'
__author__ = 'Ryan Kirkpatrick <scouts@rkirkpat.net>'
__date__ = '2004/01/05'
__version__ = 'ESPyUtils 1.0'

# Needed modules.
import sys
import re
import gzip
from zipfile import ZipFile
from tempfile import TemporaryFile
import utils

# Get program name, and set defaults.
name = sys.argv.pop(0)
base_url = ""
backup_file = ""
gzipped = 0
troop = ""
passwd = ""
passwd_file = ""

# What the command should look like.
def Usage():
    print "Usage: backup.py [-v] [-g] -U {base_url} -b {backup_file}"
    print "                 (-t {troop} -p {passwd})|(-f {passwd_file})"
    sys.exit(1)

# Were there options? Handle them.
for argv in sys.argv:
    # Verbosity? Set if so.
    if argv == "-v": utils.verbose = 1

    # Gzip backup file? Set if so.
    if argv == "-g": gzipped = 1

    # Base URL? Indicate next parameter is it.
    elif argv == "-U": base_url = "next"
    elif base_url == "next": base_url = argv

    # Backup file? Indicate next parameter is it.
    elif argv == "-b": backup_file = "next"
    elif backup_file == "next": backup_file = argv

    # Troop? Indicate next parameter is it.
    elif argv == "-t": troop = "next"
    elif troop == "next": troop = argv

    # Password? Indicate next parameter is it.
    elif argv == "-p": passwd = "next"
    elif passwd == "next": passwd = argv

    # Password file? Indicate next parameter is it.
    elif argv == "-f": passwd_file = "next"
    elif passwd_file == "next": passwd_file = argv

# Test the command line parameters.
(okay,result) = utils.GetURL(base_url)
if not okay: print result; Usage()
if not troop or not passwd:
    try: input = open(passwd_file,"r")
    except:
        print "Could not open password file, %s!" % passwd_file
        Usage()
    troop = input.readline().replace("\n","")
    passwd = input.readline().replace("\n","")
    input.close()
if not troop or not passwd:
    print "No valid troop name or password found!"
    Usage()
try:
    if gzipped: output = gzip.open(backup_file + ".gz","wb")
    else: output = open(backup_file,"w")
except:
    print "Could not open backup file, %s!" % backup_file
    Usage()

# We are ready to start backing up data.
utils.Verbose("%s Backup Script [%s]\n" % (__version__,__date__))
utils.Verbose("Backing up EasyScout data for troop '%s' into file '%s'...\n" % (troop,backup_file),0)

# First step is to login.
utils.Verbose("  Logging in...")
data = {"action":"Login", "name":troop, "password":passwd}
(okay,result) = utils.GetURL(base_url,{},data)
if not okay: raise StandardError(result)
utils.Verbose()

# Then extract the session id from the login result.
utils.Verbose("  Aquiring session id...")
session = re.search("\?z=[^&]+&",result)
if not session: raise StandardError("Could not find session id in login result! %s" % result)
session = result[session.start()+3:session.end()-1]
utils.Verbose()

# Then download the backup.
utils.Verbose("  Downloading backup file...")
data = {"z":session, "action":"doexport", "settype":0}
(okay,result) = utils.GetURL(base_url,{},data)
if not okay: raise StandardError(result)
utils.Verbose()

# Now, extract the XML export file from the zip archive we were given.
utils.Verbose("  Extracting XML data...")
tmp = TemporaryFile()
tmp.write(result); tmp.seek(0)
zip = ZipFile(tmp)
data = zip.read(zip.namelist()[0])
utils.Verbose()

# Then write the XML export data to the given backup file.
utils.Verbose("  Writing XML data...")
output.write(data)
output.close()
utils.Verbose()

# All done!
utils.Verbose("Done!\n",0)
