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 |
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')