PK œqhYî¶J‚ßFßF)nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/ $#$#$#

Dir : /opt/support/lib/
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64
IP: 209.182.202.254
Choose File :

Url:
Dir : //opt/support/lib/arg_types.py

"""Custom argparse types"""
from pathlib import Path
import re
import string
from argparse import ArgumentTypeError as BadArg
import netaddr
import rads

CPMOVE_RE = re.compile(
    r'(?:cpmove|backup)-'  # prefix
    r'(?:(?:[0-9.]{1,10}_)(?:[0-9-]{1,10}_))?'  # optional date
    r'((?![0-9])[0-9a-zA-Z]{1,20})\.tar\.gz$'  # username and suffix
)

# Technically capital A-Z would be valid too, but for our purposes, reject that
DOMAIN_RE = re.compile(r'^(?:(?!-)[a-z0-9-]{1,63}(?<!-)\.)+[a-z]+$')
# (?:                       Start of group #1
#   (?!-)                   Can't start with a hyphen
#   [a-z0-9-]{1,63}         Domain name is [a-z0-9-], 1 to 63 length
#   (?<!-)                  Can't end with hyphen
#   \.                      Follow by a dot "."
# )+                        End of group #1; must appear at least once
# [a-z]+                    TLD
# $                         End


def cpuser_safe_arg(user: str) -> str:
    """Argparse type: checks rads.cpuser_safe"""
    if not rads.cpuser_safe(user):
        raise BadArg('user does not exist or is restricted')
    return user


def any_cpuser_arg(user: str) -> str:
    """Accepts any cPanel user"""
    if not rads.is_cpuser(user):
        raise BadArg('not a valid cPanel user')
    return user


def valid_domain(domain: str) -> str:
    """Argparse type: validates a domain"""
    if not DOMAIN_RE.match(domain):
        raise BadArg('invalid domain')
    return domain


def valid_username(user: str) -> str:
    """Argparse type: validate a username as documented on docs.cpanel.net"""
    if not user:
        raise BadArg('cannot be blank')
    valid_chars = string.ascii_lowercase + string.digits
    if any(x for x in user if x not in valid_chars):
        raise BadArg("may only use lower letters (a-z) and digits (0-9)")
    if len(user) > 16:
        raise BadArg('cannot contain more than 16 characters')
    if user[0] in string.digits:
        raise BadArg('cannot begin with a digit (0-9)')
    if user.startswith('test'):
        raise BadArg('cannot begin with the string test')
    if user.endswith('assword'):
        raise BadArg('cannot end with the string assword')
    if user in rads.OUR_RESELLERS:
        raise BadArg('restoring this user with this tool is forbidden')
    return user


def cpmove_file_type(str_path: str) -> Path:
    """Argparse type: a cPanel backup within /home"""
    path = existing_file(str_path)
    if not path.is_relative_to('/home'):
        raise BadArg('Backups should be in the /home directory')
    if not CPMOVE_RE.match(path.name):
        raise BadArg(f"{path} is not a cPanel backup")
    return path


def existing_file(str_path: str) -> Path:
    """Argparse type: any existing file"""
    path = Path(str_path).resolve()
    if not path.is_file():
        raise BadArg(f'{path} is not a file')
    return path


def path_in_home(str_path: str) -> Path:
    """Argparse type: a path relative to /home"""
    path = Path(str_path).resolve()
    if not path.is_dir() or not path.is_relative_to('/home'):
        raise BadArg(f'{path} is not a directory relative to /home')
    return path


def ipaddress(addr_str: str) -> netaddr.IPAddress:
    """Argparse type: checks an IP address"""
    try:
        if netaddr.valid_ipv4(addr_str) or netaddr.valid_ipv6(addr_str):
            addr = netaddr.IPAddress(addr_str)
        else:
            addr = None
    except netaddr.AddrFormatError:
        addr = None
    if addr and (
        addr.is_netmask() or addr.is_loopback() or addr.is_link_local()
    ):
        addr = None
    if addr:
        return addr
    raise BadArg('invalid IP Address')