#!/usr/bin/python2

import os
import re
import sys
import subprocess
from qubes.qubes import QubesVmCollection,QubesException,QubesHVm
from qubes.qubes import xs

def main():

    source = os.getenv("QREXEC_REMOTE_DOMAIN")

    if source is None:
        print >> sys.stderr, 'This script must be called as qrexec service!'
        exit(1)

    qvm_collection = QubesVmCollection()
    qvm_collection.lock_db_for_writing()
    try:
        qvm_collection.load()

        source_vm = qvm_collection.get_vm_by_name(source)
        if source_vm is None:
            raise QubesException('Domain ' + source + ' does not exists (?!)')

        if not isinstance(source_vm, QubesHVm):
            raise QubesException('Service qubes.ToolsNotify is designed only for HVM domains')

        xs_path = "/local/domain/{0}/qubes-tools".format(source_vm.get_xid())

        # for now used only to check for the tools presence
        untrusted_version = xs.read('', '{0}/version'.format(xs_path))
        # reserved for future use
        untrusted_os = xs.read('', '{0}/os'.format(xs_path))
        # qrexec agent presence (0 or 1)
        untrusted_qrexec = xs.read('', '{0}/qrexec'.format(xs_path))
        # gui agent presence (0 or 1)
        untrusted_gui = xs.read('', '{0}/gui'.format(xs_path))
        # default user for qvm-run etc
        untrusted_user = xs.read('', '{0}/default-user'.format(xs_path))

        if untrusted_version is None:
            # tools didn't advertised its features; it's strange that this
            # service is called, but ignore it
            return

        # any suspicious string will raise exception here
        version = int(untrusted_version)

        # untrusted_os - ignore for now

        if untrusted_qrexec is None:
            qrexec = 0
        else:
            qrexec = int(untrusted_qrexec)

        if untrusted_gui is None:
            gui = 0
        else:
            gui = int(untrusted_gui)

        if untrusted_user is not None:
            if re.match(r'^[a-zA-Z0-9-]+$', untrusted_user):
                user = untrusted_user
        else:
            user = None

        # Let the tools to be able to enable *or disable* each particular component
        source_vm.qrexec_installed = qrexec > 0
        source_vm.guiagent_installed = gui > 0

        if user:
            source_vm.default_user = user

        qvm_collection.save()

        retcode = subprocess.call(['qvm-sync-appmenus', '--force-rpc'])
        if retcode == 0 and hasattr(source_vm, 'appmenus_recreate'):
            # TODO: call the same for child VMs? This isn't done for Linux VMs,
            # so probably should be ignored for Windows also
            source_vm.appmenus_recreate()
    except Exception as e:
        print >> sys.stderr, e.message
        exit(1)
    finally:
        qvm_collection.unlock_db()

main()