#!/usr/bin/python3
# coding: utf-8
#
# gtkproxyconfig-daemon
# Copyright (C) FSnow 2012-2018 <fsnow@yandex.ru>
#
# gtk-proxy-config 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 3 of the License, or
# (at your option) any later version.
#
# gtk-proxy-config 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, see <http://www.gnu.org/licenses/>.

import os
import dbus
import dbus.service
import dbus.mainloop.glib

from dbus.exceptions import DBusException
from gi.repository import GObject

import gtkproxyconfig.common as utils


class DemoException(dbus.DBusException):
    _dbus_error_name = 'gtkproxyconfig.DemoException'


class NoValidArgumentsException(dbus.DBusException):
    _dbus_error_name = 'gtkproxyconfig.NoValidArgumentsException'


class PermissionDeniedByPolicy(dbus.DBusException):
    _dbus_error_name = 'gtkproxyconfig.PermissionDeniedByPolicy'


class gtkproxyconfigDaemon(dbus.service.Object):
    def __init__(self, conn=None, object_path=None, bus_name=None):
        dbus.service.Object.__init__(self, conn, object_path, bus_name)
        self.enforce_polkit = True
        self.dbus_info = None
        self.polkit = None
        self.__caller_pid__ = 0
        self._package_operation_in_progress = False

    @dbus.service.method("gtkproxyconfig.Iface",
                         in_signature='', out_signature='',
                         sender_keyword='sender', connection_keyword='conn')
    def RaiseException(self, sender=None, conn=None):
        raise DemoException('RaiseException gtkproxyconfig method')

    @dbus.service.method("gtkproxyconfig.Iface",
                         in_signature='', out_signature='',
                         sender_keyword='sender', connection_keyword='conn')
    def Exit(self, sender=None, conn=None):
        mainloop.quit()

    @dbus.service.method('gtkproxyconfig.Iface',
                         in_signature='s', out_signature='',
                         sender_keyword='sender', connection_keyword='conn')
    def clean_profile(self, path, sender=None, conn=None):
        self._check_polkit_privilege(sender, conn,
                                     'gtkproxyconfig.daemon.start')
        print(path, type(path))
        utils.clean_profile(path)

    @dbus.service.method('gtkproxyconfig.Iface',
                         in_signature='sas', out_signature='',
                         sender_keyword='sender', connection_keyword='conn')
    def write_profile(self, path, new_dbus_lines, sender=None, conn=None):
        self._check_polkit_privilege(sender, conn,
                                     'gtkproxyconfig.daemon.start')
        utils.write_profile(path, new_dbus_lines)

    @dbus.service.method('gtkproxyconfig.Iface',
                         in_signature='', out_signature='',
                         sender_keyword='sender', connection_keyword='conn')
    def clean_apt_conf(self, sender=None, conn=None):
        self._check_polkit_privilege(sender, conn,
                                     'gtkproxyconfig.daemon.start')
        utils.clean_apt_conf()

    @dbus.service.method('gtkproxyconfig.Iface',
                         in_signature='as', out_signature='',
                         sender_keyword='sender', connection_keyword='conn')
    def write_apt_conf(self, new_dbus_lines, sender=None, conn=None):
        self._check_polkit_privilege(sender, conn,
                                     'gtkproxyconfig.daemon.start')
        utils.write_apt_conf(new_dbus_lines)

    def _check_polkit_privilege(self, sender, conn, privilege):
        """Verify that sender has a given PolicyKit privilege."""
        if sender is None and conn is None:
            raise PermissionDeniedByPolicy

        # Get peer PID
        if self.dbus_info is None:
            self.dbus_info = dbus.Interface(
                conn.get_object('org.freedesktop.DBus',
                                '/org/freedesktop/DBus/Bus', False),
                'org.freedesktop.DBus')

        pid = self.dbus_info.GetConnectionUnixProcessID(sender)

        # Query PolicyKit
        if self.polkit is None:
            self.polkit = dbus.Interface(dbus.SystemBus().get_object(
                'org.freedesktop.PolicyKit1',
                '/org/freedesktop/PolicyKit1/Authority', False),
                'org.freedesktop.PolicyKit1.Authority')
        try:
            # Don't need is_challenge return here,
            # since we call with AllowUserInteraction
            (is_auth, _, details) = self.polkit.CheckAuthorization(
                ('unix-process',
                 {'pid': dbus.UInt32(pid, variant_level=1),
                  'start-time': dbus.UInt64(0, variant_level=1)}),
                privilege, {'': ''}, dbus.UInt32(1), '', timeout=600)
        except:
            raise PermissionDeniedByPolicy

        if not is_auth:
            raise PermissionDeniedByPolicy

        if self.__caller_pid__ == 0:
            self.__caller_pid__ = pid


if __name__ == '__main__':
    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)

    bus = dbus.SystemBus()
    name = dbus.service.BusName("gtkproxyconfig.Daemon", bus)
    object = gtkproxyconfigDaemon(bus, '/gtkproxyconfigDaemon')

    mainloop = GObject.MainLoop()
    mainloop.run()
