Aurora
Adminer
Auto Root
WP Admin
cPanel Reset
Anti Backdoor
Root
usr
share
lve
modlscapi
user
Upload
New Folder
New File
Name
Size
Permissions
Actions
..
-
-
-
Upload File
Select File
New Folder
Folder Name
New File
File Name
Add WordPress Admin
Database Host
Database Name
Database User
Database Password
Admin Username
Admin Password
cPanel Password Reset
Email Address
Edit: stat_utils.py
# Copyright (c) Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2018 All Rights Reserved # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import string import sys import os import traceback import json import configparser from io import StringIO from pipes import quote import exec_command class StatUtilsException(Exception): pass def cpanel_whmapi(cmd, **kwargs): """ Perform cPanel WHM API console request and return data from result :param cmd: whm api command :return: data dict from result """ joined_kwargs = ' '.join([quote('{0}={1}'.format(k, v)) for k, v in kwargs.items()]) result = exec_command.exec_command("/usr/sbin/whmapi1 {cmd} {kw} --output json".format(cmd=cmd, kw=joined_kwargs)) try: dict_result = json.loads(''.join(result)) except ValueError: # if result is not JSON raise StatUtilsException( "Failed to get JSON from this API request: {0} {1}; output: {2}".format(cmd, joined_kwargs, ''.join(result))) try: return dict_result['data'] except KeyError: # if there are no data field in received JSON raise StatUtilsException("Failed to get data from this API result: {0}".format(dict_result)) def plesk_bin_php_handler(cmd, **kwargs): """ Perform Plesk php_handler utility console request and return result :param cmd: php_handler command :return: dict result """ # need to quote only value (-k 'v'), quoting full params ('-k v') causes API failure joined_kwargs = ' '.join(['-{0} {1}'.format(k, quote(v)) for k, v in kwargs.items()]) result = exec_command.exec_command("/usr/local/psa/bin/php_handler --{cmd} {kw} -json true".format(cmd=cmd, kw=joined_kwargs)) try: return json.loads(''.join(result)) except ValueError: raise StatUtilsException( "Failed to get JSON from this API request: php_handler {0} {1}; output: {2}".format(cmd, joined_kwargs, ''.join(result))) def get_da_domains(): """ Get domains per user :return: dict( user: list of domains ) """ da_users_path = '/usr/local/directadmin/data/users' da_domains_path = '/usr/local/directadmin/data/users/{user}/domains.list' da_users = os.listdir(da_users_path) domains = dict.fromkeys(da_users) try: for user in da_users: with open(da_domains_path.format(user=user), 'r') as domains_list_file: domains[user] = set([l.strip() for l in domains_list_file.readlines()]) except (OSError, IOError): raise StatUtilsException(''.join(traceback.format_exc().split('\n'))) return domains def get_da_php_options(): """ Get php settings from options.conf :return: dict( first php setting: {version, mode}, second php setting: {version, mode}, ) """ options_path = '/usr/local/directadmin/custombuild/options.conf' try: config_parser, global_section = read_da_config(options_path) php1_ver = config_parser.get(global_section, 'php1_release') php2_ver = config_parser.get(global_section, 'php2_release') php1_handler = config_parser.get(global_section, 'php1_mode') php2_handler = config_parser.get(global_section, 'php2_mode') except configparser.NoOptionError: raise StatUtilsException('No option found: {0}'.format(''.join(traceback.format_exc().split('\n')))) return { 1: { 'version': php1_ver, 'handler': 'lsapi' if php1_handler == 'lsphp' else php1_handler }, 2: { 'version': php2_ver, 'handler': 'lsapi' if php2_handler == 'lsphp' else php2_handler } } def read_da_config(conf_file, append_section_name='dummy_section'): """ Read DA config file with ConfigParser. Need to add dummy section for success :param conf_file: config file name :param append_section_name: name of section to place in the beginning of file :return: RawConfigParser instance """ try: with open(conf_file) as f: file_content = StringIO('[{s}]\n'.format(s=append_section_name) + f.read()) config_parser = configparser.RawConfigParser(strict=False) config_parser.read_file(file_content) except (OSError, IOError): raise StatUtilsException(''.join(traceback.format_exc().split('\n'))) return config_parser, append_section_name def pretty_version_keys(php_ver, pre='php'): """ Convert simple php versions to pretty format :param php_ver: {major}.{minor} version :param pre: desired key start :return: alt-php{major}{minor} or desired `pre`{major}{minor} """ template = '{0}%s%s'.format(pre) try: return template % tuple(php_ver.split('.')) except Exception: return php_ver def dump_lsapi(ctl_path='/usr/sbin/httpd'): """ Get `httpd -t -D DUMP_RUN_LSAPI` info For httpd24 this default path is `/opt/rh/httpd24/root/usr/sbin/httpd`, generated in make_from_templates.sh script :param ctl_path: path to httpd (also apachectl may be used) :return: dict( lsapi_option: value ) """ apache_conf_data = exec_command.exec_command('{ctl} -t -D DUMP_RUN_LSAPI'.format(ctl=ctl_path)) try: return dict([l.lower().split(' ') for l in apache_conf_data]) except: return dict() def dump_loaded_modules(ctl_path='/usr/sbin/httpd'): """ Get `httpd -M` For httpd24 this default path is `/opt/rh/httpd24/root/usr/sbin/httpd`, generated in make_from_templates.sh script :param ctl_path: path to httpd (also apachectl may be used) :return: dict( apache_module: value ) """ apache_modules = exec_command.exec_command('{ctl} -M'.format(ctl=ctl_path)) try: return dict([l.lower().split(' ') for l in apache_modules]) except: return dict() def liblsapi_path(): """ Retrieve path to liblsapi, depends on arch :return: path to liblsapi """ is_64bits = sys.maxsize > 2**32 return '/usr/lib{a}/liblscapi.so'.format(a='64' if is_64bits else '') def rpm_query(pkg): """ Get version-release from rpm -q `pkg` :param pkg: package name to query :return: version-release """ try: ver, rel = ''.join(exec_command.exec_command('/bin/rpm -q ' + pkg + ' --qf %{v}-%{r}')).split('-') return '{ver}-{rel}'.format(ver=ver, rel=rel.split('.')[0]) except ValueError: return None def query_strings(fname, template): """ Filter strings by given template Also split string upon given template :param fname: path to file :param template: template to find in string :return: first template occurrence splitted by template """ try: return [l for l in strings(fname) if template in l][0].split(template)[1].strip() except (IndexError, IOError, OSError): return None def strings(fname, n=6): """ Strings utility analog. Finds printable strings in executable :param fname: path to file :param n: minimum string length :return: generator, yeilds string """ with open(fname, errors='ignore') as f: result = "" for c in f.read(): if c in string.printable: result += c continue if len(result) >= n: yield result result = "" if len(result) >= n: # catch result at EOF yield result def count_domains(handler_struct, default_keys, only_lsapi=True): """ Count domains :param handler_struct: handler: version: set_of_domains structure :param default_keys: sequence of keys to add as default if no `lsapi` found :param only_lsapi: return only lsapi statistics :return: statistics - number of lsapi domains per version if only_lsapi=True number of lsapi domains per version per handler otherwise """ result_stat = dict() for h, data in handler_struct.items(): result_stat[h] = dict((k, len(v)) for k, v in data.items()) # if there are no lsapi handler domains, return 0 per each installed version try: return result_stat['lsapi'] if only_lsapi else result_stat except KeyError: return dict.fromkeys([x for x in default_keys if x != 'no'], 0)