true, 'am_file' => $files['am_filename'], 'waf_file' => $files['waf_filename'], 'av_file' => $files['av_filename'], 'am_created_at' => $files['created_at'], ] ); self::generateMarkerFile(); $message = __( 'Agent manager have been successfully installed', 'wtotem'); WebTotemOption::setNotification( 'success', $message ); } else { $message = sprintf(__( 'Check %s folder\'s write permission.', 'wtotem' ), ABSPATH) . sprintf(__(' Read more here.', 'wtotem' ), 'https://docs.wtotem.com/agent-setup#it-additional-recommendations'); WebTotemOption::setNotification( 'error', $message ); return FALSE; } } // Update config_id. WebTotemAPI::getHostID($host['name']); } catch ( \Exception $e ) { WebTotemOption::setNotification( 'error', $e->getMessage() ); return FALSE; } return TRUE; } /** * Get the AM file download link and agents (AV, WAF) files name. * * @param string $host_id * Host id on WebTotem. * * @return array * Agent Manager download link, names of agents */ public static function getAgentsFiles( $host_id ) { $result = WebTotemAPI::getAgentsFiles( $host_id ); if ( ! $result ) { $file = [ 'download_link' => NULL ]; $message = __( 'Error generating the agent manager file.', 'wtotem' ); WebTotemOption::setNotification( 'error', $message ); } else { $file = $result; } return $file; } /** * Check the existence of the service file and the record in the DB. * * @param string $service * Service short name (am, av, waf). * * @return array * Service file data (installed status, file exist status, file name). */ public static function checkInstalledService( $service ) { $file = WebTotemOption::getOption( $service . "_file" ); return [ 'option_status' => WebTotemOption::getOption( $service . "_installed" ), 'file_status' => ( (bool) $file ) && is_file( ABSPATH . $file ), 'file_name' => $file, ]; } /** * Remove all agents files and folders. Clear agents options. * * @return bool * Returns TRUE if agent files * and folders have been successfully deleted. */ public static function removeAgents() { // Deleting all agent records from the database. WebTotemOption::clearOptions( [ 'am_installed', 'waf_installed', 'av_installed', 'am_file', 'waf_file', 'av_file', ] ); self::postdelete(); if($wp_filesystem = self::wpFileSystem()){ $list = $wp_filesystem->dirlist( ABSPATH ); $uploads_list = $wp_filesystem->dirlist( ABSPATH .'wp-content/uploads' ) ?: []; foreach ($uploads_list as $key => $item){ $uploads_list[$key]['name'] = 'wp-content/uploads/' . $item['name']; } $list = array_merge($list, $uploads_list); foreach ( $list as $item ) { $target_item = ABSPATH . $item['name']; // Check whether the item is a directory. $recursive = ( $item['type'] == 'd' ) ? true : false; $pattern = '/([a-zA-Z0-9_]{64}.av.php)|([a-zA-Z0-9_]{64}.am.php)|([a-zA-Z0-9_]{64}.waf.php)|(\.wtotem_[a-zA-Z0-9_]{12,16})/'; if ( preg_match( $pattern, $target_item ) ) { $wp_filesystem->delete( $target_item, $recursive, $item['type'] ); } } } return TRUE; } /** * This method clears the system file from the WAF connection strings. * * @return bool */ public static function postdelete(): bool { $base_path = ABSPATH; $targets = [ 'default' => $base_path . 'index.php', 'wp' => $base_path . 'wp-load.php', ]; foreach ($targets as $target_path) { self::cut_inc($target_path); } return true; } /** * This method clears the system file from the WAF connection strings. * * @return string */ private static function cut_inc(string $target_path) { if (file_exists($target_path)) { $reg = '/^([\r\n\t])*((<\?php\s)?if\s?\(function_exists\(\'current_user_can\'\)\)\s?{\s?if\s?\(\s?!current_user_can\(\'publish_posts\'\)\s?\)\s?{\s)?(<\?php\s?)?\$wtwaf\s?=\s?dirname\(__FILE__\).{76,77}\.waf\.php(\'|\")?;\s?if\s?\(file_exists\(\$wtwaf\)(\s&&\sis_readable\(\$wtwaf\))?\)\s?{(\s?if\s?\(function_exists\("is_admin"\)\)\s?{\s?if\s?\(!is_admin\(\)\)\s?{)?\s?@include_once\(\$wtwaf\);\s?}(\s?}\s?else\s?{\s?@include_once\(\$wtwaf\);\s?}\s?})?\s?unset\(\$wtwaf\);\s?(\?>|}\s})?([\r\n\t])*/im'; $reg2 = '/(\?>)?(\s*(<\?php)?\s+if\s?\(\s*PHP_VERSION_ID\s*>\s*70000\s*\)\s*{\s*\$wtwaf\s*=\s*__DIR__\s*\.\s*\'(\/\.\.\/\.\.)?\/_include_\w{64}\.waf\.php\'\s*;\s*if\s*\(\s*file_exists\s*\(\s*\$wtwaf\s*\)\s*\)\s*{\s*@\s*include_once\s*\(\s*\$wtwaf\s*\)\s*;\s*}\s*unset\s*\(\s*\$wtwaf\s*\)\s*;\s*}\s*(\?>)?\s*)(<\?php)?/im'; $target_content = file_get_contents($target_path); $pos_inc = stripos($target_content, '@include_once($wtwaf);'); if ($pos_inc !== false) { $cutted = preg_replace($reg, '', $target_content); if (is_string($cutted) && $cutted !== '') { if (preg_match($reg2, $cutted, $reg2_matches)) { if (!empty($reg2_matches[1]) && !empty($reg2_matches[5])) { $cutted = str_replace($reg2_matches[0], '', $cutted); } else { $cutted = str_replace($reg2_matches[2], '', $cutted); } } if (is_string($cutted) && $cutted !== '') { $wp_filesystem = self::wpFileSystem(); $res = $wp_filesystem->put_contents($target_path, $cutted, FS_CHMOD_FILE); } else { $res = 'preg_replace error 2'; } } else { $res = 'preg_replace error 1'; } } else { $res = 'inc not found'; } } else { $res = 'not found'; } return $res; } /** * Base WordPress Filesystem class which Filesystem implementations extend. * * @return object|bool * Instance of Filesystem class. */ private static function wpFileSystem() { global $wp_filesystem; if ( empty( $wp_filesystem ) ) { require_once( ABSPATH . 'wp-admin/includes/file.php' ); WP_Filesystem(); } if (empty($wp_filesystem)) { WebTotemOption::setNotification('error', _('WP FileSystem path error')); return FALSE; } return $wp_filesystem; } /** * @param $download_url * Link from where to download the file. * @param $path * Path where to save the file. * * @return bool * If the file is saved successfully, it returns true. */ private static function downloadFile($download_url, $path) { $args = [ 'timeout' => '30', 'sslverify' => FALSE, ]; // if(WebTotemOption::getOption('api_environment') == 'M'){ // $download_url = str_replace("wtotem.com", "wtotem.net", $download_url); // } $response = wp_remote_get($download_url, $args); $http_code = wp_remote_retrieve_response_code($response); if ($http_code < 200) { WebTotemOption::setNotification('error', __( 'Could not download file.', 'wtotem' )); return FALSE; } $response_body = wp_remote_retrieve_body($response); if($wp_filesystem = self::wpFileSystem()){ if(!empty($response_body)){ return $wp_filesystem->put_contents($path, $response_body, FS_CHMOD_FILE); } else { $message = __( 'API: Response body is empty.', 'wtotem' ); WebTotemOption::setNotification( 'error', $message ); } } return FALSE; } /** * Generate the file that indicates that a WAF connection is being used through the plugin. */ public static function generateMarkerFile() { if($am_filename = WebTotemOption::getOption('am_file')) { if ( $wp_filesystem = self::wpFileSystem() ) { $content = '' . $am_filename; $file_path = WEBTOTEM_PLUGIN_PATH . '/generate.php'; if ( ! file_exists($file_path) or $wp_filesystem->get_contents($file_path) != $content) { if ( ! $wp_filesystem->put_contents( $file_path, $content, FS_CHMOD_FILE ) ) { $message = sprintf( __( 'Check %s folder\'s write permission.', 'wtotem' ), WEBTOTEM_PLUGIN_PATH ) . sprintf( __( ' Read more here.', 'wtotem' ), 'https://docs.wtotem.com/agent-setup#it-additional-recommendations' ); WebTotemOption::setNotification( 'warning', $message ); } } } } } /** * WAF Include. */ public static function wafInclude(){ if(WebTotemOption::isActivated()){ $sapi = @php_sapi_name(); if( $sapi != "cli" ) { if ($waf = WebTotemOption::getOption("waf_file")) { $include_waf_file = ABSPATH . '_include_' . $waf; if (is_file($include_waf_file) && is_readable($include_waf_file)) { include_once $include_waf_file; } } } } } /** * Check if the plugin version has changed. */ public static function checkVersion(){ if(WebTotemOption::isActivated()){ // Get version of the plugin that was previously installed. $version = WebTotemOption::getOption('plugin_version'); if ($version == WEBTOTEM_VERSION) { return; } WebTotemOption::setOptions(['plugin_version' => WEBTOTEM_VERSION]); // Generate the file that indicates that a WAF connection is being used through the plugin. self::generateMarkerFile(); } } }