# -*- coding: utf-8 -*-
#
# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2019 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT
"""
Now this package only cleans up old files and does not install new.
All new hooks must be installed using cllib.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from future import standard_library
standard_library.install_aliases()
from builtins import *

import os
from secureio import print_error
from clcommon.cpapi import getCPName, PLESK_NAME, DIRECTADMIN_NAME
from clcommon.public_hooks.bundle.plesk import remove_hook_by_str_id_and_location

# List of Defines
USERDEL_COMMAND = 'USERDEL_CMD /usr/bin/userdel.cagefs'

SOURCE_HOOKS_DIR = '/usr/share/cagefs-plugins/hooks'

# DirectAdmin paremetres
DA_CREATE_USER_HOOK_FILENAME = 'user_create_post.sh'
DA_RESTORE_USER_HOOK_FILENAME = 'user_restore_post.sh'
DA_REMOVE_USER_HOOK_FILENAME = 'user_destroy_post.sh'
DA_CREATE_USER_HOOK_CMD = '/usr/share/cagefs-plugins/hooks/directadmin/user_create_post.sh'
DA_RESTORE_USER_HOOK_CMD = '/usr/share/cagefs-plugins/hooks/directadmin/user_restore_post.sh'
DA_REMOVE_USER_HOOK_CMD = '/usr/share/cagefs-plugins/hooks/directadmin/user_destroy_post.sh'
DA_HOOK_DEST = SOURCE_HOOKS_DIR + '/directadmin/' + DA_CREATE_USER_HOOK_FILENAME + '/' + DA_CREATE_USER_HOOK_FILENAME


# Plesk parametres
_OLD_CAGEFS_PLESK_HOOKS_DIR = '/usr/share/cagefs-plugins/hooks/plesk'
_OLD_CAGEFS_PLESK_HOOKS = {
    'phys_hosting_create': {'SCRIPT_FILE': 'cagefs_plesk_hs_created.sh'},
    'phys_hosting_update': {'SCRIPT_FILE': 'cagefs_plesk_hs_updated.sh'},
    'phys_hosting_delete': {'SCRIPT_FILE': 'cagefs_plesk_hs_deleted.sh'},
    'domain_update':       {'SCRIPT_FILE': 'cagefs_plesk_dm_updated.sh'},
}


# open file content
def get_file_content(file_name):
    f = open(file_name, 'r')
    content = f.readlines()
    f.close()
    return content


# write changes to file
def write_file_content(file_name, content, open_method = 'w'):
    content = ''.join(content)
    f = open(file_name, open_method)
    f.write(content)
    f.close()


# USERDEL_CMD hook install into /etc/login.defs
def user_del_hook_install():
    try:
        f = open("/etc/login.defs", "r")
        content = f.readlines()
        f.close()

        i = 0
        userdel_cmd_old = ''
        na_userdel = -1

        for line in content:
            if line.startswith('USERDEL_CMD'):
                userdel_cmd_old = content[i]
                content[i] = USERDEL_COMMAND + '\n'
                break
            if line.startswith('#') and line.find('USERDEL_CMD') != -1:
                na_userdel = i
            i += 1

        if not userdel_cmd_old.startswith(USERDEL_COMMAND):
            if na_userdel != -1 and len(userdel_cmd_old) == 0:
                userdel_cmd_old = content[na_userdel]
                content[na_userdel] = USERDEL_COMMAND + '\n'

            if len(userdel_cmd_old) != 0:
                write_file_content("/etc/login.defs", content)

                if (not userdel_cmd_old.startswith("#")) and (userdel_cmd_old.find(USERDEL_COMMAND) == -1):
                    write_file_content("/etc/cagefs/userdel.old", userdel_cmd_old.replace('USERDEL_CMD', '').strip())
            else:
                write_file_content("/etc/login.defs", '\n' + USERDEL_COMMAND + '\n', "a")
    except (OSError, IOError) as e:
        print_error('Failed to install USERDEL_CMD hook:', str(e))


# USERDEL_CMD hook remove from /etc/login.defs
def user_del_hook_remove():
    try:
        f = open("/etc/cagefs/userdel.old", "r")
        userdel_cmd_old = f.read()
        f.close()
        userdel_cmd_old = 'USERDEL_CMD ' + userdel_cmd_old
    except IOError:
        userdel_cmd_old = ''

    try:
        os.remove("/etc/cagefs/userdel.old")
    except OSError:
        pass

    try:
        f = open("/etc/login.defs", "r")
        content = f.readlines()
        f.close()
        i = 0
        for line in content:
            if line.find(USERDEL_COMMAND) != -1:
                content[i] = userdel_cmd_old + '\n'
                break
            i += 1

        write_file_content("/etc/login.defs", content)
    except (OSError, IOError) as e:
        print_error('Failed to remove hook for DirectAdmin:', str(e))


# Remove old hook for DA
def da_hooks_remove():
    # there hooks are now in cllib package
    from clcommon.public_hooks.bundle.directadmin import remove_da_hook
    remove_da_hook(DA_CREATE_USER_HOOK_FILENAME, DA_CREATE_USER_HOOK_CMD)
    remove_da_hook(DA_REMOVE_USER_HOOK_FILENAME, DA_REMOVE_USER_HOOK_CMD)
    remove_da_hook(DA_RESTORE_USER_HOOK_FILENAME, DA_RESTORE_USER_HOOK_CMD)

    try:
        if not os.path.isfile(DA_HOOK_DEST):
            return

        content = get_file_content(DA_HOOK_DEST)
        i = 0
        start_delete = False
        new_content = []
        for line in content:
            # check old hook start line
            if line.find('/usr/sbin/cagefsctl --set-default-user-status "$username"') != -1:
                start_delete = True
            # add line in new hook content if line not from old hook
            if not start_delete:
                new_content.append(content[i])
            # check for old hook end
            if (line.find('fi') != -1) and start_delete:
                start_delete = False
            i += 1
        # write changes to hook
        write_file_content(DA_HOOK_DEST, new_content)
    except (OSError, IOError) as e:
        print_error('Failed to remove old hook for DirectAdmin:', str(e))


def plesk_hooks_remove():
    """
    Remove all Plesk hooks installed by this package.
    """
    for hook in _OLD_CAGEFS_PLESK_HOOKS:
        remove_hook_by_str_id_and_location(hook, bin_dir=_OLD_CAGEFS_PLESK_HOOKS_DIR)


def configure_pam_lve(configfile, enable):
    try:
        if not os.path.isfile(configfile):
            return
        SPACE = '      '
        DEFAULT = SPACE.join(['session', 'required', 'pam_lve.so', '500', str(int(enable))]) + '\n'
        f = open(configfile, 'r')
        lines = f.readlines()
        f.close()
        found = False
        for i in range(len(lines)):
            line = lines[i].strip()
            if not line.startswith('#'):
                s = line.split()
                l = len(s)
                if (l >= 3) and (s[2] == 'pam_lve.so'):
                    if l == 3:
                        line = line + '      500     ' + str(int(enable))
                        lines[i] = line + '\n'
                    elif l == 4:
                        line = line + '     ' + str(int(enable))
                        lines[i] = line + '\n'
                    elif l >= 5:
                        try:
                            v = int(s[4])
                        except ValueError:
                            lines[i] = DEFAULT
                            found = True
                            break
                        if v != int(enable):
                            line = SPACE.join([s[0], s[1], s[2], s[3], str(int(enable))])
                            if l >= 6:
                                line = line + SPACE + SPACE.join(s[5:])
                            lines[i] = line + '\n'
                    found = True
                    break
        if found:
            f = open(configfile, 'w')
            for line in lines:
                f.write(line)
            f.close()
        else:
            f = open(configfile, 'a')
            f.write(DEFAULT)
            f.close()
    except (IOError, OSError) as e:
        print_error('configure_pam_lve error for file ' + configfile, str(e))


def configure_pam_lve_for_cagefs(enable):
    configure_pam_lve('/etc/pam.d/sshd', enable)
    configure_pam_lve('/etc/pam.d/su', enable)
    if os.path.isfile('/etc/pam.d/crond'):
        configure_pam_lve('/etc/pam.d/crond', enable)
    elif os.path.isfile('/etc/pam.d/cron'):
        configure_pam_lve('/etc/pam.d/cron', enable)
    configure_pam_lve('/etc/pam.d/atd', enable)


def HooksInstall():
    user_del_hook_install()
    configure_pam_lve_for_cagefs(True)
    # remove all hooks that were installed
    # by cagefs package (now we install them in cllib)
    cp_name = getCPName()
    if cp_name == DIRECTADMIN_NAME:
        da_hooks_remove()
    if cp_name == PLESK_NAME:
        plesk_hooks_remove()


def HooksRemove():
    user_del_hook_remove()
    configure_pam_lve_for_cagefs(False)
