MMCT BYPASS SHELL
:
216.73.216.98
:
91.213.11.35 / forkliftsafetysystems.com
:
Linux mgh-web6.maghost.ro 4.18.0-553.54.1.lve.el8.x86_64 #1 SMP Wed Jun 4 13:01:13 UTC 2025 x86_64
:
/
sbin
/
UPLOAD FILE:
files >> //sbin/wp-toolkit-clone-awp-settings
#!/opt/cloudlinux/venv/bin/python3 # -*- coding: utf-8 -*- # Copyright © Cloud Linux GmbH & Cloud Linux Software, Inc 2010-2025 All Rights Reserved # # Licensed under CLOUD LINUX LICENSE AGREEMENT # http://cloudlinux.com/docs/LICENSE.TXT import argparse import json import logging import os import pwd import subprocess import sys from urllib.parse import urlparse from clwpos.logsetup import setup_logging from clwpos.optimization_features import Feature # Set up logger logger = setup_logging( caller_name='wp-toolkit-clone-awp-settings', console_level=logging.INFO, file_level=logging.DEBUG, logfile_path='/var/log/clwpos/wp-toolkit-clone.log' ) def get_wp_toolkit_instance_info(instance_id): """Get WP Toolkit instance information Returns JSON data from WP Toolkit API in the following format: { "id": 3, "siteUrl": "https://us17.com/wp1", "fullPath": "/var/www/vhosts/us17.com/httpdocs/wp1", "mainDomainId": 3, "path": "/httpdocs/wp1", "ownerId": 4, "name": "Exquisite Goods", "version": "6.8.1", "alive": true, "stateText": "Working", ... // other fields } Key fields used by this script: - id: WordPress instance ID (for validation) - siteUrl: Full URL of the WordPress site (used to extract domain and wp_path) - fullPath: Absolute filesystem path (used to determine site owner) Args: instance_id (str|int): WP Toolkit instance ID Returns: dict|None: Instance data on success, None on failure """ logger.debug(f"Getting WP Toolkit instance info for ID: {instance_id}") try: # Simple panel detection - check if Plesk binary exists if os.path.exists('/usr/sbin/plesk'): cmd = ['/usr/sbin/plesk', 'ext', 'wp-toolkit'] else: cmd = ['/usr/local/bin/wp-toolkit'] cmd.extend(['-info', '-instance-id', str(instance_id), '-format', 'json']) result = subprocess.run(cmd, capture_output=True, text=True, check=True) instance = json.loads(result.stdout) if isinstance(instance, dict) and 'id' in instance: if str(instance.get('id')) == str(instance_id): return instance else: logger.error(f"Instance ID mismatch: expected {instance_id}, got {instance.get('id')}") return None else: logger.error(f"Invalid instance data structure: {type(instance)}") return None except subprocess.CalledProcessError as e: logger.error(f"WP Toolkit command failed with return code {e.returncode}") logger.debug(f"Command stderr: {e.stderr}") return None except json.JSONDecodeError as e: logger.error(f"Failed to parse WP Toolkit JSON output: {e}") return None except Exception as e: logger.error(f"Unexpected error getting instance info: {e}") return None def extract_site_details(instance): """Extract domain and wp_path from WP Toolkit instance data""" if not instance or not isinstance(instance, dict): logger.error(f"Invalid instance data: {type(instance)}") return None, None try: site_url = instance.get('siteUrl', '') if not site_url: logger.error("Missing siteUrl in instance data") return None, None # Parse URL properly using standard library parsed = urlparse(site_url) domain = parsed.netloc # Get path and normalize it wp_path = parsed.path.strip('/') if not wp_path: wp_path = '/' return domain, wp_path except Exception as e: logger.error(f"Error extracting site details: {e}") return None, None def get_site_owner(instance): """Get site owner by examining filesystem ownership using fullPath from WP Toolkit""" full_path = instance.get('fullPath', '') domain = instance.get('siteUrl', '').replace('https://', '').replace('http://', '').split('/')[0] try: if not full_path or not os.path.exists(full_path): logger.error(f"Full path does not exist: {full_path}") return None stat_info = os.stat(full_path) owner_uid = stat_info.st_uid owner = pwd.getpwuid(owner_uid).pw_name return owner except Exception as e: logger.error(f"Error getting site owner: {e}") return None def get_awp_features(domain, wp_path, username): """Get AccelerateWP features for a site""" try: cmd = [ 'cloudlinux-awp-user', '--user', username, 'get', '--domain', domain, '--wp-path', wp_path ] result = subprocess.run(cmd, capture_output=True, text=True, check=True) features_data = json.loads(result.stdout) return features_data except subprocess.CalledProcessError as e: logger.error(f"cloudlinux-awp-user get failed: {e.stderr}") return None except json.JSONDecodeError as e: logger.error(f"Failed to parse AWP features JSON: {e}") return None except Exception as e: logger.error(f"Unexpected error getting AWP features: {e}") return None def copy_awp_features(source_features, source_domain, source_wp_path, target_domain, target_wp_path, target_username): """Copy AccelerateWP features from source to target""" if not source_features: logger.error("No source features data") return False if not isinstance(source_features, dict): logger.error(f"Source features is not a dict: {type(source_features)}") return False if 'docroots' not in source_features: logger.error("Missing 'docroots' key in source features data") return False # Normalize wp_path for comparison (both '/' and '' mean root WordPress) normalized_source_path = '' if source_wp_path == '/' else source_wp_path # Find the features for the specific WordPress site that is being cloned wp_features = None for i, docroot in enumerate(source_features.get('docroots', [])): # Check if this docroot contains our source domain docroot_domains = docroot.get('domains', []) logger.debug(f"Docroot {i}: domains={docroot_domains}") if source_domain not in docroot_domains: logger.debug(f"Skipping docroot {i} - does not contain domain {source_domain}") continue logger.debug(f"Docroot {i} contains source domain, checking WordPress sites...") wps = docroot.get('wps', []) logger.debug(f"Found {len(wps)} WordPress sites in this docroot") for j, wp_site in enumerate(wps): site_path = wp_site.get('path', '') # Normalize site_path for comparison (both '/' and '' mean root WordPress) normalized_site_path = '' if site_path == '/' else site_path logger.debug(f" WP site {j}: path='{site_path}' (normalized: '{normalized_site_path}') - comparing with '{normalized_source_path}'") # Check if this is exactly the WordPress site that is being cloned if normalized_site_path == normalized_source_path: wp_features = wp_site.get('features', {}) logger.debug(f"Found source site: {source_domain}:{source_wp_path}") logger.debug(f"Features available: {list(wp_features.keys()) if wp_features else 'None'}") break if wp_features is not None: break if wp_features is None: logger.error(f"Could not find source WordPress site: {source_domain}:{source_wp_path}") logger.error("Available sites in docroots:") for i, docroot in enumerate(source_features.get('docroots', [])): domains = docroot.get('domains', []) logger.error(f" Docroot {i}: domains={domains}") for j, wp_site in enumerate(docroot.get('wps', [])): path = wp_site.get('path', '') logger.error(f" WP site {j}: path='{path}'") return False if not wp_features: logger.info("No features configured on source site") return True features_to_copy = [] # Use centralized feature mapping from Feature class for feature_name, feature_data in wp_features.items(): if isinstance(feature_data, dict) and feature_data.get('enabled'): try: # Use centralized mapping from Feature class feature_obj = Feature(feature_name) cli_feature_name = feature_obj.to_interface_name() features_to_copy.append(cli_feature_name) except Exception as e: logger.warning(f"Unknown feature '{feature_name}': {e}") continue if not features_to_copy: logger.info("No features enabled on source site") return True logger.info(f"Copying features: {features_to_copy}") # Enable features on target success = True for feature in features_to_copy: try: cmd = [ 'cloudlinux-awp-user', '--user', target_username, 'enable', '--feature', feature, '--domain', target_domain, '--wp-path', target_wp_path, '--ignore-errors' ] result = subprocess.run(cmd, capture_output=True, text=True, check=True) logger.info(f"Enabled {feature}") except subprocess.CalledProcessError as e: logger.error(f"Failed to enable {feature}: {str(e)}") success = False except Exception as e: logger.error(f"Unexpected error enabling {feature}: {e}") success = False return success def main(): parser = argparse.ArgumentParser(description='Copy AccelerateWP settings from parent site to clone') parser.add_argument('--source-instance-id', required=True, help='Source WP Toolkit instance ID') parser.add_argument('--target-instance-id', required=True, help='Target WP Toolkit instance ID') parser.add_argument('--quiet', action='store_true', help='Suppress output messages') args, unknown = parser.parse_known_args() # Unknown arguments are normal in some contexts (e.g., WP Toolkit hook for cPanel) if unknown: logger.info(f"Unknown arguments: {unknown}") # Adjust logging level if quiet mode requested if args.quiet: logger.setLevel(logging.ERROR) for handler in logger.handlers: handler.setLevel(logging.ERROR) logger.info(f"Starting AWP copy: {args.source_instance_id} → {args.target_instance_id}") # Get source instance info source_instance = get_wp_toolkit_instance_info(args.source_instance_id) if not source_instance: logger.error("Failed to get source instance information") sys.exit(1) # Get target instance info target_instance = get_wp_toolkit_instance_info(args.target_instance_id) if not target_instance: logger.error("Failed to get target instance information") sys.exit(1) # Extract site details source_domain, source_wp_path = extract_site_details(source_instance) target_domain, target_wp_path = extract_site_details(target_instance) if not all([source_domain, target_domain]): logger.error("Failed to extract site details") sys.exit(1) # Get site owners source_username = get_site_owner(source_instance) target_username = get_site_owner(target_instance) if not all([source_username, target_username]): logger.error("Failed to determine site owners") sys.exit(1) logger.info(f"Source: {source_domain}:{source_wp_path} ({source_username})") logger.info(f"Target: {target_domain}:{target_wp_path} ({target_username})") # Get source AWP features source_features = get_awp_features(source_domain, source_wp_path, source_username) if not source_features: logger.error("Failed to get source AWP features") sys.exit(1) # Copy features to target if copy_awp_features(source_features, source_domain, source_wp_path, target_domain, target_wp_path, target_username): logger.info("AWP settings copied successfully") sys.exit(0) else: logger.error("Failed to copy AWP settings") sys.exit(1) if __name__ == '__main__': main()
SonySec07 | MukoMuko Cyber Team | Ver3.2