PNG  IHDRxsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<,tEXtComment File Manager

File Manager

Path: /opt/cloudlinux/venv/lib/python3.11/site-packages/xray/console_utils/

Viewing File: validations.py

# -*- coding: utf-8 -*-

# Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2021 All Rights Reserved
#
# Licensed under CLOUD LINUX LICENSE AGREEMENT
# http://cloudlinux.com/docs/LICENSE.TXT

"""
This module contains functions for performing necessary validations
"""
import ipaddress
import json
import logging
import re
from argparse import Namespace
from urllib.parse import urlparse

from schema import Schema, And, Optional, Regex, SchemaError, Use, Or
from xray.internal.utils import read_sys_id

logger = logging.getLogger('validations')

# --- URL validator regexps taken from Django framework ---
ul = '\u00a1-\uffff'  # unicode letters range (must not be a raw string)
# IP patterns
ipv4_re = r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}'
# Host patterns
hostname_re = r'[a-z' + ul + r'0-9](?:[a-z' + ul + r'0-9-]{0,61}[a-z' + ul + r'0-9])?'
# Max length for domain name labels is 63 characters per RFC 1034 sec. 3.1
domain_re = r'(?:\.(?!-)[a-z' + ul + r'0-9-]{1,63}(?<!-))*'
tld_re = (
        r'\.'  # dot
        r'(?!-)'  # can't start with a dash
        r'(?:[a-z' + ul + '-]{2,63}'  # domain label
                          r'|xn--[a-z0-9]{1,59})'  # or punycode label
                          r'(?<!-)'  # can't end with a dash
                          r'\.?'  # may have a trailing dot
)
host_re = '(' + hostname_re + domain_re + tld_re + '|localhost)'
regex = re.compile(
    r'^(?:http)s?://'  # scheme
    r'(?:[^\s:@/]+(?::[^\s:@/]*)?@)?'  # user:pass authentication
    r'(?:' + ipv4_re + '|' + host_re + ')'
                                       r'(?::\d{2,5})?'  # port
                                       r'(?:[/?#][^\s]*)?'  # resource path
                                       r'\Z', re.IGNORECASE)
# ---

# --- EMAIL validator regexp taken from https://emailregex.com/ ---
email_regex = r"""(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])"""
# ---


# --- Validation helper functions
def is_ip_valid(ipaddr: str) -> bool:
    """
    Checks if given IP address is a valid one
    :param ipaddr: IP address
    :return: True if IP address is valid, False otherwise
    """
    if isinstance(ipaddr, int):
        return False
    try:
        ipaddress.ip_address(ipaddr)
        return True
    except ValueError:
        return False


def is_ipv4_valid(ipaddr: str) -> bool:
    """
    Checks if given IP address is a valid one for IPv4
    '*' is also allowed
    :param ipaddr: IPv4 address
    :return: True if IPv4 address is valid, False otherwise
    """
    if isinstance(ipaddr, int):
        return False
    if ipaddr == '*':
        return True
    try:
        ipaddress.IPv4Address(ipaddr)
        return True
    except ValueError:
        return False


def url_cast(orig_url: str) -> str:
    """
    Add http scheme if original url is missing it
    """
    fragments = urlparse(orig_url)
    if not fragments.scheme:
        return f'http://{orig_url}'
    return orig_url
# ---


# --- Validation Schemas
validation_schema = Schema({
    'command': And(str, lambda c: c in ('start', 'stop', 'continue',
                                        'complete', 'delete',
                                        'autocomplete-tasks',
                                        'enable-continuous',
                                        'disable-continuous',
                                        'start-continuous',
                                        'stop-continuous',
                                        'continuous-tracing-list',
                                        'tasks-list', 'requests-list',
                                        'request-data',
                                        'enable-user-agent',
                                        'disable-user-agent',
                                        'user-agent-status',
                                        'advanced-metrics',
                                        'enable-serverwide-mode',
                                        'disable-serverwide-mode'),
                   error='Invalid command'),
    Optional('lang'): Or(str, None),
    'system_id': And(str, lambda s: s == read_sys_id(),
                     error='system_id is invalid'),
    Optional('tracing_task_id'): str,
    Optional('url'): And(Use(url_cast), Regex(regex, error='URL is invalid')),
    Optional('email'): And(str, Regex(email_regex, error='EMAIL is invalid')),
    Optional('client_ip'): And(str, is_ipv4_valid,
                               error='IP is invalid'),
    Optional('time'): And(int, lambda t: 0 < t <= 2880,
                          error='minimum time count is 1 minute, maximum - 48 hours (2880 minutes)'),
    Optional('request_qty'): And(int, lambda q: 0 < q <= 100,
                                 error='minimum request_qty count is 1, maximum - 100'),
    Optional('request_id'): And(int, lambda q: q > 0,
                                error='minimum request_id is 1'),
    Optional('enable'): Or(bool, None),
    Optional('disable'): Or(bool, None),
    Optional('status'): Or(bool, None),
})

validation_user_schema = Schema({
    'command': And(str, lambda c: c in ('start', 'stop', 'continue',
                                        'complete', 'delete',
                                        'tasks-list', 'requests-list',
                                        'request-data', 'user-agent-status'),
                   error='Invalid user command'),
    Optional('lang'): Or(str, None),
    Optional('tracing_task_id'): str,
    Optional('url'): And(Use(url_cast), Regex(regex, error='URL is invalid')),
    Optional('client_ip'): And(str, is_ipv4_valid,
                               error='IP is invalid'),
    Optional('time'): And(int, lambda t: 0 < t <= 2880,
                          error='minimum time count is 1 minute, maximum - 48 hours (2880 minutes)'),
    Optional('request_qty'): And(int, lambda q: 0 < q <= 100,
                                 error='minimum request_qty count is 1, maximum - 100'),
    Optional('request_id'): And(int, lambda q: q > 0,
                                error='minimum request_id is 1')
})

validation_adviser_schema = Schema({
    Optional('api_version'): Or(str, None),
    Optional('lang'): Or(str, None),
    'command': And(str, lambda c: c in ('list',
                                        'details',
                                        'apply',
                                        'rollback',
                                        'subscription',
                                        'agreement',
                                        'counters',
                                        'status',
                                        'sites-status',
                                        'wordpress-plugin-install',
                                        'wordpress-plugin-uninstall',
                                        'get-options',
                                        'get-limits',
                                        'get-usage',
                                        'update-advices-metadata',

                                        'awp-cdn-get-pullzone',
                                        'awp-cdn-remove-pullzone',
                                        'awp-cdn-purge',
                                        'awp-sync',
                                        'get-cdn-usage',
                                        'report-analytics',

                                        'wp-plugin-data',
                                        'wp-plugin-copy'),
                   error='Invalid command'),
    Optional('advice_id'): Or(str, None),
    Optional('ignore_errors'): bool,
    Optional('async_mode'): bool,
    Optional('source'): Or(str, None),
    Optional('reason'): Or(str, None),
    Optional('extends'): bool,
    Optional('listen'): bool,
    Optional('username'): Or(str, None),

    Optional('account_id'): Or(str, None),
    Optional('domain'): str,
    Optional('website'): str,
    Optional('text'): str,
    Optional('accept_license_terms'): bool,

    Optional('analytics_data'): Or(str, None),

    # for analytics reporting
    Optional('feature'): Or(str, None),
    Optional('event'): Or(str, None),
    Optional('user_hash'): Or(str, None),
    Optional('journey_id'): Or(str, None),
    Optional('variant_id'): Or(str, None),

    # for wp plugin manager
    Optional('plugin_name'): str,
    Optional('plugin_version'): str,
    Optional('tmp_dir'): str,
})

# ---


def _validate(input_args: dict, _scheme: Schema) -> Namespace:
    """
    Validate given input with schema
    Input arguments expected in s dict form
    :param input_args: dict with input data
    :param _scheme: schema for validation
    """
    try:
        return Namespace(**(_scheme.validate(input_args)))
    except SchemaError as e:
        logger.error('Input validation error', extra={'err': str(e)})
        raise SystemExit(json.dumps({
            'result': f'Input validation error: {str(e)}'
        }))


def validate(input_args: dict) -> Namespace:
    """
    Validate given input with schema
    Input arguments expected in s dict form
    :param input_args: dict with input data
    :param _scheme: schema for validation
    """
    return _validate(input_args, validation_schema)


def validate_user(input_args: dict) -> Namespace:
    """
    Validate given input with schema
    Input arguments expected in s dict form
    :param input_args: dict with input data
    :param _scheme: schema for validation
    """
    return _validate(input_args, validation_user_schema)


def validate_adviser(input_args: dict) -> Namespace:
    """
    Validate given input with schema
    Input arguments expected in s dict form
    :param input_args: dict with input data
    :param _scheme: schema for validation
    """
    return _validate(input_args, validation_adviser_schema)
b IDATxytVսϓ22 A@IR :hCiZ[v*E:WũZA ^dQeQ @ !jZ'>gsV仿$|?g)&x-EIENT ;@xT.i%-X}SvS5.r/UHz^_$-W"w)Ɗ/@Z &IoX P$K}JzX:;` &, ŋui,e6mX ԵrKb1ԗ)DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA݀!I*]R;I2$eZ#ORZSrr6mteffu*((Pu'v{DIߔ4^pIm'77WEEE;vƎ4-$]'RI{\I&G :IHJ DWBB=\WR޽m o$K(V9ABB.}jѢv`^?IOȅ} ڶmG}T#FJ`56$-ھ}FI&v;0(h;Б38CӧOWf!;A i:F_m9s&|q%=#wZprrrla A &P\\СC[A#! {olF} `E2}MK/vV)i{4BffV\|ۭX`b@kɶ@%i$K z5zhmX[IXZ` 'b%$r5M4º/l ԃߖxhʔ)[@=} K6IM}^5k㏷݆z ΗÿO:gdGBmyT/@+Vɶ纽z񕏵l.y޴it뭷zV0[Y^>Wsqs}\/@$(T7f.InݺiR$푔n.~?H))\ZRW'Mo~v Ov6oԃxz! S,&xm/yɞԟ?'uaSѽb,8GלKboi&3t7Y,)JJ c[nzӳdE&KsZLӄ I?@&%ӟ۶mSMMњ0iؐSZ,|J+N ~,0A0!5%Q-YQQa3}$_vVrf9f?S8`zDADADADADADADADADAdqP,تmMmg1V?rSI꒟]u|l RCyEf٢9 jURbztѰ!m5~tGj2DhG*{H9)꒟ר3:(+3\?/;TUݭʴ~S6lڧUJ*i$d(#=Yݺd{,p|3B))q:vN0Y.jkק6;SɶVzHJJЀ-utѹսk>QUU\޲~]fFnK?&ߡ5b=z9)^|u_k-[y%ZNU6 7Mi:]ۦtk[n X(e6Bb."8cۭ|~teuuw|ήI-5"~Uk;ZicEmN/:]M> cQ^uiƞ??Ңpc#TUU3UakNwA`:Y_V-8.KKfRitv޲* 9S6ֿj,ՃNOMߤ]z^fOh|<>@Å5 _/Iu?{SY4hK/2]4%it5q]GGe2%iR| W&f*^]??vq[LgE_3f}Fxu~}qd-ږFxu~I N>\;͗O֊:̗WJ@BhW=y|GgwܷH_NY?)Tdi'?խwhlmQi !SUUsw4kӺe4rfxu-[nHtMFj}H_u~w>)oV}(T'ebʒv3_[+vn@Ȭ\S}ot}w=kHFnxg S 0eޢm~l}uqZfFoZuuEg `zt~? b;t%>WTkķh[2eG8LIWx,^\thrl^Ϊ{=dž<}qV@ ⠨Wy^LF_>0UkDuʫuCs$)Iv:IK;6ֲ4{^6եm+l3>݆uM 9u?>Zc }g~qhKwڭeFMM~pМuqǿz6Tb@8@Y|jx](^]gf}M"tG -w.@vOqh~/HII`S[l.6nØXL9vUcOoB\xoǤ'T&IǍQw_wpv[kmO{w~>#=P1Pɞa-we:iǏlHo׈꒟f9SzH?+shk%Fs:qVhqY`jvO'ρ?PyX3lх]˾uV{ݞ]1,MzYNW~̈́ joYn}ȚF߾׮mS]F z+EDxm/d{F{-W-4wY듏:??_gPf ^3ecg ҵs8R2מz@TANGj)}CNi/R~}c:5{!ZHӋӾ6}T]G]7W6^n 9*,YqOZj:P?Q DFL|?-^.Ɵ7}fFh׶xe2Pscz1&5\cn[=Vn[ĶE鎀uˌd3GII k;lNmشOuuRVfBE]ۣeӶu :X-[(er4~LHi6:Ѻ@ԅrST0trk%$Č0ez" *z"T/X9|8.C5Feg}CQ%͞ˣJvL/?j^h&9xF`њZ(&yF&Iݻfg#W;3^{Wo^4'vV[[K';+mӍִ]AC@W?1^{එyh +^]fm~iԵ]AB@WTk̏t uR?l.OIHiYyԶ]Aˀ7c:q}ힽaf6Z~қm(+sK4{^6}T*UUu]n.:kx{:2 _m=sAߤU@?Z-Vކеz왍Nэ{|5 pڶn b p-@sPg]0G7fy-M{GCF'%{4`=$-Ge\ eU:m+Zt'WjO!OAF@ik&t݆ϥ_ e}=]"Wz_.͜E3leWFih|t-wZۍ-uw=6YN{6|} |*={Ѽn.S.z1zjۻTH]흾 DuDvmvK.`V]yY~sI@t?/ϓ. m&["+P?MzovVЫG3-GRR[(!!\_,^%?v@ҵő m`Y)tem8GMx.))A]Y i`ViW`?^~!S#^+ѽGZj?Vģ0.))A꨷lzL*]OXrY`DBBLOj{-MH'ii-ϰ ok7^ )쭡b]UXSְmռY|5*cֽk0B7镹%ڽP#8nȎq}mJr23_>lE5$iwui+ H~F`IjƵ@q \ @#qG0".0" l`„.0! ,AQHN6qzkKJ#o;`Xv2>,tێJJ7Z/*A .@fفjMzkg @TvZH3Zxu6Ra'%O?/dQ5xYkU]Rֽkق@DaS^RSּ5|BeHNN͘p HvcYcC5:y #`οb;z2.!kr}gUWkyZn=f Pvsn3p~;4p˚=ē~NmI] ¾ 0lH[_L hsh_ғߤc_њec)g7VIZ5yrgk̞W#IjӪv>՞y睝M8[|]\շ8M6%|@PZڨI-m>=k='aiRo-x?>Q.}`Ȏ:Wsmu u > .@,&;+!!˱tﭧDQwRW\vF\~Q7>spYw$%A~;~}6¾ g&if_=j,v+UL1(tWake:@Ș>j$Gq2t7S?vL|]u/ .(0E6Mk6hiۺzښOrifޱxm/Gx> Lal%%~{lBsR4*}{0Z/tNIɚpV^#Lf:u@k#RSu =S^ZyuR/.@n&΃z~B=0eg뺆#,Þ[B/?H uUf7y Wy}Bwegל`Wh(||`l`.;Ws?V@"c:iɍL֯PGv6zctM̠':wuW;d=;EveD}9J@B(0iհ bvP1{\P&G7D޴Iy_$-Qjm~Yrr&]CDv%bh|Yzni_ˆR;kg}nJOIIwyuL}{ЌNj}:+3Y?:WJ/N+Rzd=hb;dj͒suݔ@NKMԄ jqzC5@y°hL m;*5ezᕏ=ep XL n?מ:r`۵tŤZ|1v`V뽧_csج'ߤ%oTuumk%%%h)uy]Nk[n 'b2 l.=͜E%gf$[c;s:V-͞WߤWh-j7]4=F-X]>ZLSi[Y*We;Zan(ӇW|e(HNNP5[= r4tP &0<pc#`vTNV GFqvTi*Tyam$ߏWyE*VJKMTfFw>'$-ؽ.Ho.8c"@DADADADADADADADADA~j*֘,N;Pi3599h=goضLgiJ5փy~}&Zd9p֚ e:|hL``b/d9p? fgg+%%hMgXosج, ΩOl0Zh=xdjLmhݻoO[g_l,8a]٭+ӧ0$I]c]:粹:Teꢢ"5a^Kgh,&= =՟^߶“ߢE ܹS J}I%:8 IDAT~,9/ʃPW'Mo}zNƍ쨓zPbNZ~^z=4mswg;5 Y~SVMRXUյڱRf?s:w ;6H:ºi5-maM&O3;1IKeamZh͛7+##v+c ~u~ca]GnF'ټL~PPPbn voC4R,ӟgg %hq}@#M4IÇ Oy^xMZx ) yOw@HkN˖-Sǎmb]X@n+i͖!++K3gd\$mt$^YfJ\8PRF)77Wא!Cl$i:@@_oG I{$# 8磌ŋ91A (Im7֭>}ߴJq7ޗt^ -[ԩSj*}%]&' -ɓ'ꫯVzzvB#;a 7@GxI{j޼ƌ.LÇWBB7`O"I$/@R @eee@۷>}0,ɒ2$53Xs|cS~rpTYYY} kHc %&k.], @ADADADADADADADADA@lT<%''*Lo^={رc5h %$+CnܸQ3fҥK}vUVVs9G R,_{xˇ3o߾;TTTd}馛]uuuG~iԩ@4bnvmvfϞ /Peeeq}}za I~,誫{UWW뮻}_~YƍSMMMYχ֝waw\ďcxꩧtEƍկ_?۷5@u?1kNׯWzz/wy>}zj3 k(ٺuq_Zvf̘:~ ABQ&r|!%KҥKgԞ={<_X-z !CyFUUz~ ABQIIIjݺW$UXXDٳZ~ ABQƍecW$<(~<RSSvZujjjԧOZQu@4 8m&&&jԩg$ď1h ͟?_{768@g =@`)))5o6m3)ѣƌJ;wҿUTT /KZR{~a=@0o<*狔iFɶ[ˎ;T]]OX@?K.ۈxN pppppppppppppppppPfl߾] ,{ァk۶mڿo5BTӦMӴiӴ|r DB2e|An!Dy'tkΝ[A $***t5' "!駟oaDnΝ:t֭[gDШQ06qD;@ x M6v(PiizmZ4ew"@̴ixf [~-Fٱc&IZ2|n!?$@{[HTɏ#@hȎI# _m(F /6Z3z'\r,r!;w2Z3j=~GY7"I$iI.p_"?pN`y DD?: _  Gÿab7J !Bx@0 Bo cG@`1C[@0G @`0C_u V1 aCX>W ` | `!<S `"<. `#c`?cAC4 ?c p#~@0?:08&_MQ1J h#?/`7;I  q 7a wQ A 1 Hp !#<8/#@1Ul7=S=K.4Z?E_$i@!1!E4?`P_  @Bă10#: "aU,xbFY1 [n|n #'vEH:`xb #vD4Y hi.i&EΖv#O H4IŶ}:Ikh @tZRF#(tXҙzZ ?I3l7q@õ|ۍ1,GpuY Ꮿ@hJv#xxk$ v#9 5 }_$c S#=+"K{F*m7`#%H:NRSp6I?sIՖ{Ap$I$I:QRv2$Z @UJ*$]<FO4IENDB`