Ӻh&JdZddlZddlZddlZddlZddlZddlZddlmZddl m Z m Z m Z ddl mZddlZddlmZmZmZmZmZmZddlmZddlmZdd lmZmZdd lmZm Z m!Z!m"Z"m#Z#m$Z$dd l%m&Z&m'Z'm(Z(dd l)m*Z+dd l,m-Z-ddl.m/Z/m0Z0m1Z1m2Z2dZ3dZ4ej56e4dZ7ej56e4dZ8ej56e4dZ9ej56e8dZ:ej56e4ddZ;dZej56e>dZ?ej56e>dZ@ejAdejBe<ZCdZDdZEdZFd ZGd!ZHdDd#ZIdEd%ZJdFd'ZKd(ZLd)ZMd*ZNd+ZOd,ZPd-ZQdGd.ZRd/ZSd0ZTe'jUe=g1d2e eVeVffd3ZWd4ZXdHd5ZYd6Z*d7ZZd8Z[d9Z\d:Z]d;Z^d<Z_d=Z`d>Zad?Zbd@ZcdAZdGdBdCe'ZedS)Iz. CloudLinux API for DirectAdmin control panel N) format_exc)DictListTuple)urlparse)WebConfigMissingWebConfigParsingErrorapache_conf_parser load_fastnginx_conf_parser&read_unicode_file_with_decode_fallback)load)ClPwd)"_docroot_under_user_via_custom_binget_domains_via_custom_binary)CpApiTypeErrorNoDBAccessDataNoDomain NoPanelUser ParsingError ReadFileError)DomainDescriptionGeneralPanelPluginV1PHPDescriptionget_admin_email)Feature)ExternalProgramFailedfind_module_param_in_configget_file_linesgrep DirectAdminz/usr/local/directadminzconf/directadmin.confdatazconf/mysql.confusers custombuildz options.confz user.confz/etc/virtual/domainownersadminz reseller.list admin.listz.+/(.+)/c~tjdptjdS)N"/usr/local/directadmin/directadminz(/usr/local/directadmin/custombuild/build)ospathisfile/builddir/build/BUILD/imunify360-venv-2.5.2/opt/imunify360/venv/lib/python3.11/site-packages/clcommon/cpapi/plugins/directadmin.pydetectr0Ks2 7>>> ? ? F 7>>D E EFr.ci} tt}|d|d<|d|d<nW#t$r%}tdt |z|d}~wt $r}tdt|d}~wwxYw|S)Nuserloginpasswdpassz0Can not open file with data to database access; z+Can not get database access data from file ) loadconfig DA_DB_CONFIOErrorrstrKeyError)access login_dataerrs r/ db_accessr>Ps F  ++ $V,w#H-v  >S I     F* F F    Ms */ B A B&A>>Bcdtjtjtdt D}d|D}t |S)NcBg|]}t|Sr-) USER_PATTERNmatch).0r+s r/ zcpusers..bs&nnnt,$$T**nnnr.*c<g|]}||dS))group)rCrBs r/rDzcpusers..cs'BBBUEB%++a..BBBr.)globr*r+join DA_USERS_PATH USER_CONFtuple) match_list users_lists r/cpusersrPasTnntym]`bkAlAl7m7mnnnJBBjBBBJ   r.cttd5}d|D}dddn #1swxYwYt|S)Nutf-8encodingc6g|]}|Sr-striprClines r/rDzresellers..is 5554$**,,555r.)openRESELLERS_LISTrM)fresellers_lists r/ resellersr^gs nw / / /61551555666666666666666   044cttd5}d|D}dddn #1swxYwYt|S)NrRrSc6g|]}|Sr-rVrXs r/rDzadmins..os 222tzz||222r.)rZ ADMINS_LISTset)r\ admins_lists r/adminsrems kG , , ,322222 333333333333333 {  r_Fcddlm}t}|||}|r6|tt t z }|S)Nr)_dblogin_cplogin_pairs) cplogin_lstr;) clcommon.cpapi.plugins.universalrgr>rM get_da_userrKitems)rhwith_system_usersrgr;r#s r/dblogin_cplogin_pairsrmsseGGGGGG [[F ! !k& I I ID: k-006688999 Kr.Tc,i}tj}tj|tjd}|D]}tj|r|dz|zdz} t |d5}t|dkr|dd}|||<dddn #1swxYwY#t$r'|s"tj d|zYwxYwtj||S) Nz./*/z /domains.listrRrSrzNo file ) r*getcwdchdirrIr+isdirrZlenreadliner8sysstderrwrite) r+quietr$cur_dirdir_listuser_dir file_domainsr\ user_names r/rjrj|sk EikkGHTNNNyH @ @ 7== " " @#:0?BL @,9995Q1::<<((1,,$,QRRL +4i(555555555555555 @ @ @@J$$Z,%>??? @ @HW Ls6-C >5B?3 C ?C C C C  .C<;C<cploginpackagemailresellerdnslocalecF g}t|tr|g}nat|ttfrt|}n5|t }n$t ddt |jddddfdd d d  fd |D}|D]|}tj t|t}tj |r0t| | fd |D}|S)Ncpinfozstr|unicode|list|tuple)funcnamesupportedtypes received_typec|ddkr|dS|dS)Nusertyperusernamecreatorgetconfigs r/ _get_resellerzcpinfo.._get_resellers= ::j ! !Z / /::j)) )zz)$$$r.c,|dS)Nrrrs r/zcpinfo..s :0F0Fr.c,|dS)Nrrrs r/rzcpinfo..s 90E0Er.c,|dS)Nemailrrs r/rzcpinfo..sVZZ-@-@r.c|SNr-)rrs r/rzcpinfo..sv1F1Fr.c,|dS)Ndomainrrs r/rzcpinfo..sFJJx,@,@r.c,|dS)Nlanguagerrs r/rzcpinfo..svzz*/E/Er.rc g|] }| Sr-r-)rCkey_user_conf_maps r/rDzcpinfo..s 3 3 3cnS! 3 3 3r.c&g|] }|Sr-r-)rCr user_configs r/rDzcpinfo..s#@@@#SS--@@@r.) isinstancer9listrMrPrtype__name__r*r+rJrKrLexistsr append) cpuserkeylssearch_sys_usersreturned cpusers_listkeyls_ruser_conf_filerrrs @@@r/rrsdH&#Bx FT5M * *BV}} yy h?W+/<<+@BBB B%%% "G!F!E!E@@"F"F"F"F@@ E E GGN 4 3 3 3U 3 3 3F BBmXyII 7>>. ) ) B#N33K OO@@@@@@@ A A A Or.cd}t}t|D]*}||ks|d|r ||}n+|g}nt |}|D]}||vr |d|fcSdS)z Old method for getting doc_root for domain under root Method reads DA config :return: (doc_root, username) cortege N.rG)_load_domains_ownersrkeysendswith userdomains)rr~_domain_to_user_map main_domain domains_listds r/_docroot_under_rootrsI.00/446677 [ FOO4E 4E4E$F$F +K8I E ! "9-- ## Q;;Q4? " " " ##r.ct}|tjd}t |j}|D]}|d|kr|d|jfcS dS)z Old method for getting doc_root for domain under user Method parses /home//domains directory :return: (doc_root, username) cortege r server_name document_rootN)r get_pw_by_uidr*getuid_get_domains_list_as_userpw_dirpw_name)rclpwduser_pwlist_domains_and_doc_roots domain_datas r/!_docroot_under_user_old_mechanismrs GGE!!")++..q1G!:7>!J!J1AA } % / //@ @ @ @ 0AAr.cd}|}tj}tj}|dkr|dkrt |}nt |}||St d|d)z Retrieves document root for domain :param domain: Domain to determine doc_root :return: Cortege: (doc_root, domain_user) Nrz'Can't obtain document root for domain '')rWr*rgeteuidrrr)rresuideuids r/docrootrs C \\^^F )++C :<tj|rtj|}|dks|rst|}|D]_} | ddur | d|vr%| d| d| df<| | d| df`|St\} } | dkr| S| d krtd |d td | ) aD Get user's domains list :return list: domain names Example: [('cltest1.com', '/home/cltest1/domains/cltest1.com/public_html'), ('mk.cltest1.com', '/home/cltest1/domains/cltest1.com/public_html/mk'), ('cltest11.com', '/home/cltest1/domains/cltest11.com/public_html') ] ~rrrTrr zUser z not found in the databasezFailed to get userdomains: )r*r+rJrKrr expanduserislinkrealpathrinsertrrrr) ras_rootrrrmain_domain_pathr public_pathrrrcrs r/rr1sL ]F33I :<>) $ $ ""3<00I',,y-88K w~~k""9rw~~k'B'B97++K88 qyyGy.y99   V VFe}$$m$(888##A}(=vo?V'WXXXX##VM%:F?>) $ $ $ww~66H MM( # # #  ??r.cFt|dS)z Return domain's owner :param domain: Domain/sub-domain/add-domain name :return: user name or None if domain not found N)rrrs r/ domain_ownerrqs ! ! % %fd 3 33r.) panel_parkerreturnc tt}n6#ttf$r"}t t ||d}~wwxYwi}|D]^}|}|s|d\}}|}|}|||<_|S)zC Get domain<->user map from /etc/virtual/domainowners file N:) r DOMAINOWNERS splitlinesOSErrorr8rr9rWsplit) domains_linesrrline_domain_user_s r/rrzs +>|LLWWYY W +++CFF##*+ - -   S))--// ',G$$ s&)AAAc|gSt}tjt |d} t |d5}d|D}||tt|t|zcdddS#1swxYwYdS#ttf$rgcYSwxYw)z Return list of reseller users :param resellername: reseller name; return empty list if None :return list[str]: user names list Nz users.listrRrSc6g|]}|Sr-rV)rCitems r/rDz"reseller_users..s >>>4$**,,>>>r.) rrr*r+rJrKrZrrrcr8r) resellernameall_users_dictusers_list_filerOs r/reseller_usersrs&  WW**,,Ngll=, MMO /G 4 4 4 ? >>:>>>J   l + + +N++c*oo=>>  ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? W  s7 CA B7* C7B;;C>B;?CCCcd|gSt|}tt|dS)z Get pairs user <=> domain for given reseller; Empty list if cannot get or no users found; :type resellername: str :return list[tuple[str, str]]: tuple[username, main_domain] N)rr)r)rdictr)rr$s r/reseller_domainsrs8 < ( (E u$6777 8 88r.ctjtdt}t |}|dtS)Nr&r)r*r+rJrKrLr6runiversal_get_admin_email)admin_user_filecnfs r/rrsAgll='9EEO _ % %C 777577 8 88r.ctjt|t}tj|r< t |ddkS#t$r}td|d}~wwxYwdS)z{ Check if given user is reseller; :type username: str :rtype: bool :raise: ParsingError, ReadFileError rrz)User config exists, but no usertype givenNF) r*r+rJrKrLrr6 IndexErrorr)rrrs r/ is_resellerrs',,}h BBK w~~k""S Sk**:6*D D S S SJKKQR R S 5s A%% B/A??Bcd|dS)Nzhttp://z:2222r-rs r/get_user_login_urlr s "V " " ""r.c`i} tt}n#ttf$rYdSwxYwd}d|d|vrsd|d|vrki|t |<|d|d|t |d<|d|d|t |d<|dz }d|d|vrd|d|vk|S)zJ Return map (PHP_DA_CODE:{PHP_HANDLER, PHP_VERSION}) :return: NrGphp_mode_release handler_typephp_version_id)r6 DA_OPT_PATHr8rr9) _php_da_mapphp_cfgis r/_get_da_php_configr+s  K[)) W tt A ...G # #(9a(9(9(9W(D(D CFF.5nAnnn.E CFFN+078Ia8I8I8I0J CFF,- Q ...G # #(9a(9(9(9W(D(D s ..ctjtt |dt |dz} t |}n#t tf$rYdSwxYw|d}||dkrd}|S)z Return php code from domain config :param domain: :param owner: :return: string '1' or '2' - php code in DA rz.conf1 php1_selectN0) r*r+rJrKr9r6r8rr)rownerdomain_config_file domain_config domain_phps r/_get_php_code_info_for_domainr4smSZZCPVKKZaLabb"#566 W ss""=11JZ3.. sAA+*A+cg}|D]:}|d|vr||d;|S)Nr)rr) all_domainsmapped_all_domains subdomainsrs r/_get_subdomainsr9sVJ%% !9*//11 1 1 &)$$$$ r.c t}i}t}||Si}|D].\}}||g|/|D]\}}t |} t ||}n#t$rg}YnwxYw|D]}t||} | |vs|| ddkrd} || } t||} n#t$rg} YnwxYw|g|z| zD]A} t|| d| dd| d dd || <B|S) a Return php version information for each domain :return: domain to php info mapping Example output: {'cltest.com': {'handler_type': 'mod_php', 'php_version_id': '7.1', 'username': 'cltest'}, 'cltest2.com': {'handler_type': 'fastcgi', 'php_version_id': '7.3', 'username': 'kek_2'}, 'cltest3.com': {'handler_type': 'suphp', 'php_version_id': '5.5', 'username': 'cltest3'}, 'omg.kek': {'handler_type': 'php-fpm', 'php_version_id': '5.2', 'username': 'cltest'}} :rtype: dict[str, dict] Nr&nor-r%r"rr)rr&r%display_version) rr+rk setdefaultrrr9 Exceptionr4 _useraliasesrreplace) map_domain_user result_map php_da_mapowner_to_domainsrr0rall_domains_in_httpd_filer8 php_info_codephp_infodomain_aliases domain_entitys r/get_domains_php_inforJs(+,,OJ#%%J-/(..00>> ##E2..55f====*0022  w$/$6$6! ()BOTTJJ   JJJ   F9&%HHMJ..!-01ABdJJ!$ !-0H $!-eV!  / / /1BC        r.cpt}|gS|}g}|D] }|d}|dkrd|ddd}tj|sLt |}|r|}|td|dd|tj ||tj |d tj |d   |S) zL Gets compiled phpXY - could be chosen via DirectAdmin PHP Selector Nr&r;z/usr/local/phprrror"zbin/phpz lib/php.inirL) r+valuesr@r*r+rrbrWrrrJ)rCinstalled_php_datarU version_inforNramodules_dir_paths r/"_get_compiled_custombuild_versionsrhisL$%%J $**,,N+  /0 d?? JwsB/G/GJJJw~~122  45HII  8/5577 n7W__S"5577 011( 0)<< 0-@@         r.c Xtj|sgSg} t|d5}|}dddn #1swxYwYn=#t $r0}t jt jd|d|dYd}~nd}~wwxYwd|DS)z1 Parse user aliases file and return data rRrSNzCan`t open file "z " due to : ""chg|]/}|dd0S)=r)rWr )rCrecords r/rDz _get_aliases..s3 < < >$   DV $ ) ) ) !Q;;==D ! ! ! ! ! ! ! ! ! ! ! ! ! ! ! VVV f(*Td*T*TPQ*T*T*TUUUUUUUUV < z1PanelPlugin.get_cp_description..s.GG4T[[..GGGGGGr.cR|ddS)Nrr)r@isdigit)ss r/ _is_floatz1PanelPlugin.get_cp_description.._is_floats"yyb))11333r.r)namerNadditional_info) r^PopenPIPE communicater nextfilterr}r>)rzpout_ version_wordsrrNs r/get_cp_descriptionzPanelPlugin.get_cp_descriptions  !5s;!!  ) Q  ) ) ) ) ) ) ) ) ) ) ) ) ) ) )HG399;;GGGM 4 4 46)];;R@@G&7tTT T   44 s5.B)A B)AB)AA B)) B76B7ctS)z Getting root access to mysql database. For example {'login': 'root', 'db': 'mysql', 'host': 'localhost', 'pass': '9pJUv38sAqqW'} :return: root access to mysql database :rtype: dict :raises: NoDBAccessData )r>r~s r/r>zPanelPlugin.db_accesss{{r.ctS)z Generates a list of cpusers registered in the control panel :return: list of cpusers registered in the control panel :rtype: tuple )rPr~s r/rPzPanelPlugin.cpuserssyyr.ctS)z Generates a list of resellers in the control panel :return: list of cpusers registered in the control panel :rtype: tuple )r^r~s r/r^zPanelPlugin.resellerss{{r.c t|S)zc Check if given user is reseller; :type username: str :rtype: bool )r)rzrs r/rzPanelPlugin.is_resellers 8$$$r.ctjt|t}tj|sdSt |}|ddkS)z| Return True if username is in admin names :param str username: user to check :return: bool Frr&)r*r+rJrKrLrr )rzrrrs r/is_adminzPanelPlugin.is_adminsS mXyIIw~~n-- 5// :&'11r.NFc"t||S)a  Get mapping between system and DB users @param cplogin_lst :list: list with usernames for generate mapping @param with_system_users :bool: add system users to result list or no. default: False )rm)rzrhrls r/rmz!PanelPlugin.dblogin_cplogin_pairss%[2CDDDr.rTc&t|||S)a Retrieves info about panel user(s) :param str|unicode|list|tuple|None cpuser: user login :param keyls: list of data which is necessary to obtain the user, the valuescan be: cplogin - name/login user control panel mail - Email users reseller - name reseller/owner users locale - localization of the user account package - User name of the package dns - domain of the user :param bool search_sys_users: search for cpuser in sys_users or in control panel users (e.g. for Plesk) :return: returns a tuple of tuples of data in the same sequence as specified keys in keylst :rtype: tuple )r)r)rzrrrs r/rzPanelPlugin.cpinfos"fe6FGGGGr.ctS)zR Retrieve admin email address :return: Host admin's email rr~s r/rzPanelPlugin.get_admin_email+s    r.c t|S)z Return document root for domain :param str|unicode domain: :return Cortege: (document_root, owner) )rrzrs r/rzPanelPlugin.docroot2s vr.c"t||Sr)r?)rrs r/ useraliaseszPanelPlugin.useraliases:sFF+++r.c t|S)z Return domain and document root pairs for control panel user first domain is main domain :param str|unicode cpuser: user login :return list of tuples (domain_name, documen_root) )r)rzrs r/rzPanelPlugin.userdomains>s6"""r.ctS)z Detects and returns list of folders contained the home dirs of users of the cPanel :return: list of folders, which are parent of home dirs of users of the panel )rr~s r/rzPanelPlugin.homedirsGs zzr.c t|S)z Return reseller users :param resellername: reseller name; autodetect name if None :return list[str]: user names list )rrzrs r/rzPanelPlugin.reseller_usersNs l+++r.c t|S)z Get dict[user, domain] :param reseller_name: reseller's name :rtype: dict[str, str|None] :raises DomainException: if cannot obtain domains )rrs r/rzPanelPlugin.reseller_domainsVs ---r.c t|S)z` Get login url for current panel; :type domain: str :rtype: str )r rs r/r zPanelPlugin.get_user_login_url_s "&)))r.ctS)z_ List all admins names in given control panel :return: list of strings )rer~s r/rezPanelPlugin.adminsgs xxr.c t|S)z Return domain's owner :param domain: Domain/sub-domain/add-domain name :rtype: str :return: user name or None if domain not found )rrs r/rzPanelPlugin.domain_ownernsF###r.ctS)z Return php version information for each domain :return: domain to php info mapping :rtype: dict[str, dict] )rJr~s r/rJz PanelPlugin.get_domains_php_infows $%%%r.ctt}d|vr|dS|dd}|dS|ddS)zf Retrieve current DA skin name :return: Current DA skin name. None if unknown system_skindocsrootNro)r6rrr )rrs r/_get_da_skin_namezPanelPlugin._get_da_skin_names` G$$ F " "-( (::j$//  4~~c""2&&r.ctjtd}d}t}|dkr%t |}|d|S|S)zZ Retrieve encoding name, used for package/reseller names :return: z,data/skins/enhanced/lang/en/lf_standard.htmlutf8enhanced lang_encoding)r*r+rJDA_DIRrurr6r)enhanced_skin_configdefault_encoding current_skin skin_configs r/get_encoding_namezPanelPlugin.get_encoding_namesh "w||F4bcc!"4466 : % %%%9::K???4DEE Er.r.ctjfSr)r RUBY_SELECTORr~s r/get_unsupported_cl_featuresz'PanelPlugin.get_unsupported_cl_featuress  !  r.cg} ttj}n#ttf$rYdSwxYwd|D}t ddd|D][} t |dd}||vr||E#ttf$rYXwxYw|s|d |S) zl Retrieves active httpd's ports from httpd's config :return: list of apache's ports Nc6g|]}|Sr-rVrXs r/rDz5PanelPlugin.get_apache_ports_list..s 000$000r.ListenFT)match_any_positionmultiple_searchdata_from_file rGP) r ruHTTPD_CONFIG_FILErr8r!rr rr ValueError)_httpd_ports_listlinesrYvalues r/get_apache_ports_listz!PanelPlugin.get_apache_ports_lists ";#@AAEE!   44 00%000eTbghhh  D DJJsOOA.// 111%,,U333 +      )  $ $R ( ( (  s33ABB.-B.c rd}d} tt}ttdddd|}|D]Y}|d}|ddkr|d }|dd kr|d }|d krd }Zn#t ttf$rYnwxYw||fS) a Determines active web server from options.conf, directive 'webserver' :return: tuple (active_web_server_name, apache_active_module_name) active_web_server_name: 'apache', 'nginx', 'nginx_apache', 'litespeed', 'openlitespeed', etc apache_active_module_name: 'prefork', 'event', 'worker' (None, None) if DA options.conf read/parse error Nz^apache_mpm|^webserverFT) fixed_stringrrrrlr webserverrG apache_mpmautoworker) r r'rr!rWr rr8r)web_server_nameapache_active_module_name options_linesgrep_result_listrY line_partss r/_get_active_web_server_paramsz)PanelPlugin._get_active_web_server_paramss$(! +;77M#D)APUjo9=m%]%]%] ^ ^ ) = =!ZZ\\//44 a=K//&0mOa=L000:1 -0F::4<1 =*-    D  999sBBB21B2apache_module_namec t|j|dS#tttt f$rdt fcYSwxYw)a Determine MaxRequestWorkers directive value for specified apache module. Reads config file /etc/httpd/conf/extra/httpd-mpm.conf :param apache_module_name: Current apache's module name: 'prefork', 'event', 'worker' :return: tuple (max_req_num, message) max_req_num - Maximum request apache workers number or 0 if error message - OK/Error message MaxRequestWorkersr)rHTTPD_MPM_CONFIGrr8rrr)rzrs r/#_get_max_request_workers_for_modulez/PanelPlugin._get_max_request_workers_for_modulesa #.t/D/A/BDD D*j9 # # #jll? " " " #s-AAc|\}}|| ddtdfS|dkrdd|dfS||S)z Get current maximum request apache workers from httpd's config :return: tuple (max_req_num, message) max_req_num - Maximum request apache workers number or 0 if error message - OK/Error message Nr"There was error during read/parse . Apache collector will not workapache!DA is configured for web server '9'; but 'apache' is needed. Apache collector will not work)rr'r)rzrrs r/get_apache_max_request_workersz*PanelPlugin.get_apache_max_request_workerss6:5W5W5Y5Y22  "&?&Gh;hhhh h h & &7/7777 7778QRRRr.cxd} t|j}d}d}|D]}|}||r|}.|dr@|r>||ddd}nn#t t f$rYnwxYw|S)z Determine apache mod_status URI from /etc/httpd/conf/extra/httpd-info.conf config :return Apache mod_status URI or None if error/not found Nz )r HTTPD_INFO_CONFIGrW startswithr@rr8)rz location_uri info_lineslocation_directive location_linerYs r/_get_httpd_status_uriz!PanelPlugin._get_httpd_status_uris    ((>??J!,  M"  zz||??#566$(M??#=>>=#0#8#89KR#P#P#X#XY\^`#a#a#g#g#i#iLE!    D sBB##B76B7cj|\}}| ddtdfS|dkrdd|dfS |}|dSd |d }tj|d }|jd krdd|d|jfS|jd}|d}ttd|}|ddd } t| dfS#t$rdtfcYSwxYw)z Retrieves Apache's connections number (from apache's mod_status) :return: tuple (conn_num, message) conn_num - current connections number, 0 if error message - OK/Trace Nrrrrrr)rz%Can't found mod_status URI in configszhttp://127.0.0.1z?auto)timeoutzGET z response code is rR zTotal Accesses)rrrGOK)rr'rrequestsr status_codecontentdecoder rr!rWrr>r) rzrrrurlresponse s_responses_response_listout_lists_total_accessess r/get_apache_connections_numberz)PanelPlugin.get_apache_connections_numbers"??AA  "h;hhhh h h & &7/7777 7 # 5577L#AA8\888C|C333H#s**NNN8LNNNN!)0099J(..t44OD!1/RRRSSH'{0055a8>>@@ '(($. . # # #jll? " " " #sD5DBDD21D2c<ttzS)a  Returns installed alt-php(s) on the server compiled phpXY via custombuild and alt-phpXY has different paths also user could choose version via PHP selector which was not compiled with custombuild (will be absent in DA configs) )rYrhr-r.r/get_installed_php_versionsz&PanelPlugin.get_installed_php_versions>s/003U3W3WWWr.cd}tj|sdSt|d5}|}dddn #1swxYwY|sdS|dS)Nz)/usr/local/directadmin/data/admin/ip.listrrRrSr)r*r+rrZrnrW)rz ip_list_filer\ipss r/ get_server_ipzPanelPlugin.get_server_ipIsB w~~l++ 2 , 1 1 1 Q++--C                21v||~~sAAArrcd|d}tj|sdSt|}|ddS)Nrsz /user.confrr)r*r+rr r)rr user_confs r/get_user_emails_listz PanelPlugin.get_user_emails_listVsNMMMM w~~i(( 2i(( }}Wb)))r.ctjddd|gdddj}t|dkrdSt |}|jd |jd S) Nr)z--create-login-urlzuser=TF)r\r[r]rrz://ro)r^r_r`rtrschemenetloc)rgenerated_loginparseds r/panel_login_linkzPanelPlugin.panel_login_link_s$.*N*>@R@R@R*T8<4uVVVV\    1 $ $2/**-44FM4444r.ct|d}t|dkrdS|dS)Nrorrz/evo/user/plugins/awp#/)rur rstriprt)rlinks r/panel_awp_linkzPanelPlugin.panel_awp_linkjsF++H55<>2////r.c@t}g}|D]}tjt|t }tj|sMt|}|ddkr| ||S)N suspendedyes) rPr*r+rJrKrLrr rr)rz all_userssuspended_usersr2rrs r/suspended_users_listz PanelPlugin.suspended_users_listqsII  - -DW\\-yIIN7>>.11 #N33K{++u44&&t,,,r.NFNrTr)2r __module__ __qualname__rrrrxrrr>rPr^rrrmrrr staticmethodrrrrrr rerrJrrrMrrrrrrr9rrrrrrrrr rr __classcell__)r{s@r/rurus4=?AAAAA:   %%% 2 2 2EEEE)d $HHHH&!!!,,\,###,,,,....***$$$&&&''\'$  \  U7C<-@    !49!!!\!4:5c?:::\:>#c#eTWY\T\o#### Sc3h S S S Ss8###@XX\X   *s*C***\*55\500\0       r.rur)Tr)Fr)f__doc__rIr*rSr^rvro tracebackrtypingrrr urllib.parserrclcommon.clconfparsrr r r r r rr6clcommon.clpwdrclcommon.cpapi.cpapicustombinrrclcommon.cpapi.cpapiexceptionsrrrrrrclcommon.cpapi.GeneralPanelrrrrirrclcommon.featuresrclcommon.utilsrrr r!r}rr+rJr DA_DATA_DIRr7rKr'rLrryr[rbrTescaperAr0r>rPr^rermrjrrrrrrrrrr cache_callr9rrrrr r+r4r9rJrYrbrhrqr?rur-r.r/r+s  $$$$$$$$$$!!!!!!322222  &%%%%%  " ',,v6 7 7gll66** W\\&"3 4 4  ['22 gll6=.AA  * GLLg . . i99gll9l33 rz=2. 9 9 9 9999    ###*(@@@F2   (((V = = =   PPPPP&PPPPPr.