HEX
Server: Apache
System: Linux sxb1plzcpnl440011.prod.sxb1.secureserver.net 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
User: xfp2mtarcm67 (7705020)
PHP: 7.3.33
Disabled: NONE
Upload Files
File: //opt/alt/python37/lib/python3.7/site-packages/orphanedaccountscanner/cpanel_databases.py
#! /opt/alt/python37/bin/python3
import os
import re
import socket
import datetime

ignore = [
    'gdlinuxm',
    'gdresell',
    'gdmigrate',
    'vpsmigrate',
    'cpanelsolr',
    'diablo',
    'gdlegal',
    'binlogs',
    'cphulkd',
    'gdlinuxm_wp2',
    'horde',
    'modsec',
    'mysql',
    'performance_schema',
    'roundcube',
]

def system_health() -> bool:
    if not os.path.exists('/var/lib/mysql'):
        raise SystemError('Directory not found')
    return True

def get_hostname() -> str:
    if socket.gethostname() == str():
        raise TypeError("Hostname audit event failed!")
    return socket.gethostname().split('.')[0]


def check_hostname() -> bool:
    """
        Grabs a servers unix hostname and checks if it's a cPanel server

        Returns: bool
    """
    short_name = get_hostname()
    hostname_regex = '^(a2|p3|sg2|sg3|sxb1|n1|n3)pl(v|vw|m|z|)cpnl\d{2,}$'

    if re.search(hostname_regex, short_name):
        return True

def directory_scan(dir) -> list:
    """
        Parses a given directory and returns a list of sub directories ignoring
        files and hidden dirs/files

        Returns: list of dirs
    """
    if dir not in ['/home', '/var/lib/mysql']:
        raise TypeError('We have no idea how to scan that, sorry')

    try:
        entries = []
        with os.scandir(dir) as scan_path:
            for entry in scan_path:
                if not entry.name.startswith('.') and entry.is_file():
                    # both parsers need dirs and not hidden
                    continue
                else:
                    entries.append(entry)
    except OSError as error_message:
        raise SystemError(error_message)
    return entries

def get_directory_info(dir: os.DirEntry, base_dir: str,) -> list:
    stat = dir.stat()
    if stat.st_gid == 199 or stat.st_gid == 0:
        # Skip GDSTAFF and ROOT owned things
        pass
    if dir.name in ignore:
        # Skip all things that we are explicitly ignoring
        pass

    # If there's not a trailing / the name conc. doesn't work
    if base_dir[-1] is not '/':
        base_dir += '/'

    from subprocess import run
    process = run(['du', '-s', base_dir + dir.name], capture_output=True, text=True)
    size_in_kb = process.stdout.split('\t')[0]

    return [ dir.name, stat.st_uid, stat.st_gid, stat.st_atime, size_in_kb ]

def build_databases_sot():
    '''We found that the best SOT for databases is on-box with
    `whmapi1 list_databases'''
    from subprocess import Popen, PIPE
    whmapi = Popen("whmapi1 list_databases".split(), stdout=PIPE)
    grep = Popen("grep name".split(), stdin=whmapi.stdout, stdout=PIPE)
    cut = Popen(['cut', '-d', ':', '-f2'], stdin=grep.stdout, stdout=PIPE)
    process = Popen("sort -n".split(), stdin=cut.stdout, stdout=PIPE)
    out, err = process.communicate()
    dbs = []
    for db in out:
        dbs.append(db)
    return dbs

if __name__ == '__main__':
    # Build a list of commands to ensure the host is operational to scan
    verification_commands = [
        check_hostname(),
        system_health()
    ]
    for _ in verification_commands:
        if not _ == True:
            raise SystemError(message)

    DATABASES = build_databases_sot()
    ldatabases = directory_scan('/var/lib/mysql')
    for entry in ldatabases:
        name, uid, gid, st_atime, size = get_directory_info(entry, '/var/lib/mysql')
        LOCAL['databases'][name] = {
            'uid': uid,
            'gid': gid,
            'st_atime': datetime.datetime.fromtimestamp(st_atime).strftime("%Y-%m-%d %I:%M:%S"),
            'size': size
        }

    print(LOCAL['databases'], DATABASES)