Mini Shell

Direktori : /opt/sharedrads/
Upload File :
Current File : //opt/sharedrads/docroot.py

#!/opt/imh-python/bin/python3
"""
@noaha

Quickly and  accurately return the document root of a given domain
owned by the current cPanel user as reported by cPanel userdata
"""
import yaml
from getpass import getuser
from sys import argv
import sys
from os import geteuid
import re


def load_yaml(filename, exit_on_fail=False):
    """
    return yaml object from filename and
    handle exceptions according exit_on_fail
    """
    try:
        with open(filename) as f:
            yaml_text = f.read()
    except OSError:
        if exit_on_fail:
            sys.exit("Could not read file: %s" % filename)
        else:
            raise
    try:
        return yaml.load(yaml_text, Loader=yaml.SafeLoader)
    except yaml.YAMLError as err:
        if exit_on_fail:
            sys.exit(f"Unable to parse YAML from {filename}:\n{err}")
        else:
            raise


def get_docroot(user, vhost, exit_on_fail=False):
    """
    Get the full path to a domain/vhost's document root.
    If exit_on_fail is True, the process will exit upon failure
    This is in place for use as a module

    If disabled, throws: yaml.YAMLError, IOError,
    """
    if not user:
        if exit_on_fail:
            sys.exit("cPanel user was not specified")
        raise ValueError("User must have value")
    if not vhost:
        if exit_on_fail:
            sys.exit("Domain was not specified")
        raise ValueError("vhost must have value")
    # We process everything in lowercase to avoid casing issues
    vhost = vhost.lower()
    userdata_file = "/var/cpanel/userdata/%s/main" % user
    userdata = load_yaml(userdata_file, exit_on_fail)

    if vhost.startswith("www."):
        # This check is in defense against a subdomain
        # "www.example.domain.com" which may or may not be possible, but we
        # do not want to risk the confusion.
        if vhost not in userdata["sub_domains"]:
            # Otherwise, strip the first "www" from vhost
            vhost = vhost.split("www.", 1)[1]

    # locate the data file that contains vhost information
    if userdata["main_domain"] == vhost or vhost in userdata["sub_domains"]:
        domain_datafile = f"/var/cpanel/userdata/{user}/{vhost}"
    elif vhost in userdata["parked_domains"]:
        domain_datafile = "/var/cpanel/userdata/{}/{}".format(
            user, userdata["main_domain"]
        )
    elif vhost in userdata["addon_domains"]:
        domain_datafile = "/var/cpanel/userdata/{}/{}".format(
            user, userdata["addon_domains"][vhost]
        )
    else:
        if exit_on_fail:
            sys.exit("Unable to find vhost in userdata")
        return None

    domain_data = load_yaml(domain_datafile, exit_on_fail)
    # Double check this file actually contains our vhost
    if domain_data["servername"] == vhost or re.search(
        "(^| )%s( |$)" % vhost, domain_data["serveralias"]
    ):
        return domain_data["documentroot"]
    if exit_on_fail:
        sys.exit(
            f"Something is wrong, the domain was not found in {domain_datafile}"
        )
    return None


def whoowns(domain, exit_on_fail=False):
    """
    Implement whoowns without forcing a fork.
    """
    try:
        with open("/etc/userdomains") as f:
            userdomains = f.read().splitlines()
    except OSError:
        if exit_on_fail:
            sys.exit("Could not read file: /etc/userdomains")
        else:
            raise
    for userdomain in userdomains:
        split = userdomain.partition(": ")
        if split[0] == domain:
            return split[2]

    sys.exit("Domain not found in /etc/userdomains")


def main():
    if len(argv) < 2 or argv[1] is None or "-h" in argv or "--help" in argv:
        sys.exit(
            """Usage: docroot.py domain

Quickly and accurately return the document root of a given domain
owned by the current cPanel user as reported by cPanel userdata"""
        )

    # strip protocol, perform basic validation
    validation_result = re.match(
        r"^(https?://)?([^/]+\.[^/]+)/?$", argv[1], re.I
    )
    if validation_result:
        vhost = validation_result.group(2)
    else:
        sys.exit("Invalid domain/vhost specified")

    if geteuid() == 0:
        user = whoowns(vhost, exit_on_fail=True)
    else:
        user = getuser()

    print(get_docroot(user, vhost, exit_on_fail=True))


if __name__ == "__main__":
    main()

Zerion Mini Shell 1.0