#!/usr/bin/python import sys import os import os.path as os_path import re import time import shutil import whm_util as util from pprint import pprint keyname = 'server1.adaptainc.com' #hostname = 'https://%s:2087' % (keyname, ) hostname = 'https://127.0.0.1:2087' htaccess = '.htaccess' phpTagRegex = '^(#\\s*requirephp(\\s+(\\d*))?)\\s*$' phpTagGroups = {'full': 0, 'php': 2} phpTag = '#requirephp' phpHandlerGeneric = '^AddHandler\\sapplication\\/x-httpd-php' phpVersions = { 'default': { 'match': '^AddHandler\\sapplication\\/x-httpd-php\\s', 'patch': 'AddHandler application/x-httpd-php .php', }, '4': { 'match': '^AddHandler\\sapplication\\/x-httpd-php4\\s', 'patch': 'AddHandler application/x-httpd-php4 .php', }, '5': { 'match': '^AddHandler\\sapplication\\/x-httpd-php5\\s', 'patch': 'AddHandler application/x-httpd-php5 .php', }, '54': { 'match': '^AddHandler\\sapplication\\/x-httpd-php54\\s', 'patch': 'AddHandler application/x-httpd-php54 .php', }, '52': { 'match': '^AddHandler\\sapplication\\/x-httpd-php52\\s', 'patch': 'AddHandler application/x-httpd-php52 .php', }, '53': { 'match': '^AddHandler\\sapplication\\/x-httpd-php53\\s', 'patch': 'AddHandler application/x-httpd-php53 .php', }, '56': { 'match': '^AddHandler\\sapplication\\/x-httpd-php56\\s', 'patch': 'AddHandler application/x-httpd-php56 .php', }, } addonDocRoots = [ '/home/lisa/public_html/abrakammg', '/home/tstfwd/public_preview/MSCA-CLONE/www', '/home/tstfwd/public_preview/infit-copy/www', '/home/tstfwd/public_preview/system', ] def getDocRoots(whm_conn): result = [] accounts = whm_conn('listaccts') users = [e['user'] for e in accounts['acct']] for u in users: domains = whm_conn('cpanel', user=u, cpanel_jsonapi_module='DomainLookup', cpanel_jsonapi_func='getdocroots') docroots = {} for e in domains['cpanelresult']['data']: docroots[e['docroot']] = 1 result += list(docroots.keys()) addons = [] for addon_docroot in addonDocRoots: for real_docroot in result: if real_docroot in addon_docroot: # eg '/home/lisa/public_html' in '/home/lisa/public_html/abrakammg' addons.append(addon_docroot) break result += addons return result def readFile(filename): result = None try: f = open(filename) try: result = [line.rstrip() for line in f] finally: f.close() except IOError: result = None return result def loadAllFiles(docroots): result = {} for docroot in docroots: filename = os_path.join(docroot, htaccess) result[filename] = readFile(filename) return result def findStrInList(what, where): result = (-1, None) found = False regex = re.compile(what) i = 0 for line in where: match = regex.search(line) found = match is not None if found: result = (i, match) break i += 1 return result def checkPhpTag(content): result, comment, index, php_tag, php_version = False, '', -1, '', '' index, tag_match = findStrInList(phpTagRegex, content) result = index >= 0 and tag_match is not None if not result: comment = '%s broken or not found' % phpTag if result: php_tag = tag_match.groups()[phpTagGroups['full']] php_version = tag_match.groups()[phpTagGroups['php']] if php_version is None: php_version = 'default' result = php_version in phpVersions if not result: comment = 'invalid php version - %s' % php_version return result, comment, index, php_tag, php_version def checkPhpHandler(content, php_tag, php_version, generic=False): result, comment, index = False, '', -1 if generic: match_string = phpHandlerGeneric else: match_string = phpVersions[php_version]['match'] index, handler_match = findStrInList(match_string, content) result = index >= 0 and handler_match is not None if not result: comment = 'AddHandler is missing or does not match "%s"' % php_tag return result, comment, index def checkFile(content): result, comment, _, php_tag, php_version = checkPhpTag(content) if result: result, comment, _ = checkPhpHandler(content, php_tag, php_version, generic=False) if result: comment = 'OK' return result, comment def patchFile(content): if content is None: return False, None, 'no content' result, new_content, comment = False, None, '' result, comment, php_tag_index, php_tag, php_version = checkPhpTag(content) if result: handler_result, _, __ = checkPhpHandler(content, php_tag, php_version, generic=False) if handler_result: new_content, comment = None, 'NO NEED TO PATCH' else: new_content = content[:] handler_result, _, handler_index = checkPhpHandler(content, php_tag, php_version, generic=True) new_line = phpVersions[php_version]['patch'] if handler_result: old_line = new_content[handler_index] new_content[handler_index] = new_line comment = 'PATCHED line %d: REPLACED "%s" -> "%s"' % (handler_index + 1, old_line, new_line) else: new_content.insert(php_tag_index + 1, new_line) # 2 = 1 (adding the line after the found one) + 1 (index is 0-based) comment = 'PATCHED line %d: ADDED "%s"' % (php_tag_index + 2, new_line) return result, new_content, comment def saveListToExistingFile(filename, content): ts = int(time.time()) backup_filename = '%s.php-patch.%d' % (filename, ts) stat = os.stat(filename) shutil.copy2(filename, backup_filename) os.chown(backup_filename, stat.st_uid, stat.st_gid) #print '\t\t\tSAVING to %s' % filename #for line in content: # print '\t\t\t\t%s' % line f = open(filename, 'w') try: for line in content: f.write('%s\n' % line) finally: f.close() os.chmod(filename, stat.st_mode) os.chown(filename, stat.st_uid, stat.st_gid) return True, backup_filename if __name__ == '__main__': fix_htaccess = len(sys.argv) > 1 and sys.argv[1] == 'fix' remote_key = util.loadKeyFromFile('./%s-key.txt' % (keyname, )) whm = util.WhmConnection(hostname, remote_key) doc_roots = getDocRoots(whm) all_files = loadAllFiles(doc_roots) for filename, content in sorted(all_files.items()): do_print = True output = '' if content is None: output = 'missing' elif isinstance(content, list): if fix_htaccess: result, new_content, output = patchFile(content) if result and new_content is not None: _, backup_file = saveListToExistingFile(filename, new_content) output += ' | backup file %s' % backup_file else: result, output = checkFile(content) do_print = not result else: output = 'UNEXPECTED' if do_print: print '%s - %s' % (filename, output)