HEX
Server: Apache/2.4.63 (Unix)
System: Linux TOMS-220NAS 4.4.302+ #86009 SMP Wed Nov 26 18:19:17 CST 2025 x86_64
User: flavio87 (1026)
PHP: 8.3.27
Disabled: NONE
Upload Files
File: //proc/25634/root/var/packages/CMS/scripts/CMSDelegate_dirsvs_leave.py
#!/usr/bin/env python3

import logging
import os
import sqlite3
import sys
import syslog
import traceback
from ctypes import CDLL, c_char_p

NAME = 'CMS'
VERSION = '1.0'
VENDOR = 'Synology Inc.'
SDK_MODVER = '1.0'

HOOK_NAME = 'dirsvs_leave'

# The 'SYNO.CMS' prefix helps us to log into CMS's own log file.
LOG_IDENT = 'SYNO.CMS.hook.{}'.format(HOOK_NAME)

CMS_DB_PATH = '/var/packages/CMS/var/db/cms_db.sqlite'
CMS_LIB_PATH = '/var/packages/CMS/target/lib/libcms.so'

syslog.openlog(LOG_IDENT)

logger = logging.getLogger('MyLogger')
logger.setLevel(logging.INFO)
logger.addHandler(logging.StreamHandler())


def log_info(msg: str):
    new_msg = '[INFO] {}'.format(msg)

    syslog.syslog(syslog.LOG_INFO, new_msg)
    logger.info(new_msg)


def log_err(msg: str):
    new_msg = '[ERR] {}'.format(msg)

    syslog.syslog(syslog.LOG_ERR, new_msg)
    logger.error(new_msg)


def log_err_n_raise(msg: str, base_exc: Exception):
    log_err(msg)
    raise Exception(msg) from base_exc


def log_progress(msg: str, task):
    log_info(msg + ' [begin]')

    try:
        ret = task()
        log_info(msg + ' [done]')
        return ret

    except Exception:
        log_err(msg + ' [failed]')
        raise


def print_help(bin_name: str):
    print('Usage: {} --sdk-mod-ver|--name|--pkg-ver|--vendor|--pre|--post'
          .format(bin_name))


def cmds():
    return {
        '--sdk-mod-ver': lambda: print(SDK_MODVER),
        '--name': lambda: print(NAME),
        '--pkg-ver': lambda: print(VERSION),
        '--vendor': lambda: print(VENDOR),
        '--pre': lambda: log_progress('Try running pre hook', pre_hook),
        '--post': lambda: log_progress('Try running post hook', post_hook),
    }


def main():
    bin_name = sys.argv[0]

    if len(sys.argv) < 2:
        print_help(bin_name)
        return

    cmd = sys.argv[1]
    cmds().get(cmd, lambda: print_help(bin_name))()

# Below is the interesting part of hook.


def pre_hook():
    # Define your own pre hook here
    pass


def post_hook():
    try:
        hook_result = log_progress(
            'Try reading result of hook',
            get_hook_result)

        if hook_result == -1:
            log_info('Result of hook is {} so skips it'.format(hook_result))
            return

        dir_server_info = log_progress(
            'Try reading directory server info from hook',
            get_dir_server_info)

        log_info('Directory server info from hook: {}'.format(
            str(dir_server_info)))

        log_progress(
            'Try removing all delegations of given directory server from CMS'
            ' db',
            lambda: remove_delegations_of_directory_server_from_cms_db(
                dir_server_info))

    except Exception as exc:
        log_err_n_raise('Failed to run post hook', exc)


class DirServerInfo:
    def __init__(self, server_type, name):
        self.server_type = server_type
        self.name = name

    def __str__(self):
        return 'DirServerInfo{{server_type={}, name={}}}'.format(
            self.server_type, self.name)


def get_hook_result() -> int:
    try:
        return int(os.environ['RESULT'])

    except Exception as exc:
        log_err_n_raise("Failed to get result of hook", exc)


def get_dir_server_info():
    try:
        return DirServerInfo(
            os.environ['TYPE'],
            os.environ['DOMAIN'],
        )

    except Exception as exc:
        log_err_n_raise("Failed to get dir server info from hook", exc)


def remove_delegations_of_directory_server_from_cms_db(dir_server_info):
    try:
        query = read_query_string()

        with sqlite3.connect(CMS_DB_PATH) as conn:
            conn.cursor().execute(
                query,
                (dir_server_info.server_type, dir_server_info.name))

    except Exception as exc:
        log_err_n_raise(
            "Failed to remove all delegations"
            " of direcotry server from cms db: {}"
            .format(str(dir_server_info)),
            exc)


def read_query_string() -> str:
    try:
        libcms = CDLL(CMS_LIB_PATH)

        query_fn = (
            libcms.SYNOCMSDelegateRemoveAllOfDirectoryServer_sqlite_query
        )
        query_fn.restype = c_char_p

        return query_fn().decode('utf-8')

    except Exception as exc:
        log_err_n_raise(
            'Failed to read query string for'
            ' removing all delegations from directory server',
            exc)


if __name__ == '__main__':
    try:
        main()

    except Exception:
        # Here we log call stack to syslog only since python would log to
        # stdout for us.
        syslog.syslog(syslog.LOG_ERR, traceback.format_exc())
        raise