#!/usr/bin/python3.12
"""
Back up Untangle configurations via the web admin UI.
"""

from argparse import ArgumentDefaultsHelpFormatter, ArgumentParser
import configparser
from http.client import HTTPException
from os import chmod
from urllib.error import HTTPError, URLError
from socket import timeout
from sys import stderr

from untangle.untangle import Untangle

# Define a few exit codes.
EXIT_OK = 0
EXIT_BACKUPS_FAILED = 1

# Create an argument parser using our docsctring as its description.
parser = ArgumentParser(description = __doc__,
                        formatter_class = ArgumentDefaultsHelpFormatter)

parser.add_argument('-c',
                    '--config-file',
                    default='/etc/untangle-https-backup.ini',
                    help='path to configuration file')

args = parser.parse_args()

# Default to success, change it if anything fails.
status = EXIT_OK

# Parse the configuration file. In this contect "interpolation" is
# something completely berserk, and it breaks passwords containing '%'
# characters. So, we turn it off.
config = configparser.ConfigParser(interpolation=None)
config.read(args.config_file)

# And loop through each section.
for section in config.sections():
    # For each section, we create an Untangle object based on that
    # section's configuration.
    u = Untangle(config[section])
    try:
        # And then try to log in and retrieve a backup.
        u.login()
        backup = u.get_backup()

        # If that worked, we save the backup file and make it
        # accessible only to its owner.
        filename = u.name + '.backup'
        with open(filename, 'wb') as f:
            f.write(backup)
        chmod(filename, 0o600)

    # If it didn't work, but in a predictable way (some host is down),
    # then we report that error and keep going.
    except URLError as e:
        tpl = '{:s}: {:s} from {:s}'
        msg = tpl.format(u.name, str(e.reason), u.host)
        print(msg, file=stderr)
        status = EXIT_BACKUPS_FAILED
    except HTTPError as e:
        tpl = '{:s}: HTTP error {:s} from {:s}'
        msg = tpl.format(u.name, str(e.code), u.host)
        print(msg, file=stderr)
        status = EXIT_BACKUPS_FAILED
    except HTTPException as e:
        # At least one sort of HTTPException (BadStatusLine) is not
        # translated by urllib into an HTTPError, so we catch
        # HTTPExceptions too.
        tpl = '{:s}: HTTP exception {:s} from {:s}'
        msg = tpl.format(u.name, repr(e), u.host)
        print(msg, file=stderr)
        status = EXIT_BACKUPS_FAILED
    except timeout as e:
        # A socket.timeout exception occurs when something goes over
        # the configured "timeout" limit.
        tpl = '{:s}: socket timeout ({:s}) from {:s}'
        msg = tpl.format(u.name, str(e), u.host)
        print(msg, file=stderr)
        status = EXIT_BACKUPS_FAILED

exit(status)
