/
usr
/
lib
/
python2.7
/
site-packages
/
clcommon
/
cpapi
/
plugins
/
Upload Filee
HOME
#!/usr/bin/python # -*- coding: utf-8 -*- import glob import os import pwd import subprocess import sys from ConfigParser import ConfigParser, NoOptionError, NoSectionError __cpname__ = 'cPanel' DBMAPPING_SCRIPT = os.path.join(os.path.dirname(sys.executable), "cpanel-dbmapping") def detect(): return os.path.isfile('/usr/local/cpanel/cpanel') from clcommon.clconfpars import load as loadconfig #from .universal import _dblogin_cplogin_pairs from clcommon.cpapi.cpapiexceptions import NoDBAccessData, CpApiTypeError, NoDomain from clcommon import ClPwd CPANEL_DB_CONF = '/root/.my.cnf' CPANEL_USERPLANS_PATH = '/etc/userplans' CPANEL_DATABASES_PATH = '/var/cpanel/databases/' CPANEL_USERS_DIR = '/var/cpanel/users/' CPANEL_RESELLERS_PATH = '/var/cpanel/resellers' CPANEL_USERDATADOMAINS_PATH = '/etc/userdatadomains;/var/cpanel/userdata/{user}/cache' CPANEL_ACCT_CONF_PATH = '/etc/wwwacct.conf' SYSCONF_CLOUDLINUX_PATH = '/etc/sysconfig/cloudlinux' USERCONF_PARAM_MAP = { 'dns': 'dns', 'package': 'plan', 'reseller': 'owner', 'mail': 'contactemail', 'locale': 'locale', 'cplogin': 'user' } SUPPORTED_CPANEL_CPINFO = ('cplogin', 'package', 'mail', 'reseller', 'dns', 'locale') def db_access(_conf_path=CPANEL_DB_CONF): access = dict() reg_data_config = ConfigParser() opened_files = reg_data_config.read(_conf_path) if not opened_files: raise NoDBAccessData('Can not find database access data for localhost. No such file %s' % _conf_path) try: if reg_data_config.has_option(section='client', option='password'): access['pass'] = reg_data_config.get(section='client', option='password', raw=True).strip('\"') else: access['pass'] = reg_data_config.get(section='client', option='pass', raw=True).strip('\"') access['login'] = reg_data_config.get(section='client', option='user', raw=True) except (NoOptionError, NoSectionError), e: raise NoDBAccessData('Can not find database access data for localhost from config file %s; ' '%s' % (_conf_path, e.message)) access['db'] = 'mysql' return access def cpusers(_userplans_path=CPANEL_USERPLANS_PATH): stream = open(_userplans_path) users_list = [line.split(':')[0].strip() for line in stream if not line.startswith('#') and line.count(':') == 1 and len(line.strip()) > 3] stream.close() return tuple(users_list) def resellers(_resellers_path=CPANEL_RESELLERS_PATH): if not os.path.isfile(_resellers_path): # on a clean system, this file may not be return tuple() stream = open(_resellers_path) resellers_list = [line.split(':')[0].strip() for line in stream if not line.startswith('#') and (':' in line) and len(line.strip()) > 3] return tuple(resellers_list) def dblogin_cplogin_pairs(cplogin_lst=None, with_system_users=False): """ 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 """ # initialize results list results = [] # accept only list and tuple parameters uid_list = [] for username in (cplogin_lst or []): try: uid_list.append(str(pwd.getpwnam(username).pw_uid)) except KeyError: # no user exists - skip it uid_list.append("-1") # generate system command params = [DBMAPPING_SCRIPT] if not with_system_users: params.append("--nosys") params += uid_list output = subprocess.Popen(params, stdout=subprocess.PIPE, stderr=subprocess.PIPE).stdout.read() # output format: "DBuser user UID" for line in output.split("\n"): line = line.strip() if not line: continue results.append(line.split(" ")[:2]) return tuple(results) def cpinfo(cpuser=None, keyls=('cplogin', 'package', 'mail', 'reseller', 'dns', 'locale'), _cpanel_users_dir=CPANEL_USERS_DIR): returned = list() if isinstance(cpuser, (str, unicode)): cpusers_list = [cpuser] elif isinstance(cpuser, (list, tuple)): cpusers_list = tuple(cpuser) elif cpuser is None: cpusers_list = glob.glob(os.path.join(_cpanel_users_dir, '*')) else: raise CpApiTypeError(funcname='cpinfo', supportettypes='str|unicode|list|tuple', received_type=type(cpuser).__name__) for cpuser in cpusers_list: user_config_path = os.path.join(_cpanel_users_dir, cpuser) if not os.path.exists(user_config_path): print('WARNING: Can not load data to the user "%s"; Perhaps there is no such user in cPanel' % (cpuser,)) continue cpuser_data = loadconfig(user_config_path) user_data = [cpuser_data.get(USERCONF_PARAM_MAP.get(data_key)) for data_key in keyls] returned.append(tuple(user_data)) if 'mail' in keyls: # checking the presence of an additional e-mail additional_mail = cpuser_data.get('contactemail2') if additional_mail: user_data[list(keyls).index('mail')] = additional_mail user_data_tuple = tuple(user_data) if user_data_tuple not in returned: returned.append(tuple(user_data)) return tuple(returned) def get_admin_email(_conf1=None, _conf2=None, _hostname=None): """ :param str|None _conf1: for testing :param str|None _conf2: for testing :param str|None _hostname: for testing :return: """ # 1. Try to get admin email from /etc/sysconfig/cloudlinux lines = [] try: f = open(_conf1 or SYSCONF_CLOUDLINUX_PATH, 'r') lines = f.readlines() f.close() except (OSError, IOError): pass for line in lines: if line.startswith('EMAIL'): parts = line.split('=') if len(parts) == 2 and '@' in parts[1].strip(): return parts[1].strip() # 2. Try to get admin email from /etc/wwwacct.conf lines = [] try: f = open(_conf2 or CPANEL_ACCT_CONF_PATH, 'r') lines = f.readlines() f.close() except (OSError, IOError): pass host = '' for line in lines: if line.startswith('CONTACTEMAIL'): s = line.replace('CONTACTEMAIL', '').strip() if s: return s if line.startswith('HOST'): s = line.replace('HOST', '').strip() if s: host = s if host: return 'root@' + host # Admin email not found in system files, use common address from clcommon.cpapi.plugins.universal import get_admin_email return get_admin_email(_hostname=_hostname) def docroot(domain, _path=CPANEL_USERDATADOMAINS_PATH): domain = domain.strip() except_list = list() if '{user}' in _path: call_as_user = pwd.getpwuid(os.getuid()).pw_name _path = _path.replace('{user}', call_as_user) path_list = _path.split(';') for path_ in path_list: if not os.path.exists(path_): continue try: file_ = open(path_) except IOError, e: except_list.append(str(e)) continue # example line: #test.russianguns.ru: russianguns==root==sub==russianguns.ru==/home/russianguns/fla==192.168.122.40:80======0 for line in file_: if line.startswith(domain + ':'): domain_raw_data = line[len(domain) + 1:].strip() domain_data = domain_raw_data.split('==') docroot_path = domain_data[4] user = domain_data[0] file_.close() return docroot_path, user except_list.append('Can\'t find record "%s" in file "%s"' % (domain, path_)) file_.close() raise NoDomain("Can't obtain document root for domain '%s'; %s" % (domain, '; '.join(except_list))) def userdomains(cpuser, _path=CPANEL_USERDATADOMAINS_PATH): domains_order = [] result_list = [] domains_dict = {} def ordered_insert(key, value, position=None): if key in domains_dict: return elif position is not None: domains_order.insert(position, domain) else: domains_order.append(domain) domains_dict.update({key: value}) if '{user}' in _path: call_as_user = pwd.getpwuid(os.getuid()).pw_name _path = _path.replace('{user}', call_as_user) path_list = _path.split(';') for path_ in path_list: try: file_ = open(path_) except IOError: continue for line_numb, line in enumerate(file_): # example line: #test.russianguns.ru: russianguns==root==sub==russianguns.ru==/home/russianguns/fla==192.168.122.40:80======0 if not line.strip(): # ignore the empty string continue if line.count(': ') != 1: print 'Can\'t pars %s line in file "%s"; line was ignored' % (line_numb, path_) continue domain, domain_raw_data = line.split(': ') domain_data = domain_raw_data.strip().split('==') user_ = domain_data[0] if cpuser == user_: document_root = domain_data[4] main_domain = 'main' == domain_data[2] if main_domain: ordered_insert(domain, document_root, 0) # main domain must be first in list else: ordered_insert(domain, document_root) file_.close() for key in domains_order: result_list.append((key, domains_dict[key])) return result_list def homedirs(_sysusers=None, _conf_path = CPANEL_ACCT_CONF_PATH): """ Detects and returns list of folders contained the home dirs of users of the cPanel :param str|None _sysusers: for testing :param str|None _conf_path: for testing :return: list of folders, which are parent of home dirs of users of the panel """ HOMEDIR = 'HOMEDIR ' HOMEMATCH = 'HOMEMATCH ' homedirs = [] users_homedir = '' users_home_match = '' if (os.path.exists(_conf_path)): lines = open(_conf_path, 'r') for line in lines: if line.startswith(HOMEDIR): users_homedir = line.split(HOMEDIR)[1].strip() elif line.startswith(HOMEMATCH): users_home_match = line.split(HOMEMATCH)[1].strip() if users_homedir: homedirs.append(users_homedir) clpwd = ClPwd() users_dict = clpwd.get_user_dict() # for testing only if isinstance(_sysusers, (list, tuple)): class pw(object): def __init__(self, name, dir): self.pw_name = name self.pw_dir = dir users_dict = {} for (name,dir) in _sysusers: users_dict[name] = pw(name, dir) for user_name in users_dict: userdir = users_dict[user_name].pw_dir if os.path.exists(userdir + '/public_html') or os.path.exists(userdir + '/www'): homedir = os.path.dirname(userdir) if users_home_match and homedir.find('/'+users_home_match) == -1: continue if homedir not in homedirs: homedirs.append(homedir) return homedirs #TODO: You can extract the data from the database but it needs that will automatically install the package MySQL-python # cPanel repository in MySQL-python disabled #def dblogin_cplogin_pairs(cplogin_lst=None): # access = db_access() # data = _dblogin_cplogin_pairs(cplogin_lst=cplogin_lst, access=access) # return data