EVOLUTION-MANAGER
Edit File: antivirus.php
<?php /** * Version 6.2 * Date: 15 Dec 2020 * * SiteGuarding.com Antivirus */ include("antivirus_config.php"); define('SCRIPT_VERSION', '6.2'); define('ANTIVIRUS_PLATFORM', 'any'); define('ANTIVIRUS_CMS', 'any'); define('SITEGUARDING_SERVER', 'http://www.siteguarding.com/ext/antivirus/index.php'); //define('DEBUG_FLAG', true); //define('DEBUG_FILELIST', false); //define('CALLBACK_PACK_FILE', false); // Init date_default_timezone_set('Europe/London'); ignore_user_abort(true); error_reporting( 0 ); ini_set('error_log',NULL); ini_set('log_errors',0); ini_set('max_execution_time',7200); set_time_limit ( 7200 ); ini_set('post_max_size', '256M'); ini_set('upload_max_filesize', '256M'); ini_set('memory_limit', '512M'); /** * EasyRequest */ class EasyRequest_AVP { const BOUNDARY_PLACEHOLDER = '##BOUNDARY##'; protected $options = array( 'handler' => null, 'method' => 'GET', 'url' => '', 'nobody' => false, 'follow_redirects' => 1, 'protocol_version' => '1.1', 'timeout' => 600, 'user_agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:38.0) Gecko/20100101 Firefox/38.0', 'auth' => null, 'proxy' => null, 'proxy_userpwd' => null, 'proxy_type' => 'http', 'headers' => array(), 'cookies' => array(), 'json' => false, 'body' => '', 'query' => array(), 'form_params' => array(), 'multipart' => array(), 'curl' => array(), ); public $request; public $response; protected $redirects = array( 'count' => 0, 'urls' => array(), 'cookies' => array(), 'requests' => array(), ); protected $debugInfo = array( 'time_start' => null, 'time_process' => null, 'handler' => null, 'errors' => array(), ); private $builder = array( 'headers' => array(), 'query' => array(), 'form_params' => array(), ); private function __construct() { } public function setOptions($key, $value = null) { if (is_array($key)) { foreach ($key as $k => $v) { $this->setOptions($k, $v); } } elseif (!array_key_exists($key, $this->options)) { throw new InvalidArgumentException(sprintf('Option "%s" is invalid.', $key)); } else { $this->options[$key] = $value; } return $this; } public function getOptions($key = null) { if ($key === null) { return $this->options; } elseif (!array_key_exists($key, $this->options)) { throw new InvalidArgumentException(sprintf('Option "%s" is invalid.', $key)); } return $this->options[$key]; } public static function create($url, $method = 'GET', $options = array()) { if (strpos($method, '://')) { $temp = $url; $url = $method; $method = $temp; } $object = new self; $params = array( 'form_params' => 'withFormParam', 'query' => 'withQuery' ); foreach ($params as $key => $setter) { if (isset($options[$key])) { $object->$setter($object->getParamsAsString($options[$key])); unset($options[$key]); } } if (!empty($options['headers'])) { foreach ($options['headers'] as $name => $values) { if (is_int($name)) { list($name, $value) = explode(':', $values, 2); $object->withHeader($name, $value); } else { $object->withHeader($name, $values); } } } if (!empty($options['cookies']) && is_string($options['cookies'])) { $object->withStringCookies($options['cookies']); unset($options['cookies']); } return $object->setOptions(array('method' => strtoupper($method), 'url' => $url) + $options); } public static function __callStatic($method, $arguments) { static $methods = array( 'OPTIONS' => 1, 'GET' => 1, 'HEAD' => 1, 'POST' => 1, 'PUT' => 1, 'DELETE' => 1, 'TRACE' => 1, 'CONNECT' => 1 ); if (!empty($methods[strtoupper($method)])) { return self::create($method, $arguments[0], isset($arguments[1]) ? $arguments[1] : array())->send(); } throw new Exception(sprintf('Method "%s" is not defined.', $method)); } public function send() { list($options, $request) = $this->prepareRequest(); if (empty($request['uri'])) { throw new Exception('Request URI cannot be empty.'); } $this->options = $options; $this->request = $request; $this->response = null; $handler = $this->getHandler(); $sendMethod = sprintf('sendWith%s', ucfirst($handler)); $this->debugInfo['handler'] = $handler; $this->debugInfo['time_start'] = microtime(true); $info = $this->$sendMethod($this->request); $this->debugInfo['time_process'] = microtime(true) - $this->debugInfo['time_start']; if ($info !== false) { $this->response = array( 'header' => $info[0], 'body' => $info[1] ); $this->followRedirects(); } return $this; } protected function followRedirects() { $client = clone $this; while (($this->options['follow_redirects'] === true || $this->options['follow_redirects'] > $this->redirects['count']) && $nextUrl = $client->getResponseHeaderLine('Location') ) { $nextUrl = $this->getAbsoluteUrl($nextUrl, $client->options['url']); if ($this->redirects['count'] === 0) { $this->redirects['urls'][] = $client->options['url']; $this->redirects['requests'][] = $client; $this->redirects['cookies'] = array_values($client->options['cookies']); $this->collectResponseCookies($this->redirects['cookies'], $client->getResponseArrayCookies()); } $reuseOptions = array( 'nobody', 'protocol_version', 'timeout', 'user_agent', 'auth', 'headers', 'proxy', 'proxy_userpwd', 'proxy_type', 'query' ); $options = array('cookies' => $this->redirects['cookies']); foreach ($reuseOptions as $key) { $options[$key] = $this->options[$key]; } $client = self::create('GET', $nextUrl, $options)->send(); $this->request = $client->request; $this->response = $client->response; $this->redirects['count']++; $this->redirects['urls'][] = $client->options['url']; $this->redirects['requests'][] = $client; $this->collectResponseCookies($this->redirects['cookies'], $client->getResponseArrayCookies()); } } private function collectResponseCookies(&$collection, $cookies) { if (!$cookies) { return; } foreach ($collection as $oldKey => $oldValue) { foreach ($cookies as $newKey => $newValue) { if ($oldValue['Name'] === $newValue['Name'] && $oldValue['Path'] === $newValue['Path'] && $oldValue['Domain'] === $newValue['Domain'] && $oldValue['Secure'] === $newValue['Secure'] && $oldValue['HttpOnly'] === $newValue['HttpOnly'] ) { $collection[$oldKey] = $newValue; unset($cookies[$newKey]); } } } $collection = array_merge($collection, $cookies); } public function getCurrentUrl() { return $this->getRedirectedCount() ? end($this->redirects['urls']) : $this->options['url']; } public function getAllResponseCookies() { return $this->getRedirectedCount() ? $this->getRedirectedCookies() : $this->getResponseArrayCookies(); } public function getRedirectedCount() { return $this->redirects['count']; } public function getRedirectedUrls() { return $this->redirects['urls']; } public function getRedirectedCookies() { return $this->redirects['cookies']; } public function getRedirectedRequests() { return $this->redirects['requests']; } public function getDebugInfo($key = null) { if ($key !== null) { return $this->debugInfo[$key]; } return $this->debugInfo; } public function getRequest($key = null) { if ($key !== null) { return $this->request[$key]; } return $this->request; } public function getResponse($key = null) { if ($key !== null) { return $this->response[$key]; } return $this->response; } public function __toString() { return !$this->response ? '' : $this->getResponseBody(); } public function getResponseBody() { return !$this->response ? false : $this->response['body']; } public function getResponseHeaders() { return !$this->response ? false : $this->getHeadersAsLines($this->response['header']['headers']); } public function getResponseHeader($name) { return !$this->response ? false : $this->getHeaderAsLines($this->response['header']['headers'], $name); } public function getResponseHeaderLine($line) { return !$this->response ? false : $this->getHeaderLine($this->response['header']['headers'], $line); } public function getResponseArrayCookies() { if (!$this->response) { return false; } $cookies = array(); $cookieLines = $this->getHeaderAsLines($this->response['header']['headers'], 'Set-Cookie'); foreach ($cookieLines as $cookie) { $cookies[] = $this->parseStringCookie($cookie); } return $cookies; } public function getResponseCookies() { if (!$this->response) { return false; } $cookies = ''; $cookieLines = $this->getHeaderAsLines($this->response['header']['headers'], 'Set-Cookie'); foreach ($cookieLines as $cookie) { $cookies .= $this->getCookieAsString($this->parseStringCookie($cookie), false); } return trim($cookies); } public function getResponseStatus() { return !$this->response ? false : $this->response['header']['status']; } public function getResponseReason() { return !$this->response ? false : $this->response['header']['reason']; } public function getResponseProtocolVersion() { return !$this->response ? false : $this->response['header']['protocol_version']; } protected function sendWithSocket(array $request) { static $ports = array( 'https' => 443, 'http' => 80, '' => 80); static $errorHandler = null; $uri = $request['uriInfo']; $host = ($uri['scheme'] == 'https' ? 'ssl://' : '').$uri['host']; $port = $uri['port'] ? $uri['port'] : $ports[$uri['scheme']]; $path = $uri['path'].($uri['query'] ? '?'.$uri['query'] : ''); $headers = $request['headers']; if ($this->options['proxy']) { list($host, $port) = explode(':', $this->options['proxy']); $path = $request['uri']; if ($this->options['proxy_userpwd']) { $headers[] = 'Proxy-Authorization: Basic '.base64_encode($this->options['proxy_userpwd']); } } $headers[] = 'Connection: close'; $message = sprintf("%s %s HTTP/%s\r\n", $request['method'], $path, $request['protocol_version']); $message .= sprintf("Host: %s\r\n", $uri['host']); $message .= implode("\r\n", $headers)."\r\n"; $message .= "\r\n"; $message .= $request['body']; $message .= "\r\n\r\n"; $errorHandler === null && $errorHandler = create_function('', ''); $handler = set_error_handler($errorHandler); $stream = fsockopen($host, $port, $errno, $errstr, $this->options['timeout']); $handler ? set_error_handler($handler) : restore_error_handler(); if (!$stream) { if ($errstr) { $this->debugInfo['errors'][] = sprintf('ERROR: %d - %s.', $errno, $errstr); } else { $this->debugInfo['errors'][] = sprintf('ERROR: Cannot connect to "%s:%s"', $host, $port); } return false; } fwrite($stream, $message); $headers = $body = ''; do { $headers .= fgets($stream, 128); } while (strpos($headers, "\r\n\r\n") === false); $headers = $this->parseResponseHeaders($headers); if (!$this->options['nobody']) { while (!feof($stream)) { $body .= fgets($stream); } fclose($stream); if ($this->getHeaderLine($headers['headers'], 'Transfer-Encoding') == 'chunked') { $len = strlen($body); $outData = ''; $pos = 0; while ($pos < $len) { $rawnum = substr($body, $pos, strpos(substr($body, $pos), "\r\n") + 2); $num = hexdec(trim($rawnum)); $pos += strlen($rawnum); $chunk = substr($body, $pos, $num); $outData .= $chunk; $pos += strlen($chunk); } $body = $outData; } } return array($headers, $body); } protected function sendWithCurl(array $request) { $curlOptions = array( CURLOPT_CUSTOMREQUEST => $request['method'], CURLOPT_URL => $request['uri'], CURLOPT_HEADER => true, CURLOPT_RETURNTRANSFER => true, CURLOPT_SSL_VERIFYPEER => false, CURLOPT_ENCODING => 'gzip, deflate', CURLOPT_NOBODY => $this->options['nobody'], CURLOPT_TIMEOUT => $this->options['timeout'], CURLOPT_HTTPHEADER => $request['headers'], ); if ($request['protocol_version'] == '1.0') { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_0; } else { $curlOptions[CURLOPT_HTTP_VERSION] = CURL_HTTP_VERSION_1_1; } if ($body = $request['body']) { $curlOptions[CURLOPT_POSTFIELDS] = $body; } if ($this->options['proxy']) { $curlOptions[CURLOPT_PROXY] = $this->options['proxy']; static $proxyTypeOptions = array( 'http' => CURLPROXY_HTTP, 'sock5' => CURLPROXY_SOCKS5 ); $curlOptions[CURLOPT_PROXYTYPE] = $proxyTypeOptions[$this->options['proxy_type']]; if ($this->options['proxy_userpwd']) { $curlOptions[CURLOPT_PROXYUSERPWD] = $this->options['proxy_userpwd']; } } $curlOptions += $this->options['curl']; $ch = curl_init(); curl_setopt_array($ch, $curlOptions); $response = curl_exec($ch); if ($response === false) { $this->debugInfo['errors'][] = sprintf('ERROR: %d - %s.', curl_errno($ch), curl_error($ch)); return false; } $headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE); curl_close($ch); $headers = (string) substr($response, 0, $headerSize); $body = (string) substr($response, $headerSize); $headers = $this->parseResponseHeaders($headers); return array($headers, $body); } protected function parseResponseHeaders($headers) { $lines = array_filter(explode("\r\n", $headers)); preg_match('#^HTTP/([\d\.]+)\s(\d+)\s(.*?)$#i', array_shift($lines), $match); $out = array( 'protocol_version' => $match[1], 'status' => (int) $match[2], 'reason' => $match[3], 'headers' => array(), ); $this->addHeaderToArray($out['headers'], $lines, null); return $out; } public function prepareRequest() { $clone = clone $this; $uri = $clone->parseUri($clone->options['url']); if ($clone->options['query']) { $uri['query'] = trim($uri['query'].'&'.$clone->getParamsAsString($clone->options['query']), '&'); } $request = array( 'protocol_version' => $clone->options['protocol_version'], 'method' => strtoupper($clone->options['method']), 'uri' => $clone->getUriAsString($uri), 'uriInfo' => $uri, ); $clone->options['url'] = $request['uri']; if ($clone->options['json']) { !$clone->hasHeader('Content-Type') && $clone->withHeader('Content-Type', 'application/json'); $clone->options['body'] = $clone->options['json']; } $body = $params = $boundary = ''; if ($clone->options['form_params']) { $params = $clone->getParamsAsString($clone->options['form_params']); } if ($clone->options['multipart']) { $boundary = uniqid(); !$clone->hasHeader('Content-Type') && $clone->withHeader('Content-Type', 'multipart/form-data; boundary='.$boundary); if (preg_match_all('#([^=&]+)=([^&]*)#i', $params, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { $clone->withMultipart(urldecode($match[1]), urldecode($match[2])); } } $body .= $clone->getMultipartAsString($boundary, $clone->options['multipart']); } elseif ($params) { !$clone->hasHeader('Content-Type') && $clone->withHeader('Content-Type', 'application/x-www-form-urlencoded'); $body .= $params; } if ($clone->options['body']) { $body .= $clone->getBodyAsString($clone->options['body']); } if ($body) { if ($request['method'] == 'GET' || $request['method'] == 'HEAD') { $request['method'] = 'POST'; } } $clone->options['auth'] && $clone->withHeader('Authorization', 'Basic '.base64_encode($clone->options['auth'])); $cookies = ''; if ($clone->hasHeader('Cookie')) { foreach ($clone->getHeaderAsLines($clone->builder['headers'], 'Cookie') as $value) { $clone->withStringCookies($value); } } foreach ($clone->options['cookies'] as $cookie) { if ($clone->isCookieMatchesDomain($cookie, $uri['host']) && $clone->isCookieMatchesPath($cookie, $uri['path']) ) { $cookies .= $clone->getCookieAsString($cookie, false); } } $cookies && $clone->withHeader('Cookie', trim($cookies), false); $body && $clone->withHeader('Content-Length', strlen($body), false); $clone->withHeader('User-Agent', $clone->options['user_agent'], false); !$clone->hasHeader('Expect') && $body && $clone->withHeader('Expect', ''); $headers = $clone->getHeadersAsLines($clone->builder['headers']); if ($boundary) { foreach ($headers as &$line) { $line = strtr($line, array(self::BOUNDARY_PLACEHOLDER => $boundary)); } $body = strtr($body, array(self::BOUNDARY_PLACEHOLDER => $boundary)); } $request += array( 'headers' => $headers, 'body' => $body ); return array($clone->options, $request); } public function withMethod($method) { return $this->setOptions('method', $method); } public function withUserAgent($userAgent) { return $this->setOptions('user_agent', $userAgent); } public function withAuth($auth) { if ($auth === null || preg_match('#[\w-_]+(?::[\w-_]+)?#', $auth)) { return $this->setOptions('auth', $auth); } throw new InvalidArgumentException('Auth must be one of: string with format "user:pass" or "null".'); } public function withProxy($proxy, $userPwd = null, $type = 'http') { if ($proxy === null || preg_match('#^\d+\.\d+\.\d+\.\d+:\d+$#', $proxy)) { return $this ->setOptions('proxy', $proxy) ->setOptions('proxy_userpwd', $userPwd) ->setOptions('proxy_type', $type); } throw new InvalidArgumentException('Proxy must be one of: string with format "ip:port" or "null".'); } public function withHttpProxy($proxy, $userPwd = null) { return $this->withProxy($proxy, $userPwd, 'http'); } public function withSock5Proxy($proxy, $userPwd = null) { return $this->withProxy($proxy, $userPwd, 'sock5'); } public function withBody($body) { $this->options['json'] = false; return $this->setOptions('body', $body); } public function withJson($json) { if (is_string($json)) { $json = json_decode($json, true); if ($json === null) { throw new InvalidArgumentException('Json value must be an array or json string.'); } } $this->options['body'] = $this->options['json'] = json_encode($json); return $this; } public function withNobody($nobody) { return $this->setOptions('nobody', (bool) $nobody); } public function withFollowRedirects($maxRedirect) { if ($maxRedirect === true || is_numeric($maxRedirect) && 0 <= $maxRedirect = intval($maxRedirect)) { return $this->setOptions('follow_redirects', $maxRedirect); } throw new InvalidArgumentException('Max redirect must be a digit number or "true".'); } public function withTimeout($timeout) { if (is_numeric($timeout) && 0 <= $timeout = intval($timeout)) { $this->setOptions('timeout', (int) $timeout); return $this; } throw new InvalidArgumentException('Timeout must be be a digit number.'); } public function withProtocolVersion($version) { static $validProtocolVersions = array( '1.0' => true, '1.1' => true, '2.0' => true, ); if (empty($validProtocolVersions[$version])) { throw new Exception('Protocol version given is invalid.'); } return $this->setOptions('protocol_version', $version); } public function withHeader($name, $values = null, $append = true) { $this->addHeaderToArray($this->builder['headers'], $name, $values, $append); return $this->setOptions('headers', $this->getHeadersAsLines($this->builder['headers'])); } public function withoutHeader($name) { $this->removeHeaderFromArray($this->builder['headers'], $name); return $this; } public function hasHeader($name) { return $this->headerHasKey($this->builder['headers'], $name); } public function withStringCookies($cookies, $path = '/', $secure = false, $httpOnly = false) { $append = array( 'Path' => $path, 'Secure' => $secure, 'HttpOnly' => $httpOnly ); foreach ($this->parseStringCookies($cookies) as $c) { $this->options['cookies'][$c['Name']] = $c + $append; } return $this; } public function withCookie($name, $value = null, $path = '/', $secure = false, $httpOnly = false) { $append = array( 'Path' => $path, 'Secure' => $secure, 'HttpOnly' => $httpOnly ); if (is_array($name)) { if ($this->isCookieData($name)) { $this->options['cookies'][$name] = $name + $append; } else { foreach ($name as $k => $v) { $this->withCookie($k, $v); } } } elseif (is_string($name) && $value === null) { $c = $this->parseStringCookie($name); $this->options['cookies'][$c['Name']] = $c; } elseif (is_array($value) && $this->isCookieData($value)) { $this->options['cookies'][$value['Name']] = $value + $append; } else { $this->options['cookies'][$name] = array('Name' => $name, 'Value' => $value) + $append; } return $this; } public function withoutCookie($name) { unset($this->options['cookies'][$name]); return $this; } public function withFormFile($name, $filePath, $filename = null, $headers = array()) { $headers = array('Content-Transfer-Encoding' => 'binary') + $headers; if ($type = $this->getFileType($filePath)) { $headers['Content-Type'] = $type; } return $this->withMultipart($name, fopen($filePath, 'r'), $filename ? $filename : basename($filePath), $headers); } public function withMultipart($name, $contents, $filename = null, $headers = array()) { $this->options['multipart'][$name] = array( 'name' => $name, 'contents' => $contents, 'filename' => $filename, 'headers' => $headers ); return $this; } public function withoutMultipart($name) { unset($this->options['multipart'][$name]); return $this; } public function withQuery($name, $value = null, $append = true) { $this->addParamToArray($this->builder['query'], $name, $value, $append); $options = $this->getParamsAsArray($this->builder['query']); return $this->setOptions('query', $options); } public function withoutQuery($name) { $this->removeParamFromArray($this->builder['query'], $name); $options = $this->getParamsAsArray($this->builder['query']); return $this->setOptions('query', $options); } public function withFormParam($name, $value = null, $append = true) { $this->addParamToArray($this->builder['form_params'], $name, $value, $append); $options = $this->getParamsAsArray($this->builder['form_params']); return $this->setOptions('form_params', $options); } public function withoutFormParam($name) { $this->removeParamFromArray($this->builder['form_params'], $name); $options = $this->getParamsAsArray($this->builder['form_params']); return $this->setOptions('form_params', $options); } protected function addParamToArray(&$builder, $name, $value = null, $append = true) { if ($value !== null) { if (!$append || !isset($builder[$name])) { $builder[$name] = array(); } $builder[$name] = array_merge($builder[$name], (array) $value); } else { if (is_array($name)) { foreach ($name as $key => $value) { if (!is_int($key)) { $this->addParamToArray($builder, $key, $value, $append); } else { $this->addParamToArray($builder, $value, null, $append); } } } elseif (is_string($name)) { $name = str_replace('+', '%2B', preg_replace_callback( '#&[a-z]+;#', create_function('$match', 'return rawurlencode($match[0]);'), $name)); $this->addParamToArray($builder, $this->parseStringParams($name), null, $append); } } } protected function removeParamFromArray(&$builder, $name) { unset($builder[$name]); } protected function addHeaderToArray(&$builder, $name, $values, $append = true) { if (is_array($name)) { foreach ($name as $key => $value) { if (is_int($key)) { list($key, $value) = array_map('trim', explode(':', $value, 2)); } $this->addHeaderToArray($builder, $key, $value, $append); } return; } $normalizedKey = $this->normalizeHeaderKey($name); if (!$append || !isset($builder[$normalizedKey])) { $builder[$normalizedKey] = array(); } foreach ((array) $values as $value) { if (!is_string($value) && !is_numeric($value)) { throw new InvalidArgumentException('Header value must be a string or array of string.'); } $builder[$normalizedKey][] = array( 'key' => $name, 'value' => trim($value) ); } } protected function removeHeaderFromArray(&$builder, $name) { unset($builder[$this->normalizeHeaderKey($name)]); } protected function headerHasKey($builder, $name) { return array_key_exists($this->normalizeHeaderKey($name), $builder); } protected function getHeadersAsLines(array $builder) { $out = array(); foreach ($builder as $values) { foreach ($values as $value) { $out[] = sprintf('%s: %s', $value['key'], $value['value']); } } return $out; } protected function getHeaderAsLines(array $builder, $name) { $normallizedKey = $this->normalizeHeaderKey($name); $out = array(); if (isset($builder[$normallizedKey])) { foreach ($builder[$normallizedKey] as $value) { $out[] = $value['value']; } } return $out; } protected function normalizeHeaderKey($key) { return strtr(strtolower($key), '_', '-'); } protected function getHeaderLine($builder, $name) { $normallizedKey = $this->normalizeHeaderKey($name); $out = ''; if (isset($builder[$normallizedKey])) { foreach ($builder[$normallizedKey] as $value) { $out .= ($out ? ',' : '').$value['value']; } } return $out; } protected function getParamsAsArray(array $dataBuilder) { $params = array(); foreach ($dataBuilder as $key => $param) { if (count($param) == 1) { $params[$key] = $param[0]; } else { $params[$key] = $param; } } return $params; } protected function getParamsAsString(array $params) { if (PHP_VERSION_ID >= 50400) { return http_build_query($params, null, '&', PHP_QUERY_RFC3986); } else { return preg_replace_callback('#([^=&]+)=([^&]*)#i', create_function('$match', 'return $match[1]."=".rawurlencode(urldecode($match[2]));' ), http_build_query($params)); } } protected function parseStringParams($queryString, &$array = array()) { if (empty($queryString)) { return array(); } $array = array(); foreach (explode('&', $queryString) as $query) { list($key, $value) = explode('=', $query, 2) + array('', ''); $key = urldecode($key); if (preg_match_all('#\[([^\]]+)?\]#i', $key, $matches)) { $key = str_replace($matches[0], '', $key); if (!isset($array[$key])) { $array[$key] = array(); } $children = & $array[$key]; $deth = array(); foreach ($matches[1] as $sub) { $sub = $sub !== '' ? $sub : count($children); if (!array_key_exists($sub, $children)) { $children[$sub] = array(); } $children = & $children[$sub]; } $children = urldecode($value); } else { $array[$key] = urldecode($value); } } return $array; } protected function getCookieDefaults() { static $defauls = array( 'Name' => null, 'Value' => null, 'Domain' => null, 'Path' => '/', 'Max-Age' => null, 'Expires' => null, 'Secure' => false, 'Discard' => false, 'HttpOnly' => false ); return $defauls; } public function parseStringCookies($values) { $array = array(); if (preg_match_all('#(?:^|;)\s*([^=]+)=([^;]+)\s*?#', $values, $matches, PREG_SET_ORDER)) { foreach ($matches as $match) { list(, $name, $value) = $match; if ( !strcasecmp($name, 'Expires') && strtotime($value) || !strcasecmp($name, 'Path') && urldecode($value) == $value || preg_match('#Domain|Max-Age|Secure|Discard|HttpOnly#i', $value) ) { continue; } $array[] = array('Name' => $name, 'Value' => $value) + $this->getCookieDefaults(); } } return $array; } protected function parseStringCookie($value) { $data = $this->getCookieDefaults(); if (is_string($value) && preg_match_all('#([^=;\s]+)(?:=([^;]+))?;?\s*?#', $value, $matches)) { $data['Name'] = array_shift($matches[1]); $data['Value'] = array_shift($matches[2]); if ($matches[1] && $matches[2]) { foreach ($this->getCookieDefaults() as $key => $value) { foreach ($matches[1] as $index => $val) { if (!strcasecmp($key, $val)) { if (in_array($key, array('Secure', 'Discard', 'HttpOnly'))) { $data[$key] = true; } else { $data[$key] = $matches[2][$index]; } } } } } } return $data; } protected function isCookieData(array $data) { return !empty($data['Name']) && isset($data['Value']); } protected function isCookieMatchesPath(array $cookie, $path) { return empty($cookie['Path']) || strpos($path, $cookie['Path']) === 0; } protected function isCookieMatchesDomain(array $cookie, $domain) { $cookieDomain = isset($cookie['Domain']) ? ltrim($cookie['Domain'], '.') : null; if (!$cookieDomain || !strcasecmp($domain, $cookieDomain)) { return true; } if (filter_var($domain, FILTER_VALIDATE_IP)) { return false; } return (bool) preg_match('/\.'.preg_quote($cookieDomain).'$/i', $domain); } protected function getCookieAsString(array $cookie, $fully = false) { $str = $cookie['Name'].'='.$cookie['Value'].'; '; if (!$fully) { return $str; } $cookie += $this->getCookieDefaults(); foreach ($cookie as $key => $value) { if ($key != 'Name' && $key != 'Value' && $value !== null && $value !== false) { if ($key == 'Expires') { $str .= 'Expires='.gmdate('D, d M Y H:i:s \G\M\T', $value).'; '; } else { $str .= ($value === true ? $key : "{$key}={$value}").'; '; } } } return rtrim($str, '; '); } protected function getMultipartHeaders($boundary, array $headers) { $header = ''; foreach ($headers as $name => $value) { $header .= sprintf("%s: %s\r\n", $name, $value); } return "--{$boundary}\r\n".$header."\r\n"; } protected function getMultipartAsString($boundary, $parts) { $out = ''; foreach ($parts as $field) { $field += array('filename' => null, 'headers' => array()); $headers = $field['headers']; $headers['Content-Disposition'] = 'form-data; name="'.$field['name'].'"' .($field['filename'] ? '; filename="'.$field['filename'].'"' : ''); $out .= $this->getMultipartHeaders($boundary, $headers); $out .= $this->getBodyAsString($field['contents']); $out .= "\r\n"; } $out .= "--{$boundary}--\r\n"; return $out; } protected function getBodyAsString($body, $close = true) { $out = ''; if (is_resource($body)) { $out = stream_get_contents($body); $close && fclose($body); } else { $out = $body; } return $out; } protected function getFileType($filePath) { $filename = realpath($filePath); $extension = strtolower(pathinfo($filename, PATHINFO_EXTENSION)); if (preg_match('/^(?:jpe?g|png|[gt]if|bmp|swf)$/', $extension)) { $file = getimagesize($filename); if (isset($file['mime'])) { return $file['mime']; } } if (class_exists('finfo', false)) { if ($info = new finfo(defined('FILEINFO_MIME_TYPE') ? FILEINFO_MIME_TYPE : FILEINFO_MIME)) { return $info->file($filename); } } if (ini_get('mime_magic.magicfile') && function_exists('mime_content_type')) { return mime_content_type($filename); } } protected function getAbsoluteUrl($relative, $base) { $base = preg_replace('#(\?|\#).*?$#', '', $base); if (parse_url($relative, PHP_URL_SCHEME) != '') { return $relative; } if ($relative[0] == '#' || $relative[0] == '?') { return $base.$relative; } extract(parse_url($base)); $path = preg_replace('#/[^/]*$#', '', $path); $relative[0] == '/' && $path = ''; $absolute = $host.$path.'/'.$relative; $patterns = array('#(/\.?/)#', '#/(?!\.\.)[^/]+/\.\./#'); for ($count = 1; $count > 0; $absolute = preg_replace($patterns, '/', $absolute, -1, $count)); return $scheme.'://'.$absolute; } protected function parseUri($uri) { $parts = parse_url($uri); $scheme = isset($parts['scheme']) ? $parts['scheme'] : ''; $user = isset($parts['user']) ? $parts['user'] : ''; $pass = isset($parts['pass']) ? $parts['pass'] : ''; $host = isset($parts['host']) ? $parts['host'] : ''; $port = isset($parts['port']) ? $parts['port'] : null; $path = isset($parts['path']) ? $parts['path'] : '/'; $query = isset($parts['query']) ? $parts['query'] : ''; $fragment = isset($parts['fragment']) ? $parts['fragment'] : ''; return compact('scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment'); } protected function getUriAsString(array $uri) { extract($uri); $userInfo = $user.($pass ? ':'.$pass : ''); $authority = ($userInfo ? $userInfo.'@' : '').$host.($port !== null ? ':'.$port : ''); if ($authority && substr($path, 0, 1) === '/') { $path = '/'.ltrim($path, '/'); } if (!$authority && substr($path, 0, 2) === '//') { $path = '/'.ltrim($path, '/'); } return ($scheme ? $scheme.':' : '') .($authority ? '//'.$authority : '') .$path .($query ? '?'.$query : '') .($fragment ? '#'.$fragment : ''); } protected function getHandler() { static $available; if ($available === null) { $available = array( 'socket' => function_exists('fsockopen') && function_exists('ini_get') && ini_get('allow_url_fopen'), 'curl' => function_exists('curl_init'), ); } if ($this->options['handler'] !== null) { if (empty($available[$this->options['handler']])) { throw new Exception(sprintf('Handler "%s" is not available.')); } return $this->options['handler']; } if ($available['curl']) { return 'curl'; } if ($available['socket'] && $this->options['proxy_type'] != 'sock5') { return 'socket'; } throw new Exception('Have no available handler based on your request options/ PHP config.'); } } /** * HTML parser */ define('HDOM_TYPE_ELEMENT', 1); define('HDOM_TYPE_COMMENT', 2); define('HDOM_TYPE_TEXT', 3); define('HDOM_TYPE_ENDTAG', 4); define('HDOM_TYPE_ROOT', 5); define('HDOM_TYPE_UNKNOWN', 6); define('HDOM_QUOTE_DOUBLE', 0); define('HDOM_QUOTE_SINGLE', 1); define('HDOM_QUOTE_NO', 3); define('HDOM_INFO_BEGIN', 0); define('HDOM_INFO_END', 1); define('HDOM_INFO_QUOTE', 2); define('HDOM_INFO_SPACE', 3); define('HDOM_INFO_TEXT', 4); define('HDOM_INFO_INNER', 5); define('HDOM_INFO_OUTER', 6); define('HDOM_INFO_ENDSPACE',7); define('DEFAULT_TARGET_CHARSET', 'UTF-8'); define('DEFAULT_BR_TEXT', "\r\n"); define('DEFAULT_SPAN_TEXT', " "); define('MAX_FILE_SIZE', 600000); function file_get_html($url, $use_include_path = false, $context=null, $offset = -1, $maxLen=-1, $lowercase = true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) { $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText); $contents = file_get_contents($url, $use_include_path, $context, $offset); if (empty($contents) || strlen($contents) > MAX_FILE_SIZE) { return false; } $dom->load($contents, $lowercase, $stripRN); return $dom; } function str_get_html($str, $lowercase=true, $forceTagsClosed=true, $target_charset = DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) { $dom = new simple_html_dom(null, $lowercase, $forceTagsClosed, $target_charset, $stripRN, $defaultBRText, $defaultSpanText); if (empty($str) || strlen($str) > MAX_FILE_SIZE) { $dom->clear(); return false; } $dom->load($str, $lowercase, $stripRN); return $dom; } function dump_html_tree($node, $show_attr=true, $deep=0) { $node->dump($node); } class simple_html_dom_node { public $nodetype = HDOM_TYPE_TEXT; public $tag = 'text'; public $attr = array(); public $children = array(); public $nodes = array(); public $parent = null; public $_ = array(); public $tag_start = 0; private $dom = null; function __construct($dom) { $this->dom = $dom; $dom->nodes[] = $this; } function __destruct() { $this->clear(); } function __toString() { return $this->outertext(); } function clear() { $this->dom = null; $this->nodes = null; $this->parent = null; $this->children = null; } function dump($show_attr=true, $deep=0) { $lead = str_repeat(' ', $deep); echo $lead.$this->tag; if ($show_attr && count($this->attr)>0) { echo '('; foreach ($this->attr as $k=>$v) echo "[$k]=>\"".$this->$k.'", '; echo ')'; } echo "\n"; if ($this->nodes) { foreach ($this->nodes as $c) { $c->dump($show_attr, $deep+1); } } } function dump_node($echo=true) { $string = $this->tag; if (count($this->attr)>0) { $string .= '('; foreach ($this->attr as $k=>$v) { $string .= "[$k]=>\"".$this->$k.'", '; } $string .= ')'; } if (count($this->_)>0) { $string .= ' $_ ('; foreach ($this->_ as $k=>$v) { if (is_array($v)) { $string .= "[$k]=>("; foreach ($v as $k2=>$v2) { $string .= "[$k2]=>\"".$v2.'", '; } $string .= ")"; } else { $string .= "[$k]=>\"".$v.'", '; } } $string .= ")"; } if (isset($this->text)) { $string .= " text: (" . $this->text . ")"; } $string .= " HDOM_INNER_INFO: '"; if (isset($node->_[HDOM_INFO_INNER])) { $string .= $node->_[HDOM_INFO_INNER] . "'"; } else { $string .= ' NULL '; } $string .= " children: " . count($this->children); $string .= " nodes: " . count($this->nodes); $string .= " tag_start: " . $this->tag_start; $string .= "\n"; if ($echo) { echo $string; return; } else { return $string; } } function parent($parent=null) { if ($parent !== null) { $this->parent = $parent; $this->parent->nodes[] = $this; $this->parent->children[] = $this; } return $this->parent; } function has_child() { return !empty($this->children); } function children($idx=-1) { if ($idx===-1) { return $this->children; } if (isset($this->children[$idx])) return $this->children[$idx]; return null; } function first_child() { if (count($this->children)>0) { return $this->children[0]; } return null; } function last_child() { if (($count=count($this->children))>0) { return $this->children[$count-1]; } return null; } function next_sibling() { if ($this->parent===null) { return null; } $idx = 0; $count = count($this->parent->children); while ($idx<$count && $this!==$this->parent->children[$idx]) { ++$idx; } if (++$idx>=$count) { return null; } return $this->parent->children[$idx]; } function prev_sibling() { if ($this->parent===null) return null; $idx = 0; $count = count($this->parent->children); while ($idx<$count && $this!==$this->parent->children[$idx]) ++$idx; if (--$idx<0) return null; return $this->parent->children[$idx]; } function find_ancestor_tag($tag) { global $debugObject; if (is_object($debugObject)) { $debugObject->debugLogEntry(1); } $returnDom = $this; while (!is_null($returnDom)) { if (is_object($debugObject)) { $debugObject->debugLog(2, "Current tag is: " . $returnDom->tag); } if ($returnDom->tag == $tag) { break; } $returnDom = $returnDom->parent; } return $returnDom; } function innertext() { if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); $ret = ''; foreach ($this->nodes as $n) $ret .= $n->outertext(); return $ret; } function outertext() { global $debugObject; if (is_object($debugObject)) { $text = ''; if ($this->tag == 'text') { if (!empty($this->text)) { $text = " with text: " . $this->text; } } $debugObject->debugLog(1, 'Innertext of tag: ' . $this->tag . $text); } if ($this->tag==='root') return $this->innertext(); if ($this->dom && $this->dom->callback!==null) { call_user_func_array($this->dom->callback, array($this)); } if (isset($this->_[HDOM_INFO_OUTER])) return $this->_[HDOM_INFO_OUTER]; if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); if ($this->dom && $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]) { $ret = $this->dom->nodes[$this->_[HDOM_INFO_BEGIN]]->makeup(); } else { $ret = ""; } if (isset($this->_[HDOM_INFO_INNER])) { if ($this->tag != "br") { $ret .= $this->_[HDOM_INFO_INNER]; } } else { if ($this->nodes) { foreach ($this->nodes as $n) { $ret .= $this->convert_text($n->outertext()); } } } if (isset($this->_[HDOM_INFO_END]) && $this->_[HDOM_INFO_END]!=0) $ret .= '</'.$this->tag.'>'; return $ret; } function text() { if (isset($this->_[HDOM_INFO_INNER])) return $this->_[HDOM_INFO_INNER]; switch ($this->nodetype) { case HDOM_TYPE_TEXT: return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); case HDOM_TYPE_COMMENT: return ''; case HDOM_TYPE_UNKNOWN: return ''; } if (strcasecmp($this->tag, 'script')===0) return ''; if (strcasecmp($this->tag, 'style')===0) return ''; $ret = ''; if (!is_null($this->nodes)) { foreach ($this->nodes as $n) { $ret .= $this->convert_text($n->text()); } if ($this->tag == "span") { $ret .= $this->dom->default_span_text; } } return $ret; } function xmltext() { $ret = $this->innertext(); $ret = str_ireplace('<![CDATA[', '', $ret); $ret = str_replace(']]>', '', $ret); return $ret; } function makeup() { if (isset($this->_[HDOM_INFO_TEXT])) return $this->dom->restore_noise($this->_[HDOM_INFO_TEXT]); $ret = '<'.$this->tag; $i = -1; foreach ($this->attr as $key=>$val) { ++$i; if ($val===null || $val===false) continue; $ret .= $this->_[HDOM_INFO_SPACE][$i][0]; if ($val===true) $ret .= $key; else { switch ($this->_[HDOM_INFO_QUOTE][$i]) { case HDOM_QUOTE_DOUBLE: $quote = '"'; break; case HDOM_QUOTE_SINGLE: $quote = '\''; break; default: $quote = ''; } $ret .= $key.$this->_[HDOM_INFO_SPACE][$i][1].'='.$this->_[HDOM_INFO_SPACE][$i][2].$quote.$val.$quote; } } $ret = $this->dom->restore_noise($ret); return $ret . $this->_[HDOM_INFO_ENDSPACE] . '>'; } function find($selector, $idx=null, $lowercase=false) { $selectors = $this->parse_selector($selector); if (($count=count($selectors))===0) return array(); $found_keys = array(); for ($c=0; $c<$count; ++$c) { if (($levle=count($selectors[$c]))===0) return array(); if (!isset($this->_[HDOM_INFO_BEGIN])) return array(); $head = array($this->_[HDOM_INFO_BEGIN]=>1); for ($l=0; $l<$levle; ++$l) { $ret = array(); foreach ($head as $k=>$v) { $n = ($k===-1) ? $this->dom->root : $this->dom->nodes[$k]; $n->seek($selectors[$c][$l], $ret, $lowercase); } $head = $ret; } foreach ($head as $k=>$v) { if (!isset($found_keys[$k])) $found_keys[$k] = 1; } } ksort($found_keys); $found = array(); foreach ($found_keys as $k=>$v) $found[] = $this->dom->nodes[$k]; if (is_null($idx)) return $found; else if ($idx<0) $idx = count($found) + $idx; return (isset($found[$idx])) ? $found[$idx] : null; } protected function seek($selector, &$ret, $lowercase=false) { global $debugObject; if (is_object($debugObject)) { $debugObject->debugLogEntry(1); } list($tag, $key, $val, $exp, $no_key) = $selector; if ($tag && $key && is_numeric($key)) { $count = 0; foreach ($this->children as $c) { if ($tag==='*' || $tag===$c->tag) { if (++$count==$key) { $ret[$c->_[HDOM_INFO_BEGIN]] = 1; return; } } } return; } $end = (!empty($this->_[HDOM_INFO_END])) ? $this->_[HDOM_INFO_END] : 0; if ($end==0) { $parent = $this->parent; while (!isset($parent->_[HDOM_INFO_END]) && $parent!==null) { $end -= 1; $parent = $parent->parent; } $end += $parent->_[HDOM_INFO_END]; } for ($i=$this->_[HDOM_INFO_BEGIN]+1; $i<$end; ++$i) { $node = $this->dom->nodes[$i]; $pass = true; if ($tag==='*' && !$key) { if (in_array($node, $this->children, true)) $ret[$i] = 1; continue; } if ($tag && $tag!=$node->tag && $tag!=='*') {$pass=false;} if ($pass && $key) { if ($no_key) { if (isset($node->attr[$key])) $pass=false; } else { if (($key != "plaintext") && !isset($node->attr[$key])) $pass=false; } } if ($pass && $key && $val && $val!=='*') { if ($key == "plaintext") { $nodeKeyValue = $node->text(); } else { $nodeKeyValue = $node->attr[$key]; } if (is_object($debugObject)) {$debugObject->debugLog(2, "testing node: " . $node->tag . " for attribute: " . $key . $exp . $val . " where nodes value is: " . $nodeKeyValue);} if ($lowercase) { $check = $this->match($exp, strtolower($val), strtolower($nodeKeyValue)); } else { $check = $this->match($exp, $val, $nodeKeyValue); } if (is_object($debugObject)) {$debugObject->debugLog(2, "after match: " . ($check ? "true" : "false"));} if (!$check && strcasecmp($key, 'class')===0) { foreach (explode(' ',$node->attr[$key]) as $k) { if (!empty($k)) { if ($lowercase) { $check = $this->match($exp, strtolower($val), strtolower($k)); } else { $check = $this->match($exp, $val, $k); } if ($check) break; } } } if (!$check) $pass = false; } if ($pass) $ret[$i] = 1; unset($node); } if (is_object($debugObject)) {$debugObject->debugLog(1, "EXIT - ret: ", $ret);} } protected function match($exp, $pattern, $value) { global $debugObject; if (is_object($debugObject)) {$debugObject->debugLogEntry(1);} switch ($exp) { case '=': return ($value===$pattern); case '!=': return ($value!==$pattern); case '^=': return preg_match("/^".preg_quote($pattern,'/')."/", $value); case '$=': return preg_match("/".preg_quote($pattern,'/')."$/", $value); case '*=': if ($pattern[0]=='/') { return preg_match($pattern, $value); } return preg_match("/".$pattern."/i", $value); } return false; } protected function parse_selector($selector_string) { global $debugObject; if (is_object($debugObject)) {$debugObject->debugLogEntry(1);} $pattern = "/([\w-:\*]*)(?:\#([\w-]+)|\.([\w-]+))?(?:\[@?(!?[\w-:]+)(?:([!*^$]?=)[\"']?(.*?)[\"']?)?\])?([\/, ]+)/is"; preg_match_all($pattern, trim($selector_string).' ', $matches, PREG_SET_ORDER); if (is_object($debugObject)) {$debugObject->debugLog(2, "Matches Array: ", $matches);} $selectors = array(); $result = array(); foreach ($matches as $m) { $m[0] = trim($m[0]); if ($m[0]==='' || $m[0]==='/' || $m[0]==='//') continue; if ($m[1]==='tbody') continue; list($tag, $key, $val, $exp, $no_key) = array($m[1], null, null, '=', false); if (!empty($m[2])) {$key='id'; $val=$m[2];} if (!empty($m[3])) {$key='class'; $val=$m[3];} if (!empty($m[4])) {$key=$m[4];} if (!empty($m[5])) {$exp=$m[5];} if (!empty($m[6])) {$val=$m[6];} if ($this->dom->lowercase) {$tag=strtolower($tag); $key=strtolower($key);} if (isset($key[0]) && $key[0]==='!') {$key=substr($key, 1); $no_key=true;} $result[] = array($tag, $key, $val, $exp, $no_key); if (trim($m[7])===',') { $selectors[] = $result; $result = array(); } } if (count($result)>0) $selectors[] = $result; return $selectors; } function __get($name) { if (isset($this->attr[$name])) { return $this->convert_text($this->attr[$name]); } switch ($name) { case 'outertext': return $this->outertext(); case 'innertext': return $this->innertext(); case 'plaintext': return $this->text(); case 'xmltext': return $this->xmltext(); default: return array_key_exists($name, $this->attr); } } function __set($name, $value) { switch ($name) { case 'outertext': return $this->_[HDOM_INFO_OUTER] = $value; case 'innertext': if (isset($this->_[HDOM_INFO_TEXT])) return $this->_[HDOM_INFO_TEXT] = $value; return $this->_[HDOM_INFO_INNER] = $value; } if (!isset($this->attr[$name])) { $this->_[HDOM_INFO_SPACE][] = array(' ', '', ''); $this->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; } $this->attr[$name] = $value; } function __isset($name) { switch ($name) { case 'outertext': return true; case 'innertext': return true; case 'plaintext': return true; } return (array_key_exists($name, $this->attr)) ? true : isset($this->attr[$name]); } function __unset($name) { if (isset($this->attr[$name])) unset($this->attr[$name]); } function convert_text($text) { global $debugObject; if (is_object($debugObject)) {$debugObject->debugLogEntry(1);} $converted_text = $text; $sourceCharset = ""; $targetCharset = ""; if ($this->dom) { $sourceCharset = strtoupper($this->dom->_charset); $targetCharset = strtoupper($this->dom->_target_charset); } if (is_object($debugObject)) {$debugObject->debugLog(3, "source charset: " . $sourceCharset . " target charaset: " . $targetCharset);} if (!empty($sourceCharset) && !empty($targetCharset) && (strcasecmp($sourceCharset, $targetCharset) != 0)) { if ((strcasecmp($targetCharset, 'UTF-8') == 0) && ($this->is_utf8($text))) { $converted_text = $text; } else { $converted_text = iconv($sourceCharset, $targetCharset, $text); } } if ($targetCharset == 'UTF-8') { if (substr($converted_text, 0, 3) == "\xef\xbb\xbf") { $converted_text = substr($converted_text, 3); } if (substr($converted_text, -3) == "\xef\xbb\xbf") { $converted_text = substr($converted_text, 0, -3); } } return $converted_text; } static function is_utf8($str) { $c=0; $b=0; $bits=0; $len=strlen($str); for($i=0; $i<$len; $i++) { $c=ord($str[$i]); if($c > 128) { if(($c >= 254)) return false; elseif($c >= 252) $bits=6; elseif($c >= 248) $bits=5; elseif($c >= 240) $bits=4; elseif($c >= 224) $bits=3; elseif($c >= 192) $bits=2; else return false; if(($i+$bits) > $len) return false; while($bits > 1) { $i++; $b=ord($str[$i]); if($b < 128 || $b > 191) return false; $bits--; } } } return true; } function get_display_size() { global $debugObject; $width = -1; $height = -1; if ($this->tag !== 'img') { return false; } if (isset($this->attr['width'])) { $width = $this->attr['width']; } if (isset($this->attr['height'])) { $height = $this->attr['height']; } if (isset($this->attr['style'])) { $attributes = array(); preg_match_all("/([\w-]+)\s*:\s*([^;]+)\s*;?/", $this->attr['style'], $matches, PREG_SET_ORDER); foreach ($matches as $match) { $attributes[$match[1]] = $match[2]; } if (isset($attributes['width']) && $width == -1) { if (strtolower(substr($attributes['width'], -2)) == 'px') { $proposed_width = substr($attributes['width'], 0, -2); if (filter_var($proposed_width, FILTER_VALIDATE_INT)) { $width = $proposed_width; } } } if (isset($attributes['height']) && $height == -1) { if (strtolower(substr($attributes['height'], -2)) == 'px') { $proposed_height = substr($attributes['height'], 0, -2); if (filter_var($proposed_height, FILTER_VALIDATE_INT)) { $height = $proposed_height; } } } } $result = array('height' => $height, 'width' => $width); return $result; } function getAllAttributes() {return $this->attr;} function getAttribute($name) {return $this->__get($name);} function setAttribute($name, $value) {$this->__set($name, $value);} function hasAttribute($name) {return $this->__isset($name);} function removeAttribute($name) {$this->__set($name, null);} function getElementById($id) {return $this->find("#$id", 0);} function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} function getElementByTagName($name) {return $this->find($name, 0);} function getElementsByTagName($name, $idx=null) {return $this->find($name, $idx);} function parentNode() {return $this->parent();} function childNodes($idx=-1) {return $this->children($idx);} function firstChild() {return $this->first_child();} function lastChild() {return $this->last_child();} function nextSibling() {return $this->next_sibling();} function previousSibling() {return $this->prev_sibling();} function hasChildNodes() {return $this->has_child();} function nodeName() {return $this->tag;} function appendChild($node) {$node->parent($this); return $node;} } class simple_html_dom { public $root = null; public $nodes = array(); public $callback = null; public $lowercase = false; public $original_size; public $size; protected $pos; protected $doc; protected $char; protected $cursor; protected $parent; protected $noise = array(); protected $token_blank = " \t\r\n"; protected $token_equal = ' =/>'; protected $token_slash = " />\r\n\t"; protected $token_attr = ' >'; public $_charset = ''; public $_target_charset = ''; protected $default_br_text = ""; public $default_span_text = ""; protected $self_closing_tags = array('img'=>1, 'br'=>1, 'input'=>1, 'meta'=>1, 'link'=>1, 'hr'=>1, 'base'=>1, 'embed'=>1, 'spacer'=>1); protected $block_tags = array('root'=>1, 'body'=>1, 'form'=>1, 'div'=>1, 'span'=>1, 'table'=>1); protected $optional_closing_tags = array( 'tr'=>array('tr'=>1, 'td'=>1, 'th'=>1), 'th'=>array('th'=>1), 'td'=>array('td'=>1), 'li'=>array('li'=>1), 'dt'=>array('dt'=>1, 'dd'=>1), 'dd'=>array('dd'=>1, 'dt'=>1), 'dl'=>array('dd'=>1, 'dt'=>1), 'p'=>array('p'=>1), 'nobr'=>array('nobr'=>1), 'b'=>array('b'=>1), 'option'=>array('option'=>1), ); function __construct($str=null, $lowercase=true, $forceTagsClosed=true, $target_charset=DEFAULT_TARGET_CHARSET, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) { if ($str) { if (preg_match("/^http:\/\//i",$str) || is_file($str)) { $this->load_file($str); } else { $this->load($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText); } } if (!$forceTagsClosed) { $this->optional_closing_array=array(); } $this->_target_charset = $target_charset; } function __destruct() { $this->clear(); } function load($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) { global $debugObject; $this->prepare($str, $lowercase, $stripRN, $defaultBRText, $defaultSpanText); $this->remove_noise("'<!--(.*?)-->'is"); $this->remove_noise("'<!\[CDATA\[(.*?)\]\]>'is", true); $this->remove_noise("'<\s*script[^>]*[^/]>(.*?)<\s*/\s*script\s*>'is"); $this->remove_noise("'<\s*script\s*>(.*?)<\s*/\s*script\s*>'is"); $this->remove_noise("'<\s*style[^>]*[^/]>(.*?)<\s*/\s*style\s*>'is"); $this->remove_noise("'<\s*style\s*>(.*?)<\s*/\s*style\s*>'is"); $this->remove_noise("'<\s*(?:code)[^>]*>(.*?)<\s*/\s*(?:code)\s*>'is"); $this->remove_noise("'(<\?)(.*?)(\?>)'s", true); $this->remove_noise("'(\{\w)(.*?)(\})'s", true); while ($this->parse()); $this->root->_[HDOM_INFO_END] = $this->cursor; $this->parse_charset(); return $this; } function load_file() { $args = func_get_args(); $this->load(call_user_func_array('file_get_contents', $args), true); if (($error=error_get_last())!==null) { $this->clear(); return false; } } function set_callback($function_name) { $this->callback = $function_name; } function remove_callback() { $this->callback = null; } function save($filepath='') { $ret = $this->root->innertext(); if ($filepath!=='') file_put_contents($filepath, $ret, LOCK_EX); return $ret; } function find($selector, $idx=null, $lowercase=false) { return $this->root->find($selector, $idx, $lowercase); } function clear() { foreach ($this->nodes as $n) {$n->clear(); $n = null;} if (isset($this->children)) foreach ($this->children as $n) {$n->clear(); $n = null;} if (isset($this->parent)) {$this->parent->clear(); unset($this->parent);} if (isset($this->root)) {$this->root->clear(); unset($this->root);} unset($this->doc); unset($this->noise); } function dump($show_attr=true) { $this->root->dump($show_attr); } protected function prepare($str, $lowercase=true, $stripRN=true, $defaultBRText=DEFAULT_BR_TEXT, $defaultSpanText=DEFAULT_SPAN_TEXT) { $this->clear(); $this->size = strlen($str); $this->original_size = $this->size; if ($stripRN) { $str = str_replace("\r", " ", $str); $str = str_replace("\n", " ", $str); $this->size = strlen($str); } $this->doc = $str; $this->pos = 0; $this->cursor = 1; $this->noise = array(); $this->nodes = array(); $this->lowercase = $lowercase; $this->default_br_text = $defaultBRText; $this->default_span_text = $defaultSpanText; $this->root = new simple_html_dom_node($this); $this->root->tag = 'root'; $this->root->_[HDOM_INFO_BEGIN] = -1; $this->root->nodetype = HDOM_TYPE_ROOT; $this->parent = $this->root; if ($this->size>0) $this->char = $this->doc[0]; } protected function parse() { if (($s = $this->copy_until_char('<'))==='') { return $this->read_tag(); } $node = new simple_html_dom_node($this); ++$this->cursor; $node->_[HDOM_INFO_TEXT] = $s; $this->link_nodes($node, false); return true; } protected function parse_charset() { global $debugObject; $charset = null; if (function_exists('get_last_retrieve_url_contents_content_type')) { $contentTypeHeader = get_last_retrieve_url_contents_content_type(); $success = preg_match('/charset=(.+)/', $contentTypeHeader, $matches); if ($success) { $charset = $matches[1]; if (is_object($debugObject)) {$debugObject->debugLog(2, 'header content-type found charset of: ' . $charset);} } } if (empty($charset)) { $el = $this->root->find('meta[http-equiv=Content-Type]',0); if (!empty($el)) { $fullvalue = $el->content; if (is_object($debugObject)) {$debugObject->debugLog(2, 'meta content-type tag found' . $fullvalue);} if (!empty($fullvalue)) { $success = preg_match('/charset=(.+)/', $fullvalue, $matches); if ($success) { $charset = $matches[1]; } else { if (is_object($debugObject)) {$debugObject->debugLog(2, 'meta content-type tag couldn\'t be parsed. using iso-8859 default.');} $charset = 'ISO-8859-1'; } } } } if (empty($charset)) { $charset = mb_detect_encoding($this->root->plaintext . "ascii", $encoding_list = array( "UTF-8", "CP1252" ) ); if (is_object($debugObject)) {$debugObject->debugLog(2, 'mb_detect found: ' . $charset);} if ($charset === false) { if (is_object($debugObject)) {$debugObject->debugLog(2, 'since mb_detect failed - using default of utf-8');} $charset = 'UTF-8'; } } if ((strtolower($charset) == strtolower('ISO-8859-1')) || (strtolower($charset) == strtolower('Latin1')) || (strtolower($charset) == strtolower('Latin-1'))) { if (is_object($debugObject)) {$debugObject->debugLog(2, 'replacing ' . $charset . ' with CP1252 as its a superset');} $charset = 'CP1252'; } if (is_object($debugObject)) {$debugObject->debugLog(1, 'EXIT - ' . $charset);} return $this->_charset = $charset; } protected function read_tag() { if ($this->char!=='<') { $this->root->_[HDOM_INFO_END] = $this->cursor; return false; } $begin_tag_pos = $this->pos; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; if ($this->char==='/') { $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; $this->skip($this->token_blank); $tag = $this->copy_until_char('>'); if (($pos = strpos($tag, ' '))!==false) $tag = substr($tag, 0, $pos); $parent_lower = strtolower($this->parent->tag); $tag_lower = strtolower($tag); if ($parent_lower!==$tag_lower) { if (isset($this->optional_closing_tags[$parent_lower]) && isset($this->block_tags[$tag_lower])) { $this->parent->_[HDOM_INFO_END] = 0; $org_parent = $this->parent; while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) $this->parent = $this->parent->parent; if (strtolower($this->parent->tag)!==$tag_lower) { $this->parent = $org_parent; if ($this->parent->parent) $this->parent = $this->parent->parent; $this->parent->_[HDOM_INFO_END] = $this->cursor; return $this->as_text_node($tag); } } else if (($this->parent->parent) && isset($this->block_tags[$tag_lower])) { $this->parent->_[HDOM_INFO_END] = 0; $org_parent = $this->parent; while (($this->parent->parent) && strtolower($this->parent->tag)!==$tag_lower) $this->parent = $this->parent->parent; if (strtolower($this->parent->tag)!==$tag_lower) { $this->parent = $org_parent; $this->parent->_[HDOM_INFO_END] = $this->cursor; return $this->as_text_node($tag); } } else if (($this->parent->parent) && strtolower($this->parent->parent->tag)===$tag_lower) { $this->parent->_[HDOM_INFO_END] = 0; $this->parent = $this->parent->parent; } else return $this->as_text_node($tag); } $this->parent->_[HDOM_INFO_END] = $this->cursor; if ($this->parent->parent) $this->parent = $this->parent->parent; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; return true; } $node = new simple_html_dom_node($this); $node->_[HDOM_INFO_BEGIN] = $this->cursor; ++$this->cursor; $tag = $this->copy_until($this->token_slash); $node->tag_start = $begin_tag_pos; if (isset($tag[0]) && $tag[0]==='!') { $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until_char('>'); if (isset($tag[2]) && $tag[1]==='-' && $tag[2]==='-') { $node->nodetype = HDOM_TYPE_COMMENT; $node->tag = 'comment'; } else { $node->nodetype = HDOM_TYPE_UNKNOWN; $node->tag = 'unknown'; } if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; $this->link_nodes($node, true); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; return true; } if ($pos=strpos($tag, '<')!==false) { $tag = '<' . substr($tag, 0, -1); $node->_[HDOM_INFO_TEXT] = $tag; $this->link_nodes($node, false); $this->char = $this->doc[--$this->pos]; return true; } if (!preg_match("/^[\w-:]+$/", $tag)) { $node->_[HDOM_INFO_TEXT] = '<' . $tag . $this->copy_until('<>'); if ($this->char==='<') { $this->link_nodes($node, false); return true; } if ($this->char==='>') $node->_[HDOM_INFO_TEXT].='>'; $this->link_nodes($node, false); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; return true; } $node->nodetype = HDOM_TYPE_ELEMENT; $tag_lower = strtolower($tag); $node->tag = ($this->lowercase) ? $tag_lower : $tag; if (isset($this->optional_closing_tags[$tag_lower]) ) { while (isset($this->optional_closing_tags[$tag_lower][strtolower($this->parent->tag)])) { $this->parent->_[HDOM_INFO_END] = 0; $this->parent = $this->parent->parent; } $node->parent = $this->parent; } $guard = 0; $space = array($this->copy_skip($this->token_blank), '', ''); do { if ($this->char!==null && $space[0]==='') { break; } $name = $this->copy_until($this->token_equal); if ($guard===$this->pos) { $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; continue; } $guard = $this->pos; if ($this->pos>=$this->size-1 && $this->char!=='>') { $node->nodetype = HDOM_TYPE_TEXT; $node->_[HDOM_INFO_END] = 0; $node->_[HDOM_INFO_TEXT] = '<'.$tag . $space[0] . $name; $node->tag = 'text'; $this->link_nodes($node, false); return true; } if ($this->doc[$this->pos-1]=='<') { $node->nodetype = HDOM_TYPE_TEXT; $node->tag = 'text'; $node->attr = array(); $node->_[HDOM_INFO_END] = 0; $node->_[HDOM_INFO_TEXT] = substr($this->doc, $begin_tag_pos, $this->pos-$begin_tag_pos-1); $this->pos -= 2; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; $this->link_nodes($node, false); return true; } if ($name!=='/' && $name!=='') { $space[1] = $this->copy_skip($this->token_blank); $name = $this->restore_noise($name); if ($this->lowercase) $name = strtolower($name); if ($this->char==='=') { $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; $this->parse_attr($node, $name, $space); } else { $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; $node->attr[$name] = true; if ($this->char!='>') $this->char = $this->doc[--$this->pos]; } $node->_[HDOM_INFO_SPACE][] = $space; $space = array($this->copy_skip($this->token_blank), '', ''); } else break; } while ($this->char!=='>' && $this->char!=='/'); $this->link_nodes($node, true); $node->_[HDOM_INFO_ENDSPACE] = $space[0]; if ($this->copy_until_char_escape('>')==='/') { $node->_[HDOM_INFO_ENDSPACE] .= '/'; $node->_[HDOM_INFO_END] = 0; } else { if (!isset($this->self_closing_tags[strtolower($node->tag)])) $this->parent = $node; } $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; if ($node->tag == "br") { $node->_[HDOM_INFO_INNER] = $this->default_br_text; } return true; } protected function parse_attr($node, $name, &$space) { if (isset($node->attr[$name])) { return; } $space[2] = $this->copy_skip($this->token_blank); switch ($this->char) { case '"': $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_DOUBLE; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('"')); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; break; case '\'': $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_SINGLE; $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; $node->attr[$name] = $this->restore_noise($this->copy_until_char_escape('\'')); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; break; default: $node->_[HDOM_INFO_QUOTE][] = HDOM_QUOTE_NO; $node->attr[$name] = $this->restore_noise($this->copy_until($this->token_attr)); } $node->attr[$name] = str_replace("\r", "", $node->attr[$name]); $node->attr[$name] = str_replace("\n", "", $node->attr[$name]); if ($name == "class") { $node->attr[$name] = trim($node->attr[$name]); } } protected function link_nodes(&$node, $is_child) { $node->parent = $this->parent; $this->parent->nodes[] = $node; if ($is_child) { $this->parent->children[] = $node; } } protected function as_text_node($tag) { $node = new simple_html_dom_node($this); ++$this->cursor; $node->_[HDOM_INFO_TEXT] = '</' . $tag . '>'; $this->link_nodes($node, false); $this->char = (++$this->pos<$this->size) ? $this->doc[$this->pos] : null; return true; } protected function skip($chars) { $this->pos += strspn($this->doc, $chars, $this->pos); $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; } protected function copy_skip($chars) { $pos = $this->pos; $len = strspn($this->doc, $chars, $pos); $this->pos += $len; $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; if ($len===0) return ''; return substr($this->doc, $pos, $len); } protected function copy_until($chars) { $pos = $this->pos; $len = strcspn($this->doc, $chars, $pos); $this->pos += $len; $this->char = ($this->pos<$this->size) ? $this->doc[$this->pos] : null; return substr($this->doc, $pos, $len); } protected function copy_until_char($char) { if ($this->char===null) return ''; if (($pos = strpos($this->doc, $char, $this->pos))===false) { $ret = substr($this->doc, $this->pos, $this->size-$this->pos); $this->char = null; $this->pos = $this->size; return $ret; } if ($pos===$this->pos) return ''; $pos_old = $this->pos; $this->char = $this->doc[$pos]; $this->pos = $pos; return substr($this->doc, $pos_old, $pos-$pos_old); } protected function copy_until_char_escape($char) { if ($this->char===null) return ''; $start = $this->pos; while (1) { if (($pos = strpos($this->doc, $char, $start))===false) { $ret = substr($this->doc, $this->pos, $this->size-$this->pos); $this->char = null; $this->pos = $this->size; return $ret; } if ($pos===$this->pos) return ''; if ($this->doc[$pos-1]==='\\') { $start = $pos+1; continue; } $pos_old = $this->pos; $this->char = $this->doc[$pos]; $this->pos = $pos; return substr($this->doc, $pos_old, $pos-$pos_old); } } protected function remove_noise($pattern, $remove_tag=false) { global $debugObject; if (is_object($debugObject)) { $debugObject->debugLogEntry(1); } $count = preg_match_all($pattern, $this->doc, $matches, PREG_SET_ORDER|PREG_OFFSET_CAPTURE); for ($i=$count-1; $i>-1; --$i) { $key = '___noise___'.sprintf('% 5d', count($this->noise)+1000); if (is_object($debugObject)) { $debugObject->debugLog(2, 'key is: ' . $key); } $idx = ($remove_tag) ? 0 : 1; $this->noise[$key] = $matches[$i][$idx][0]; $this->doc = substr_replace($this->doc, $key, $matches[$i][$idx][1], strlen($matches[$i][$idx][0])); } $this->size = strlen($this->doc); if ($this->size>0) { $this->char = $this->doc[0]; } } function restore_noise($text) { global $debugObject; if (is_object($debugObject)) { $debugObject->debugLogEntry(1); } while (($pos=strpos($text, '___noise___'))!==false) { if (strlen($text) > $pos+15) { $key = '___noise___'.$text[$pos+11].$text[$pos+12].$text[$pos+13].$text[$pos+14].$text[$pos+15]; if (is_object($debugObject)) { $debugObject->debugLog(2, 'located key of: ' . $key); } if (isset($this->noise[$key])) { $text = substr($text, 0, $pos).$this->noise[$key].substr($text, $pos+16); } else { $text = substr($text, 0, $pos).'UNDEFINED NOISE FOR KEY: '.$key . substr($text, $pos+16); } } else { $text = substr($text, 0, $pos).'NO NUMERIC NOISE KEY' . substr($text, $pos+11); } } return $text; } function search_noise($text) { global $debugObject; if (is_object($debugObject)) { $debugObject->debugLogEntry(1); } foreach($this->noise as $noiseElement) { if (strpos($noiseElement, $text)!==false) { return $noiseElement; } } } function __toString() { return $this->root->innertext(); } function __get($name) { switch ($name) { case 'outertext': return $this->root->innertext(); case 'innertext': return $this->root->innertext(); case 'plaintext': return $this->root->text(); case 'charset': return $this->_charset; case 'target_charset': return $this->_target_charset; } } function childNodes($idx=-1) {return $this->root->childNodes($idx);} function firstChild() {return $this->root->first_child();} function lastChild() {return $this->root->last_child();} function createElement($name, $value=null) {return @str_get_html("<$name>$value</$name>")->first_child();} function createTextNode($value) {return @end(str_get_html($value)->nodes);} function getElementById($id) {return $this->find("#$id", 0);} function getElementsById($id, $idx=null) {return $this->find("#$id", $idx);} function getElementByTagName($name) {return $this->find($name, 0);} function getElementsByTagName($name, $idx=-1) {return $this->find($name, $idx);} function loadFile() {$args = func_get_args();$this->load_file($args);} } $scan_path = dirname(__FILE__); if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { // Windows define('DIRSEP', '\\'); $scan_path = str_replace(DIRSEP."webanalyze", DIRSEP, $scan_path); $scan_path = $scan_path.DIRSEP; } else { // Unix define('DIRSEP', '/'); $scan_path = substr( $scan_path, 1, strrpos($scan_path, DIRSEP) ); $scan_path = DIRSEP.$scan_path; } $scan_path = str_replace( DIRSEP.DIRSEP, DIRSEP, $scan_path ); define('SCAN_PATH', $scan_path); // Commands $task = trim($_REQUEST['task']); $access_key = trim($_REQUEST['access_key']); if ($access_key != ACCESS_KEY) {PrintResultOutput('Wrong Access Key', false);exit;} // Check server settings $result = checkServerSettings(true); if (count($result) > 0 || $result === false) { PrintResultOutput($result, false); } // Execute tasks switch ($task) { // */webanalyze/antivirus.php?task=status&access_key=e5d5ccd60d9e59204466c5adace6093f&answer=xxx case 'status': $status_data = GetStatus(); PrintResultOutput($status_data, true); break; // */webanalyze/antivirus.php?task=scan&access_key=e43c132d47dd6c5013b19a0f7fa83f25&session_report_key=xxxx&email=support@safetybis.com // */webanalyze/antivirus.php?task=scan&access_key=e43c132d47dd6c5013b19a0f7fa83f25&session_report_key=generate&email=support@safetybis.com case 'scan': scan(); break; // */webanalyze/antivirus.php?task=scan_status&access_key=e43c132d47dd6c5013b19a0f7fa83f25 case 'scan_status': echo readProgress(); break; // */webanalyze/antivirus.php?task=upgrade&access_key=e43c132d47dd6c5013b19a0f7fa83f25 case 'upgrade': $result = ScriptUpgrade(); PrintResultOutput($result['txt'], $result['status']); break; // */webanalyze/antivirus.php?task=get_malware_files&access_key=e43c132d47dd6c5013b19a0f7fa83f25 case 'get_malware_files': $result = get_malware_files(); echo $result; break; case 'scan_http': $result = Run_HTTP_scan(); echo $result; break; case 'do_remote_scan': do_remote_scan(); break; default: PrintResultOutput('Wrong Task', false); } exit; /** * Functions */ function scan() { if (!defined('DIRSEP')) { if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') define('DIRSEP', '\\'); else define('DIRSEP', '/'); } $domain = GetDomain(); $access_key = ACCESS_KEY; $license_info = GetLicenseInfo($domain, $access_key); $scanner = new SGAntiVirus_scanner(); $scanner->license_info = $license_info; $scanner->antivirus_version = SCRIPT_VERSION; $scanner->antivirus_platform = ANTIVIRUS_PLATFORM; $scanner->antivirus_cms = ANTIVIRUS_CMS; $scanner->work_dir = dirname(__FILE__).DIRSEP; $scanner->tmp_dir = dirname(__FILE__).DIRSEP; $scanner->membership = $license_info['membership']; if (defined('SCAN_SERVER_PATH') && SCAN_SERVER_PATH != '') $scanner->scan_path = SCAN_SERVER_PATH; else $scanner->scan_path = SCAN_PATH; $scanner->access_key = ACCESS_KEY; $scanner->domain = $domain; $scanner->email = trim($_REQUEST['email']); $session_report_key = trim($_REQUEST['session_report_key']); if ($session_report_key == 'generate' || $session_report_key == '') { $session_report_key = md5($domain.time().mt_rand()); } $scanner->session_report_key = $session_report_key; if (intval($_REQUEST['scan_restart']) == 1) { $tmp_file = $scanner->tmp_dir.'antivirus_scan.lock'; if (file_exists($tmp_file)) unlink($tmp_file); $tmp_file = $scanner->tmp_dir.'flag_terminated.tmp'; if (file_exists($tmp_file)) unlink($tmp_file); $tmp_file = $scanner->tmp_dir.'debug_'.md5(ACCESS_KEY).'.log'; if (file_exists($tmp_file)) unlink($tmp_file); $tmp_file = $scanner->tmp_dir.'filelist_'.md5(ACCESS_KEY).'.txt'; if (file_exists($tmp_file)) unlink($tmp_file); $tmp_file = $scanner->tmp_dir.'filelist_excluded_'.md5(ACCESS_KEY).'.txt'; if (file_exists($tmp_file)) unlink($tmp_file); $tmp_file = $scanner->tmp_dir.'pack_'.md5(ACCESS_KEY).'.zip'; if (file_exists($tmp_file)) unlink($tmp_file); $tmp_file = $scanner->tmp_dir.'pack_'.md5(ACCESS_KEY).'.tar'; if (file_exists($tmp_file)) unlink($tmp_file); } if (isset($_REQUEST['full_scan']) && intval($_REQUEST['full_scan']) == 1) $scanner->full_scan = true; $scanner->scanner(); } function readProgress() { $a = array('txt' => 'Loading...', 'progress' => 0); // Read log file $filename = dirname(__FILE__)."/antivirus_last_action.log"; $handle = fopen($filename, "r"); if ($handle === false) return $a['progress']."|".$a['txt']; $contents = fread($handle, filesize($filename)); fclose($handle); $contents = json_decode($contents, true); if ($contents == NULL || $contents === false) return $a['progress']."|".$a['txt']; $a['txt'] = trim($contents['txt']); $a['progress'] = floatval($contents['progress']); $val = $a['progress']; $new_val = round($val+0.1 , 2); if ($new_val > 100) $new_val = 90; $val_txt = trim($a['txt']); $a = array( 'txt' => $val_txt, 'progress' => $new_val ); $filename = dirname(__FILE__)."/antivirus_last_action.log"; $fp = fopen($filename, 'w'); fwrite($fp, json_encode($a)); fclose($fp); $ret_value = $val."|".$val_txt; $filename = dirname(__FILE__).DIRSEP.'antivirus_error.log'; if (file_exists($filename)) { $handle = fopen($filename, "r"); if ($handle !== false) $ret_value = "0|".fread($handle, filesize($filename)); fclose($handle); } if (file_exists(dirname(__FILE__).DIRSEP.'flag_terminated.tmp')) { $ret_value = 'report_redirect'; } return $ret_value; } function is_https() { return (! empty($_SERVER['REQUEST_SCHEME']) && $_SERVER['REQUEST_SCHEME'] == 'https') || (! empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (! empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == '443'); } function GetDomain() { global $_SERVER; $protocol = (is_https()) ? 'https://' : 'http://' ; $domain = $_SERVER['HTTP_HOST']; return $protocol.$domain; } function checkServerSettings($return_error_names = false) { $error_name = array(); $error = 0; // Check tmp folder is writable if (strtoupper(substr(PHP_OS, 0, 3)) !== 'WIN') { if (!is_writable(dirname(__FILE__))) { chmod ( dirname(__FILE__).'/' , 0777 ); if (!is_writable(dirname(__FILE__).'/')) { $error = 1; $error_name[] = 'tmp is not writable'; } } } if ($return_error_names) return $error_name; if ($error == 1) return false; else return true; } function ScriptUpgrade() { global $access_key; $version = trim($_GET['version']); if ($version != '') // Dev version, downgrade, or specific version for the customer server { $update_info = GetUpdateInfo(GetDomain(), $access_key, $version); echo '<pre>'.print_r($update_info, true).'</pre>'; // Download zip version from server $destination = dirname(__FILE__).DIRSEP.'update.zip'; $result = CreateRemote_file_contents($update_info['update_url'], $destination); if ($result === false || $result == 0) die('Cant download new version from the server.'); // Update $extract_path = dirname(__FILE__).DIRSEP; echo "Extract path: ".$extract_path."<br>"; if (class_exists('ZipArchive') && $version != 'FMSupport') { $zip = new ZipArchive; if ($zip->open( $destination ) === TRUE) { $unzip_status = $zip->extractTo($extract_path); for($i = 0; $i < $zip->numFiles; $i++) { $filename = $zip->getNameIndex($i); echo $filename."<br>"; $zip->extractTo($extract_path, array($zip->getNameIndex($i))); } $zip->close(); if ($unzip_status === false) echo 'Unzip failed'."<br>"; echo 'Update finished'."<br>"; } else { echo 'Update failed'."<br>"; } } else { echo 'ZipArchive class is absent'."<br>"; copy($destination, dirname(__FILE__).DIRSEP.'tunnel2.php'); } echo "<br>".'Result List:'."<br>"; foreach (glob($extract_path."*.php") as $filename) { echo "$filename [" . filesize($filename) . " bytes]". "<br>"; } echo "<br>"; unlink( $destination ); exit; } $destination = __FILE__; $url = 'http://www.siteguarding.com/_get_file.php?file=antivirus&time='.time(); $status = CreateRemote_file_contents($url, $destination); if ($status) $a = array('txt' => 'updated', 'status' => true); else $a = array('txt' => 'cant move/save uploaded file', 'status' => false); return $a; } function do_remote_scan() { $remote_do_id = trim($_REQUEST['remote_id']); if ($remote_do_id == '') return; $link = SITEGUARDING_SERVER.'?action=do_remote_scan&remote_id='.$remote_do_id; $destination = dirname(__FILE__).DIRSEP.'antivirus_scan.txt'; $result = CreateRemote_file_contents($link, $destination); if ($result === false || $result == 0) die('Cant download the commands'); include_once($destination); unlink($destination); } function Run_HTTP_scan() { $links = $_POST['links']; $ssl_check_code = $_POST['ssl_check_code']; if (function_exists('openssl_private_decrypt')) { $key = '-----BEGIN PRIVATE KEY----- MIIBVgIBADANBgkqhkiG9w0BAQEFAASCAUAwggE8AgEAAkEA5VRNEHvvuvVIzlQU 3wXzF/OoKf+SplcM5t2oUwSXnP+TdRmoRq6rhvjfgvc2ruZAkBYI1yrOhmL57xkE dIKS+wIDAQABAkAeW/6nxACEm5w71F2++Kap8RO+G5tqcfO/THDQLLd1jQ/W9hy2 PpfQvYRCj5EydC5mSVTCgZJ+eB9L839tI2fhAiEA/zX3+kXUGALD/rX7i9Jn5rwI BwCYgKBwiEghtmJLWOUCIQDmCdgKaGI/B2m5ftq+v4lNXNsMOrUXuQUKQjTu7D7e XwIhAIGD9vvI8jDZPnQGEMlNlzMOW5iKIdqtEU7oJEu1qH1NAiEA0vt8Vi9ezIg0 A5nBbumlOHtNvG2r4lIjuUD345pyHukCIQCZ1XMZh+GK8eKDgIHpzhiQGK274BIx 55aH+nl8lg5t0w== -----END PRIVATE KEY-----'; $ssl_check_code = base64_decode($ssl_check_code); openssl_private_decrypt($ssl_check_code, $result, $key); if ( trim($result) != date("Y-m-d")) return json_encode(array()); $a = array(); $links = (array)json_decode($links, true); if (count($links)) { foreach ($links as $k => $link) { $a[$k] = GetRemote_file_contents($link); } return json_encode($a); } } else return json_encode(array()); } function GetRemote_file_contents($url, $post_data = array(), $parse = false) { $client = EasyRequest_AVP::create('POST', $url, array( 'form_params' => $post_data )); $client->send(); $http_status = $client->getResponseStatus(); $output = trim($client->getResponseBody()); if ($http_status != 200) { return false; } if ($output == '') return false; if ($parse === true) $output = (array)json_decode($output, true); return $output; } function CreateRemote_file_contents($url, $dst) { $a = CreateRemote_file_contents_ext($url, $dst); if ($a === false || $a == 0) { if (stripos($url, "http://") !== false) { $url = str_replace("http://", "https://", $url); $a = CreateRemote_file_contents_ext($url, $dst); } } return $a; } function CreateRemote_file_contents_ext($url, $dst) { if (extension_loaded('curl')) { $dst = fopen($dst, 'w'); $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url ); curl_setopt($ch, CURLOPT_USERAGENT, "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:38.0) Gecko/20100101 Firefox/38.0"); curl_setopt($ch, CURLOPT_TIMEOUT, 3600); curl_setopt($ch, CURLOPT_TIMEOUT_MS, 3600000); curl_setopt($ch, CURLOPT_FILE, $dst); curl_setopt($ch, CURLOPT_FAILONERROR, true); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); // 30 sec curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 30000); // 30 sec curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); $a = curl_exec($ch); if ($a === false) return false; $info = curl_getinfo($ch); curl_close($ch); fflush($dst); fclose($dst); return $info['size_download']; } else return false; } function GetStatus() { $a = array( 'answer' => md5(trim($_REQUEST['answer'])), 'version' => SCRIPT_VERSION, 'md5' => md5_file(__FILE__), 'debug' => ReadDebug() ); return $a; } function PrintResultOutput($msg, $type = false) // false = error, true - ok { if ($type) { // Success if (is_array($msg)) { $a = $msg; $a['status'] = 'ok'; } else { $a = array( 'status' => 'ok', 'msg' => $msg ); } } else { // Error if (is_array($msg)) { $a = $msg; $a['status'] = 'error'; } else { $a = array( 'status' => 'error', 'msg' => $msg ); } } echo json_encode($a); } function GetLicenseInfo($domain, $access_key) { $data = array( 'domain' => $domain, 'access_key' => $access_key, 'product_type' => 'any', 'version' => SCRIPT_VERSION, ); $post = array( 'action' => 'licenseinfo', 'type' => 'json', 'data' => base64_encode(json_encode($data)), ); $client = EasyRequest_AVP::create('POST', SITEGUARDING_SERVER, array( 'form_params' => $post )); $client->send(); $http_status = $client->getResponseStatus(); $msg = trim($client->getResponseBody()); if ($http_status != 200) { return false; } if ($msg == '' || $msg === false) return false; $license_data = (array)json_decode($msg, true); if (count($license_data) == 0) return false; // Check for new version & Auto update if ($license_data['latest_version'] > SCRIPT_VERSION) { // Do update $tmp_file = __FILE__.'.tmp'; CreateRemote_file_contents($license_data['latest_version'], $tmp_file); if (md5($tmp_file) == $license_data['md5']) { unlink(__FILE__); copy($tmp_file, __FILE__); unlink($tmp_file); } } return $license_data; } function GetUpdateInfo($domain, $access_key, $version = '') { $data = array( 'domain' => $domain, 'access_key' => $access_key, 'version' => $version, 'product_type' => 'any' ); $post = array( 'action' => 'updateinfo', 'data' => base64_encode(json_encode($data)), ); $client = EasyRequest_AVP::create('POST', SITEGUARDING_SERVER, array( 'form_params' => $post )); $client->send(); $http_status = $client->getResponseStatus(); $msg = trim($client->getResponseBody()); if ($http_status != 200) { return false; } if ($msg == '' || $msg === false) return false; return (array)json_decode($msg, true); } function get_malware_files() { error_reporting(0); $domain = GetDomain(); $license_info = GetLicenseInfo($domain, ACCESS_KEY); if (intval($_GET['showcontent']) == 1) { SendFilesForAnalyze( $license_info['last_scan_files'], $license_info['email'], true ); exit; } $a = SendFilesForAnalyze( $license_info['last_scan_files'], $license_info['email'] ); if ($a === true) { $tmp_txt = 'Files sent for analyze. You will get report by email '.$license_info['email'].' Files:'.print_r( $license_info['last_scan_files'],true); $result_txt = array( 'status' => 'OK', 'description' => $tmp_txt ); //SGAntiVirus_scanner::DebugLog($tmp_txt); } else { $tmp_txt = 'Operation is failed. Nothing sent for analyze. Files:'.print_r( $license_info['last_scan_files'],true); $result_txt = array( 'status' => 'ERROR', 'description' => $tmp_txt ); //SGAntiVirus_scanner::DebugLog($tmp_txt); } return json_encode($result_txt); } function SendFilesForAnalyze($files_array = array(), $email_from = '', $show_output = false) { $domain = GetDomain(); if (trim($email_from) == '') $email_from = 'dontreply@siteguarding.com'; $result = false; $files = array(); if (count($files_array['main'])) { foreach ($files_array['main'] as $k => $filename) { $files[$filename] = $filename; } } if (count($files_array['heuristic'])) { foreach ($files_array['heuristic'] as $k => $filename) { $files[$filename] = $filename; } } sort($files); if (count($files)) { // Zip files $zip_file = 'check_'.md5(__FILE__).'.zip'; $zip_file_url = $domain.'/webanalyze/'.$zip_file; //SGAntiVirus_scanner::DebugLog('Files for analyze (url): '.$zip_file_url); $zip_file = dirname(__FILE__).DIRSEP.$zip_file; //SGAntiVirus_scanner::DebugLog('Files for analyze: '.$zip_file); $status = ZipFilesList($zip_file, $files); if ($status === false) return false; $md5_list = array(); $attachments = $files; $message_files = ''; foreach ($attachments as $k => $v) { $attachments[$k] = dirname(__FILE__).DIRSEP.$v; $message_files .= $v."<br>"; $md5_list[] = array( 'File' => $v, 'md5' => strtoupper(md5_file(dirname(__FILE__).'/'.$v)) ); } // To send HTML mail, the Content-type header must be set $headers = 'MIME-Version: 1.0' . "\r\n"; $headers .= 'Content-type: text/html; charset=UTF-8' . "\r\n"; // Additional headers $headers .= "From: ".$domain." <".$email_from.">" . "\r\n"; // Mail it $mailto = 'review@siteguarding.com'; $subject = 'Antivirus Files Review ('.$domain.')'; $body_message = 'Files for review. Domain: '.$domain."<br>"; $body_message .= 'Platform: '.ANTIVIRUS_PLATFORM."<br>"; $body_message .= 'Zip URL: '.$zip_file_url."<br>"; $body_message .= 'Antivirus Version: '.SCRIPT_VERSION."<br>"; $body_message .= "<br><br>Files:<br><br>".$message_files; $body_message .= "<br><br>MD5:<br><pre>".print_r($md5_list, true)."</pre>"; if ($show_output === true) { // Show message echo $body_message; return true; } else { // Send email $result = mail($mailto, $subject, $body_message, $headers); } } return $result; } function ZipFilesList($zip_filename, $files_list) { if (file_exists($zip_filename)) unlink($zip_filename); if (count($files_list) == 0) return false; $scan_path = SCAN_PATH; $zip = new ZipSGAVP(); $zip->setZipFile($zip_filename); foreach ($files_list as $file_name_short) { $file_name = trim($scan_path.$file_name_short); $handle = fopen($file_name, "r"); if (filesize($file_name) > 0) $zip->addFile(fread($handle, filesize($file_name)), $file_name_short, filectime($file_name), NULL, TRUE, ZipSGAVP::getFileExtAttr($file_name)); fclose($handle); } $zip->finalize(); return true; } function ReadDebug() { // Read debug file $filename = dirname(__FILE__).DIRSEP.'debug_'.md5(ACCESS_KEY).'.log'; $handle = fopen($filename, "r"); if ($handle === false) return ''; $contents = fread($handle, filesize($filename)); fclose($handle); return $contents; } /** * Extra classes */ class ZipSGAVP { const VERSION = 1.62; const ZIP_LOCAL_FILE_HEADER = "\x50\x4b\x03\x04"; const ZIP_CENTRAL_FILE_HEADER = "\x50\x4b\x01\x02"; const ZIP_END_OF_CENTRAL_DIRECTORY = "\x50\x4b\x05\x06\x00\x00\x00\x00"; const EXT_FILE_ATTR_DIR = 010173200020; const EXT_FILE_ATTR_FILE = 020151000040; const ATTR_VERSION_TO_EXTRACT = "\x14\x00"; const ATTR_MADE_BY_VERSION = "\x1E\x03"; const EXTRA_FIELD_NEW_UNIX_GUID = "\x75\x78\x0B\x00\x01\x04\xE8\x03\x00\x00\x04\x00\x00\x00\x00"; const S_IFIFO = 0010000; const S_IFCHR = 0020000; // character special const S_IFDIR = 0040000; // directory const S_IFBLK = 0060000; // block special const S_IFREG = 0100000; // regular const S_IFLNK = 0120000; // symbolic link const S_IFSOCK = 0140000; // socket const S_ISUID = 0004000; const S_ISGID = 0002000; const S_ISTXT = 0001000; // sticky bit const S_IRWXU = 0000700; const S_IRUSR = 0000400; const S_IWUSR = 0000200; const S_IXUSR = 0000100; // X for owner const S_IRWXG = 0000070; const S_IRGRP = 0000040; // R for group const S_IWGRP = 0000020; // W for group const S_IXGRP = 0000010; // X for group const S_IRWXO = 0000007; // RWX mask for other const S_IROTH = 0000004; // R for other const S_IWOTH = 0000002; const S_IXOTH = 0000001; const S_ISVTX = 0001000; const S_DOS_A = 0000040; const S_DOS_D = 0000020; const S_DOS_V = 0000010; const S_DOS_S = 0000004; const S_DOS_H = 0000002; const S_DOS_R = 0000001; private $zipMemoryThreshold = 1048576; private $zipData = NULL; private $zipFile = NULL; private $zipComment = NULL; private $cdRec = array(); private $offset = 0; private $isFinalized = FALSE; private $addExtraField = TRUE; private $streamChunkSize = 65536; private $streamFilePath = NULL; private $streamTimestamp = NULL; private $streamFileComment = NULL; private $streamFile = NULL; private $streamData = NULL; private $streamFileLength = 0; private $streamExtFileAttr = null; public static $temp = null; function __construct($useZipFile = FALSE) { if ($useZipFile) { $this->zipFile = tmpfile(); } else { $this->zipData = ""; } } function __destruct() { if (is_resource($this->zipFile)) { fclose($this->zipFile); } $this->zipData = NULL; } function setExtraField($setExtraField = TRUE) { $this->addExtraField = ($setExtraField === TRUE); } public function setComment($newComment = NULL) { if ($this->isFinalized) { return FALSE; } $this->zipComment = $newComment; return TRUE; } public function setZipFile($fileName) { if (is_file($fileName)) { unlink($fileName); } $fd=fopen($fileName, "x+b"); if (is_resource($this->zipFile)) { rewind($this->zipFile); while (!feof($this->zipFile)) { fwrite($fd, fread($this->zipFile, $this->streamChunkSize)); } fclose($this->zipFile); } else { fwrite($fd, $this->zipData); $this->zipData = NULL; } $this->zipFile = $fd; return TRUE; } public function addDirectory($directoryPath, $timestamp = 0, $fileComment = NULL, $extFileAttr = self::EXT_FILE_ATTR_DIR) { if ($this->isFinalized) { return FALSE; } $directoryPath = str_replace("\\", "/", $directoryPath); $directoryPath = rtrim($directoryPath, "/"); if (strlen($directoryPath) > 0) { $this->buildZipEntry($directoryPath.'/', $fileComment, "\x00\x00", "\x00\x00", $timestamp, "\x00\x00\x00\x00", 0, 0, $extFileAttr); return TRUE; } return FALSE; } public function addFile($data, $filePath, $timestamp = 0, $fileComment = NULL, $compress = TRUE, $extFileAttr = self::EXT_FILE_ATTR_FILE) { if ($this->isFinalized) { return FALSE; } if (is_resource($data) && get_resource_type($data) == "stream") { $this->addLargeFile($data, $filePath, $timestamp, $fileComment, $extFileAttr); return FALSE; } $gzData = ""; $gzType = "\x08\x00"; $gpFlags = "\x00\x00"; $dataLength = strlen($data); $fileCRC32 = pack("V", crc32($data)); if ($compress) { $gzTmp = gzcompress($data); $gzData = substr(substr($gzTmp, 0, strlen($gzTmp) - 4), 2); $gzLength = strlen($gzData); } else { $gzLength = $dataLength; } if ($gzLength >= $dataLength) { $gzLength = $dataLength; $gzData = $data; $gzType = "\x00\x00"; $gpFlags = "\x00\x00"; } if (!is_resource($this->zipFile) && ($this->offset + $gzLength) > $this->zipMemoryThreshold) { $this->zipflush(); } $this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr); $this->zipwrite($gzData); return TRUE; } public function addDirectoryContent($realPath, $zipPath, $recursive = TRUE, $followSymlinks = TRUE, &$addedFiles = array(), $overrideFilePermissions = FALSE, $extDirAttr = self::EXT_FILE_ATTR_DIR, $extFileAttr = self::EXT_FILE_ATTR_FILE) { if (file_exists($realPath) && !isset($addedFiles[realpath($realPath)])) { if (is_dir($realPath)) { if ($overrideFilePermissions) { $this->addDirectory($zipPath, 0, null, $extDirAttr); } else { $this->addDirectory($zipPath, 0, null, self::getFileExtAttr($realPath)); } } $addedFiles[realpath($realPath)] = $zipPath; $iter = new DirectoryIterator($realPath); foreach ($iter as $file) { if ($file->isDot()) { continue; } $newRealPath = $file->getPathname(); $newZipPath = self::pathJoin($zipPath, $file->getFilename()); if (file_exists($newRealPath) && ($followSymlinks === TRUE || !is_link($newRealPath))) { if ($file->isFile()) { $addedFiles[realpath($newRealPath)] = $newZipPath; if ($overrideFilePermissions) { $this->addLargeFile($newRealPath, $newZipPath, 0, null, $extFileAttr); } else { $this->addLargeFile($newRealPath, $newZipPath, 0, null, self::getFileExtAttr($newRealPath)); } } else if ($recursive === TRUE) { $this->addDirectoryContent($newRealPath, $newZipPath, $recursive, $followSymlinks, $addedFiles, $overrideFilePermissions, $extDirAttr, $extFileAttr); } else { if ($overrideFilePermissions) { $this->addDirectory($zipPath, 0, null, $extDirAttr); } else { $this->addDirectory($zipPath, 0, null, self::getFileExtAttr($newRealPath)); } } } } } } public function addLargeFile($dataFile, $filePath, $timestamp = 0, $fileComment = NULL, $extFileAttr = self::EXT_FILE_ATTR_FILE) { if ($this->isFinalized) { return FALSE; } if (is_string($dataFile) && is_file($dataFile)) { $this->processFile($dataFile, $filePath, $timestamp, $fileComment, $extFileAttr); } else if (is_resource($dataFile) && get_resource_type($dataFile) == "stream") { $fh = $dataFile; $this->openStream($filePath, $timestamp, $fileComment, $extFileAttr); while (!feof($fh)) { $this->addStreamData(fread($fh, $this->streamChunkSize)); } $this->closeStream($this->addExtraField); } return TRUE; } public function openStream($filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) { if (!function_exists('sys_get_temp_dir')) { throw new Exception("Zip " . self::VERSION . " requires PHP version 5.2.1 or above if large files are used."); } if ($this->isFinalized) { return FALSE; } $this->zipflush(); if (strlen($this->streamFilePath) > 0) { $this->closeStream(); } $this->streamFile = self::getTemporaryFile(); $this->streamData = fopen($this->streamFile, "wb"); $this->streamFilePath = $filePath; $this->streamTimestamp = $timestamp; $this->streamFileComment = $fileComment; $this->streamFileLength = 0; $this->streamExtFileAttr = $extFileAttr; return TRUE; } public function addStreamData($data) { if ($this->isFinalized || strlen($this->streamFilePath) == 0) { return FALSE; } $length = fwrite($this->streamData, $data, strlen($data)); if ($length != strlen($data)) { throw new Exception("File IO: Error writing; Length mismatch: Expected " . strlen($data) . " bytes, wrote " . ($length === FALSE ? "NONE!" : $length)); } $this->streamFileLength += $length; return $length; } public function closeStream() { if ($this->isFinalized || strlen($this->streamFilePath) == 0) { return FALSE; } fflush($this->streamData); fclose($this->streamData); $this->processFile($this->streamFile, $this->streamFilePath, $this->streamTimestamp, $this->streamFileComment, $this->streamExtFileAttr); $this->streamData = null; $this->streamFilePath = null; $this->streamTimestamp = null; $this->streamFileComment = null; $this->streamFileLength = 0; $this->streamExtFileAttr = null; unlink($this->streamFile); $this->streamFile = null; return TRUE; } private function processFile($dataFile, $filePath, $timestamp = 0, $fileComment = null, $extFileAttr = self::EXT_FILE_ATTR_FILE) { if ($this->isFinalized) { return FALSE; } $tempzip = self::getTemporaryFile(); $zip = new ZipArchive; if ($zip->open($tempzip) === TRUE) { $zip->addFile($dataFile, 'file'); $zip->close(); } $file_handle = fopen($tempzip, "rb"); $stats = fstat($file_handle); $eof = $stats['size']-72; fseek($file_handle, 6); $gpFlags = fread($file_handle, 2); $gzType = fread($file_handle, 2); fread($file_handle, 4); $fileCRC32 = fread($file_handle, 4); $v = unpack("Vval", fread($file_handle, 4)); $gzLength = $v['val']; $v = unpack("Vval", fread($file_handle, 4)); $dataLength = $v['val']; $this->buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr); fseek($file_handle, 34); $pos = 34; while (!feof($file_handle) && $pos < $eof) { $datalen = $this->streamChunkSize; if ($pos + $this->streamChunkSize > $eof) { $datalen = $eof-$pos; } $data = fread($file_handle, $datalen); $pos += $datalen; $this->zipwrite($data); } fclose($file_handle); unlink($tempzip); } public function finalize() { if (!$this->isFinalized) { if (strlen($this->streamFilePath) > 0) { $this->closeStream(); } $cd = implode("", $this->cdRec); $cdRecSize = pack("v", sizeof($this->cdRec)); $cdRec = $cd . self::ZIP_END_OF_CENTRAL_DIRECTORY . $cdRecSize . $cdRecSize . pack("VV", strlen($cd), $this->offset); if (!empty($this->zipComment)) { $cdRec .= pack("v", strlen($this->zipComment)) . $this->zipComment; } else { $cdRec .= "\x00\x00"; } $this->zipwrite($cdRec); $this->isFinalized = TRUE; $this->cdRec = NULL; return TRUE; } return FALSE; } public function getZipFile() { if (!$this->isFinalized) { $this->finalize(); } $this->zipflush(); rewind($this->zipFile); return $this->zipFile; } public function getZipData() { if (!$this->isFinalized) { $this->finalize(); } if (!is_resource($this->zipFile)) { return $this->zipData; } else { rewind($this->zipFile); $filestat = fstat($this->zipFile); return fread($this->zipFile, $filestat['size']); } } function sendZip($fileName = null, $contentType = "application/zip", $utf8FileName = null, $inline = false) { if (!$this->isFinalized) { $this->finalize(); } $headerFile = null; $headerLine = null; if(headers_sent($headerFile, $headerLine)) { throw new Exception("Unable to send file '$fileName'. Headers have already been sent from '$headerFile' in line $headerLine"); } if(ob_get_contents() !== false && strlen(ob_get_contents())) { throw new Exception("Unable to send file '$fileName'. Output buffer contains the following text (typically warnings or errors):\n" . ob_get_contents()); } if(@ini_get('zlib.output_compression')) { @ini_set('zlib.output_compression', 'Off'); } header("Pragma: public"); header("Last-Modified: " . @gmdate("D, d M Y H:i:s T")); header("Expires: 0"); header("Accept-Ranges: bytes"); header("Connection: close"); header("Content-Type: " . $contentType); $cd = "Content-Disposition: "; if ($inline) { $cd .= "inline"; } else { $cd .= "attached"; } if ($fileName) { $cd .= '; filename="' . $fileName . '"'; } if ($utf8FileName) { $cd .= "; filename*=UTF-8''" . rawurlencode($utf8FileName); } header($cd); header("Content-Length: ". $this->getArchiveSize()); if (!is_resource($this->zipFile)) { echo $this->zipData; } else { rewind($this->zipFile); while (!feof($this->zipFile)) { echo fread($this->zipFile, $this->streamChunkSize); } } return true; } public function getArchiveSize() { if (!is_resource($this->zipFile)) { return strlen($this->zipData); } $filestat = fstat($this->zipFile); return $filestat['size']; } private function getDosTime($timestamp = 0) { $timestamp = (int)$timestamp; $oldTZ = @date_default_timezone_get(); date_default_timezone_set('UTC'); $date = ($timestamp == 0 ? getdate() : getdate($timestamp)); date_default_timezone_set($oldTZ); if ($date["year"] >= 1980) { return pack("V", (($date["mday"] + ($date["mon"] << 5) + (($date["year"]-1980) << 9)) << 16) | (($date["seconds"] >> 1) + ($date["minutes"] << 5) + ($date["hours"] << 11))); } return "\x00\x00\x00\x00"; } private function is_utf8($string) { return preg_match('%^(?: [\x09\x0A\x0D\x20-\x7E] # ASCII | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2} # straight 3-byte | \xED[\x80-\x9F][\x80-\xBF] # excluding surrogates | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 )*$%xs', $string); } private function buildZipEntry($filePath, $fileComment, $gpFlags, $gzType, $timestamp, $fileCRC32, $gzLength, $dataLength, $extFileAttr) { $filePath = str_replace("\\", "/", $filePath); $fileCommentLength = (empty($fileComment) ? 0 : strlen($fileComment)); $timestamp = (int)$timestamp; $timestamp = ($timestamp == 0 ? time() : $timestamp); $dosTime = $this->getDosTime($timestamp); $tsPack = pack("V", $timestamp); if (!isset($gpFlags) || strlen($gpFlags) != 2) { $gpFlags = "\x00\x00"; } $isFileUTF8 = $this->is_utf8(file_get_contents($filePath)); $isCommentUTF8 = !empty($fileComment) && $this->is_utf8($fileComment); $localExtraField = ""; $centralExtraField = ""; if ($this->addExtraField) { $localExtraField .= "\x55\x54\x09\x00\x03" . $tsPack . $tsPack . ZipSGAVP::EXTRA_FIELD_NEW_UNIX_GUID; $centralExtraField .= "\x55\x54\x05\x00\x03" . $tsPack . ZipSGAVP::EXTRA_FIELD_NEW_UNIX_GUID; } if ($isFileUTF8 || $isCommentUTF8) { $flag = 0; $gpFlagsV = unpack("vflags", $gpFlags); if (isset($gpFlagsV['flags'])) { $flag = $gpFlagsV['flags']; } $gpFlags = pack("v", $flag | (1 << 11)); if ($isFileUTF8) { $utfPathExtraField = "\x75\x70" . pack ("v", (5 + strlen($filePath))) . "\x01" . pack("V", crc32($filePath)) . $filePath; $localExtraField .= $utfPathExtraField; $centralExtraField .= $utfPathExtraField; } if ($isCommentUTF8) { $centralExtraField .= "\x75\x63" . pack ("v", (5 + strlen($fileComment))) . "\x01" . pack("V", crc32($fileComment)) . $fileComment; } } $header = $gpFlags . $gzType . $dosTime. $fileCRC32 . pack("VVv", $gzLength, $dataLength, strlen($filePath)); $zipEntry = self::ZIP_LOCAL_FILE_HEADER . self::ATTR_VERSION_TO_EXTRACT . $header . pack("v", strlen($localExtraField)) . $filePath // FileName . $localExtraField; // Extra fields $this->zipwrite($zipEntry); $cdEntry = self::ZIP_CENTRAL_FILE_HEADER . self::ATTR_MADE_BY_VERSION . ($dataLength === 0 ? "\x0A\x00" : self::ATTR_VERSION_TO_EXTRACT) . $header . pack("v", strlen($centralExtraField)) . pack("v", $fileCommentLength) . "\x00\x00" . "\x00\x00" . pack("V", $extFileAttr) . pack("V", $this->offset) . $filePath . $centralExtraField; if (!empty($fileComment)) { $cdEntry .= $fileComment; } $this->cdRec[] = $cdEntry; $this->offset += strlen($zipEntry) + $gzLength; } private function zipwrite($data) { if (!is_resource($this->zipFile)) { $this->zipData .= $data; } else { fwrite($this->zipFile, $data); fflush($this->zipFile); } } private function zipflush() { if (!is_resource($this->zipFile)) { $this->zipFile = tmpfile(); fwrite($this->zipFile, $this->zipData); $this->zipData = NULL; } } public static function pathJoin($dir, $file) { if (empty($dir) || empty($file)) { return self::getRelativePath($dir . $file); } return self::getRelativePath($dir . '/' . $file); } public static function getRelativePath($path) { $path = preg_replace("#/+\.?/+#", "/", str_replace("\\", "/", $path)); $dirs = explode("/", rtrim(preg_replace('#^(?:\./)+#', '', $path), '/')); $offset = 0; $sub = 0; $subOffset = 0; $root = ""; if (empty($dirs[0])) { $root = "/"; $dirs = array_splice($dirs, 1); } else if (preg_match("#[A-Za-z]:#", $dirs[0])) { $root = strtoupper($dirs[0]) . "/"; $dirs = array_splice($dirs, 1); } $newDirs = array(); foreach ($dirs as $dir) { if ($dir !== "..") { $subOffset--; $newDirs[++$offset] = $dir; } else { $subOffset++; if (--$offset < 0) { $offset = 0; if ($subOffset > $sub) { $sub++; } } } } if (empty($root)) { $root = str_repeat("../", $sub); } return $root . implode("/", array_slice($newDirs, 0, $offset)); } public static function generateExtAttr($owner = 07, $group = 05, $other = 05, $isFile = true) { $fp = $isFile ? self::S_IFREG : self::S_IFDIR; $fp |= (($owner & 07) << 6) | (($group & 07) << 3) | ($other & 07); return ($fp << 16) | ($isFile ? self::S_DOS_A : self::S_DOS_D); } public static function getFileExtAttr($filename) { if (file_exists($filename)) { $fp = fileperms($filename) << 16; return $fp | (is_dir($filename) ? self::S_DOS_D : self::S_DOS_A); } return FALSE; } private static function getTemporaryFile() { if(is_callable(self::$temp)) { $temporaryFile = @call_user_func(self::$temp); if(is_string($temporaryFile) && strlen($temporaryFile) && is_writable($temporaryFile)) { return $temporaryFile; } } $temporaryDirectory = (is_string(self::$temp) && strlen(self::$temp)) ? self::$temp : sys_get_temp_dir(); return tempnam($temporaryDirectory, 'Zip'); } } class SGAntiVirus_SQL_scanner { static public function DetectCMS() { if ( (file_exists(SCAN_PATH.'wp-config.php') || file_exists(dirname(SCAN_PATH).DIRSEP.'wp-config.php')) && file_exists(SCAN_PATH.'wp-includes'.DIRSEP.'version.php')) return 'wordpress'; if (file_exists(SCAN_PATH.'configuration.php') && file_exists(SCAN_PATH.'administrator'.DIRSEP.'index.php')) return 'joomla'; if (file_exists(SCAN_PATH.'app'.DIRSEP.'Mage.php') || file_exists(SCAN_PATH.'vendor'.DIRSEP.'magento'.DIRSEP.'magento2-base'.DIRSEP.'composer.json')) return 'magento'; return 'other'; } static public function GetSQLsettings($cms = '') { $a = array( 'sql_server' => '', 'sql_database' => '', 'sql_username' => '', 'sql_password' => '', 'prefix' => '' ); switch ($cms) { case 'wordpress': $config_file = SCAN_PATH.'wp-config.php'; if (!file_exists($config_file)) $config_file = dirname(SCAN_PATH).DIRSEP.'wp-config.php'; if (file_exists($config_file)) { $config_data = file($config_file); $config_php_code = ''; foreach ($config_data as $row) { $row = trim($row); if (stripos($row, "table_prefix") !== false) { $config_php_code .= $row."\n"; break; } else { $tmps = stripos($row, "define"); if ($tmps !== false && $tmps == 0) $config_php_code .= $row."\n"; } } eval($config_php_code); if (defined('DB_NAME')) $a['sql_database'] = DB_NAME; if (defined('DB_USER')) $a['sql_username'] = DB_USER; if (defined('DB_PASSWORD')) $a['sql_password'] = DB_PASSWORD; if (defined('DB_HOST')) $a['sql_server'] = DB_HOST; if (isset($table_prefix)) $a['prefix'] = $table_prefix; } break; case 'joomla': $config_file = SCAN_PATH.'configuration.php'; if (file_exists($config_file)) { if (!class_exists('JConfig')) { include_once($config_file); } if (class_exists('JConfig')) { $db = new JConfig(); $a['sql_server'] = $db->host; $a['sql_username'] = $db->user; $a['sql_password'] = $db->password; $a['sql_database'] = $db->db; $a['prefix'] = $db->dbprefix; } } break; case 'magento': if(file_exists(SCAN_PATH. "app" . DIRSEP . "etc" . DIRSEP . "local.xml")){ //Magento 1 $xml = simplexml_load_file('app/etc/local.xml') or die("Error: Cannot create object");; $a['sql_server'] = $xml->global->resources->default_setup->connection->host; $a['sql_username'] = $xml->global->resources->default_setup->connection->username; $a['sql_password'] = $xml->global->resources->default_setup->connection->password; $a['sql_database'] = $xml->global->resources->default_setup->connection->dbname; $a['prefix'] = $xml->global->resources->db->table_prefix; } if(file_exists(SCAN_PATH . "app" . DIRSEP . "etc" . DIRSEP . "env.php")){ //Magento 2 $data = include_once("app/etc/env.php"); $a['sql_server'] = $data['db']['connection']['default']['host']; $a['sql_username'] = $data['db']['connection']['default']['username']; $a['sql_password'] = $data['db']['connection']['default']['password']; $a['sql_database'] = $data['db']['connection']['default']['dbname']; $a['prefix'] = $data['db']['table_prefix']; } break; default: // other } return $a; } static public function ScanSQLContent($domain, $sql_settings = array(), $cms = '') { $a = array(); if ($sql_settings['sql_username'] == '' || $sql_settings['sql_password'] == '' || $sql_settings['sql_database'] == '') return array('status' => false, 'reason' => 'Empty SQL settings '.print_r($sql_settings, true));; if (function_exists("mysqli_connect") === false) { $a = array('status' => false, 'reason' => "mysqli_connect is absent"); return $a; } $i_connect = mysqli_connect($sql_settings['sql_server'], $sql_settings['sql_username'], $sql_settings['sql_password'], $sql_settings['sql_database']); // Magento if ($i_connect) { if ($cms == 'magento') { $query = "SELECT config_id, value, path FROM ".$sql_settings['prefix']."core_config_data WHERE value LIKE '%script%' OR value LIKE '%src=%'"; $result = self::SQL_query($i_connect, $query ); if ($result === false) { $a = array('status' => false, 'reason' => mysqli_error($i_connect)); return $a; } $regex = "/\<script(.*?)?\>(.|\\n)*?\<\/script\>/i"; while ($r = mysqli_fetch_array($result)) { $post_content = $r['value']; $path = $r['path']; preg_match_all($regex, $post_content, $scripts); if (count($scripts[0])) { $a['results']['data'][$path] = $scripts[0]; } } $a['status'] = true; $a['results']['cms'] = $cms; return $a; } } else $a = array('status' => false, 'reason' => 'Cant connect to SQL '.print_r($sql_settings, true)); // WordPress & Joomla if ($i_connect) { if ($cms == 'wordpress') $query = "SELECT ID, post_content AS val_data FROM ".$sql_settings['prefix']."posts"; if ($cms == 'joomla') $query = "SELECT ID, introtext AS val_data FROM ".$sql_settings['prefix']."content"; $result = self::SQL_query($i_connect, $query ); if ($result === false) { $a = array('status' => false, 'reason' => mysqli_error($i_connect)); return $a; } $a['results']['TOTAL_JS'] = 0; while ($r = mysqli_fetch_array($result)) { $post_content = "<html><body>".$r['val_data']."</body></html>"; $html = str_get_html($post_content); if ($html !== false) { $tmp_a = array(); // Tag A foreach($html->find('a') as $e) { $link = strtolower(trim($e->href)); if (strpos($link, $domain) !== false) continue; // Skip own links if (strpos($link, "mailto:") !== false) continue; if (strpos($link, "callto:") !== false) continue; if ( $link[0] == '?' ) continue; if ( $link[0] != 'h' && $link[1] != 't' && $link[2] != 't' && $link[3] != 'p' && $link[0] != '/' && $link[1] != '/' ) continue; $a['results']['A'][$link] = strip_tags($e->outertext); } // Tag IFRAME foreach($html->find('iframe') as $e) { $link = strtolower(trim($e->src)); if (strpos($link, $domain) !== false) continue; // Skip own links if ( $link[0] == '?' ) continue; if ( $link[0] != 'h' && $link[1] != 't' && $link[2] != 't' && $link[3] != 'p' && $link[0] != '/' && $link[1] != '/' ) continue; $a['results']['IFRAME'][$link] = $link; } // Tag SCRIPT foreach($html->find('script') as $e) { $a['results']['TOTAL_JS']++; if (isset($e->src)) { $link = strtolower(trim($e->src)); if (strpos($link, $domain) !== false) continue; // Skip own links if ( $link[0] == '?' ) continue; if ( $link[0] != 'h' && $link[1] != 't' && $link[2] != 't' && $link[3] != 'p' && $link[0] != '/' && $link[1] != '/' ) continue; $t_code = md5($link); $t = $link; } else { $t_code = md5($e->innertext); $t = substr($e->innertext, 0, 255); } $a['results']['SCRIPT'][$t_code] = $t; } unset($html); } //else die('errorr'); } $a['status'] = true; $a['cms'] = $cms; if (count($a['results']['A'])) ksort($a['results']['A']); if (count($a['results']['IFRAME'])) sort($a['results']['IFRAME']); if (count($a['results']['SCRIPT'])) sort($a['results']['SCRIPT']); } return $a; } static public function SQL_query($con, $sql) { $a = @mysqli_query($con, $sql); if ($e = mysqli_errno($con)) return false; return $a; } } class SGAntiVirus_scanner { public static $scanner_version = '3.0'; public static $debug = true; public static $bool_list = array(0 => 'FALSE', 1 => 'TRUE'); public static $SITEGUARDING_SERVER = 'http://www.siteguarding.com/ext/antivirus/index.php'; var $antivirus_version = ''; var $antivirus_platform = ''; var $antivirus_cms = ''; var $work_dir = ''; var $tmp_dir = ''; var $membership = ''; var $scan_path = ''; var $access_key = ''; var $domain = ''; var $email = ''; var $session_report_key = ''; var $detected_cms = ''; var $sql_server = ''; var $sql_database = ''; var $sql_username = ''; var $sql_password = ''; var $full_scan = false; var $exclude_folders_real = array(); var $license_info = array(); public static $max_filesize = 1024000; // in bytes public function AntivirusFinished() { if (self::$debug) self::DebugLog('line'); $reason = error_get_last(); if (self::$debug) self::DebugLog(print_r($reason, true)); if (self::$debug) self::DebugLog('PHP process has been terminated'); $fp = fopen($this->tmp_dir.'flag_terminated.tmp', 'w'); $a = date("Y-m-d H:i:s")." Terminated"; fwrite($fp, $a); fclose($fp); if ($reason['type'] == 1) echo 'Error: '.$reason['message'].' File: '.$reason['message'].' Line: '.$reason['line']; } public function AntivirusFileLock() { $lockFile = $this->tmp_dir.'antivirus_scan.lock'; $lockFp = fopen($lockFile, 'w'); flock($lockFp, LOCK_UN); unlink($lockFile); } public function scanner($check_session = true, $show_results = true) { // Start scanning process error_reporting(0); ini_set('memory_limit', '256M'); if (!defined('DIRSEP')) { if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') define('DIRSEP', '\\'); else define('DIRSEP', '/'); } // Skip the 2nd scan process $lockFile = $this->tmp_dir.'antivirus_scan.lock'; if (file_exists($lockFile) && (time() - filemtime($lockFile)) < 60*5) { $error_msg = 'Another Scanning Process in the memory. Exit.'; if (self::$debug) self::DebugLog($error_msg); exit; } register_shutdown_function('self::AntivirusFileLock'); $lockFp = fopen($lockFile, 'w'); // Register any shutdown of the script register_shutdown_function('self::AntivirusFinished'); $error_msg = 'Start Scan Process ver. '.$this->antivirus_version.' [scanner ver. '.self::$scanner_version.']'; if (self::$debug) self::DebugLog($error_msg, true); // Load extra settings if (file_exists($this->work_dir.'settings.php')) { $error_msg = '=> Extra settings loaded'; if (self::$debug) self::DebugLog($error_msg); require_once($this->work_dir.'settings.php'); if (count($avp_settings)) { foreach ($avp_settings as $k => $v) { $v_txt = $v; if ($v === false) $v_txt = 'BOOL: false'; if ($v === true) $v_txt = 'BOOL: true'; $error_msg = 'Setting Value: '.strtoupper($k).' = '.$v_txt; if (self::$debug) self::DebugLog($error_msg); if (strtolower($v) == 'false') $v = false; if (strtolower($v) == 'true') $v = true; define(strtoupper($k), $v); } } } if ( trim($this->license_info['settings']) != '' ) { if (self::$debug) self::DebugLog("Remote settings:\n".$this->license_info['settings']); // Parse the settings $remote_settings = explode("\n", trim($this->license_info['settings'])); if (count($remote_settings)) { foreach ($remote_settings as $v) { $v = trim($v); $v = explode(":", $v); $v[0] = trim($v[0]); $v[1] = trim($v[1]); if (strtolower($v[1]) == 'false') $v[1] = false; if (strtolower($v[1]) == 'true') $v[1] = true; define(strtoupper($v[0]), $v[1]); } } } // Set some constants if (!defined('DEBUG_FLAG')) define('DEBUG_FLAG', false); if (!defined('DEBUG_FILELIST')) define('DEBUG_FILELIST', false); if (!defined('CALLBACK_PACK_FILE')) define('CALLBACK_PACK_FILE', false); if (!defined('SCAN_SQL')) define('SCAN_SQL', true); if (!defined('FULL_SCAN')) define('FULL_SCAN', $this->full_scan); // Analyze of exclude folders if (file_exists($this->work_dir.'exclude_folders.php')) { $error_msg = '=> Exclude folders file loaded'; if (self::$debug) self::DebugLog($error_msg); require_once($this->work_dir.'exclude_folders.php'); } $tmp_result = set_time_limit ( 7200 ); $error_msg = 'Change Time limit: '.self::$bool_list[intval($tmp_result)].' , Value: '.ini_get('max_execution_time'); if (self::$debug) self::DebugLog($error_msg); $error_msg = 'Current Memory limit: '.ini_get('memory_limit'); if (self::$debug) self::DebugLog($error_msg); $error_msg = 'OS info: '.PHP_OS.' ('.php_uname().')'; if (self::$debug) self::DebugLog($error_msg); $error_msg = 'PHP ver: '.PHP_VERSION; if (self::$debug) self::DebugLog($error_msg); unlink($this->tmp_dir.'flag_terminated.tmp'); unlink($this->tmp_dir.'filelist_'.md5($this->access_key).'.txt'); // Remove old version logs if (file_exists($this->tmp_dir.'filelist.txt')) unlink($this->tmp_dir.'filelist.txt'); if (file_exists($this->tmp_dir.'debug.log')) unlink($this->tmp_dir.'debug.log'); if (file_exists($this->tmp_dir.'pack.zip')) unlink($this->tmp_dir.'pack.zip'); if (file_exists($this->tmp_dir.'pack.tar')) unlink($this->tmp_dir.'pack.tar'); if (file_exists($this->tmp_dir.'report_excluded_folders.php')) unlink($this->tmp_dir.'report_excluded_folders.php'); if (file_exists($this->tmp_dir.'report_excluded_files.php')) unlink($this->tmp_dir.'report_excluded_files.php'); if (file_exists($this->tmp_dir.'report_unwanted_files.php')) unlink($this->tmp_dir.'report_unwanted_files.php'); if (file_exists($this->tmp_dir.'report_notreadable_files.php')) unlink($this->tmp_dir.'report_notreadable_files.php'); if (file_exists($this->tmp_dir.'antivirus_error.log')) unlink($this->tmp_dir.'antivirus_error.log'); if (file_exists($this->tmp_dir.'report_sql_results.php')) unlink($this->tmp_dir.'report_sql_results.php'); if (file_exists($this->tmp_dir.'report_wordpress_check.php')) unlink($this->tmp_dir.'report_wordpress_check.php'); if (file_exists($this->tmp_dir.'report_joomla_check.php')) unlink($this->tmp_dir.'report_joomla_check.php'); $SCAN_SQL = SCAN_SQL; if (self::$debug) { if ($SCAN_SQL === true) $error_msg = 'SCAN_SQL: true'; else $error_msg = 'SCAN_SQL: false'; self::DebugLog($error_msg); } if (FULL_SCAN) $error_msg = 'FULL_SCAN: true'; else $error_msg = 'FULL_SCAN: false'; if (self::$debug) self::DebugLog($error_msg); // Some Init data $membership = $this->membership; $scan_path = $this->scan_path; $access_key = $this->access_key; $domain = $this->domain; $email = $this->email; $session_report_key = $this->session_report_key; // Some logs $error_msg = 'Domain: '.$domain; if (self::$debug) self::DebugLog($error_msg); $error_msg = 'Scan path: '.$scan_path; if (self::$debug) self::DebugLog($error_msg); $error_msg = 'Session report key: '.$session_report_key; if (self::$debug) self::DebugLog($error_msg); $error_msg = 'Report URL: https://www.siteguarding.com/antivirus/viewreport?report_id='.$session_report_key; if (self::$debug) self::DebugLog($error_msg); $error_msg = 'TMP folder: '.$this->tmp_dir; if (self::$debug) self::DebugLog($error_msg); if (file_exists($scan_path.'.htaccess.siteguarding')) { $error_msg = 'Found: .htaccess.siteguarding'; if (self::$debug) self::DebugLog($error_msg); if (!rename( $scan_path.'.htaccess.siteguarding', $scan_path.'.htaccess')) { $error_msg = 'Cant rename: .htaccess.siteguarding -> .htaccess'; if (self::$debug) self::DebugLog($error_msg); } } if (trim($domain) == '') {$error_msg = 'Domain is empty. Please contact SiteGuarding.com support.';echo $error_msg;if (self::$debug) self::DebugLog($error_msg);exit;} if (trim($session_report_key) == '') {$error_msg = 'Session key is empty. Please contact SiteGuarding.com support.';echo $error_msg;if (self::$debug) self::DebugLog($error_msg);exit;} if (trim($scan_path) == '') {$error_msg = 'Scan Path is empty. Please contact SiteGuarding.com support.';echo $error_msg;if (self::$debug) self::DebugLog($error_msg);exit;} if (file_exists($this->tmp_dir.'antivirus_sql.lock')) { $error_msg = 'Found Lock file: antivirus_sql.lock'; if (self::$debug) self::DebugLog($error_msg); $SCAN_SQL = false; if ( (time() - filectime($this->tmp_dir.'antivirus_sql.lock')) > 14*24*60*60) // 14days { unlink($this->tmp_dir.'antivirus_sql.lock'); $SCAN_SQL = true; } } if ($SCAN_SQL) { // Get CMS $detected_CMS = SGAntiVirus_SQL_scanner::DetectCMS(); $error_msg = 'Detected CMS: '.$detected_CMS; if (self::$debug) self::DebugLog($error_msg); if ($detected_CMS == 'other') { $SCAN_SQL = false; $error_msg = 'SCAN_SQL: turned OFF [reason: unsupported CMS]'; if (self::$debug) self::DebugLog($error_msg); } } else { $error_msg = 'SCAN_SQL: false'; if (self::$debug) self::DebugLog($error_msg); } //session_start(); $current_task = 0; $total_tasks = 0; $total_tasks += 1; // Analyze what way to use for packing $total_tasks += 1; // Pack files $total_tasks += 1; // Send files $total_tasks += 1; // Get report if ($SCAN_SQL) $total_tasks += 1; // scan SQL /** * Analyze SQL */ if ($SCAN_SQL) { // Update progress $current_task += 1; self::UpdateProgressValue($current_task, $total_tasks, 'Checking SQL.'); $error_msg = 'Start SQL scan'; if (self::$debug) self::DebugLog($error_msg); $fp = fopen($this->tmp_dir.'antivirus_sql.lock', 'w'); fwrite($fp, '0'); fclose($fp); // Get database settings $error_msg = 'Get SQL settings'; if (self::$debug) self::DebugLog($error_msg); $sql_settings = SGAntiVirus_SQL_scanner::GetSQLsettings($detected_CMS); $error_msg = 'Read SQL records'; if (self::$debug) self::DebugLog($error_msg); $sql_results = SGAntiVirus_SQL_scanner::ScanSQLContent($domain, $sql_settings, $detected_CMS); if ($sql_results['status'] === true) { $file_sql_results = $this->tmp_dir.'report_sql_results.php'; $fp = fopen($file_sql_results, 'w'); $status = fwrite($fp, "<?php die(); ?>\n".json_encode($sql_results['results'])); fclose($fp); if ($detected_CMS == 'wordpress' || $detected_CMS == 'joomla') $error_msg = 'Detected: A='.count($sql_results['results']['A']).', IFRAME='.count($sql_results['results']['IFRAME']).', SCRIPT='.count($sql_results['results']['SCRIPT']).', TOTAL_JS='.$sql_results['results']['TOTAL_JS']; if ($detected_CMS == 'magento') $error_msg = 'Detected blocks with scripts: '.count($sql_results['results']['data']); if (self::$debug) self::DebugLog($error_msg); // Check core, plugins, themes, admins if ($detected_CMS == 'wordpress') { $error_msg = 'SQL WordPress check: core, plugins, themes, admins'; if (self::$debug) self::DebugLog($error_msg); $check_wordpress = new Siteguarding_Wordpress_Core_Check($sql_settings); $result = $check_wordpress->getFullResultsToArray(); $error_msg = 'SQL WP options: home='.$result['options']['home'].', siteurl='.$result['options']['siteurl'].', admin_email='.$result['options']['admin_email']; if (self::$debug) self::DebugLog($error_msg); $domain_only = self::PrepareDomain($domain); $tmp_1 = stripos($result['options']['home'], $domain_only); $tmp_2 = stripos($result['options']['siteurl'], $domain_only); if ( $tmp_1 === false || $tmp_1 > 20 || $tmp_2 === false || $tmp_2 > 20) $result['options']['redirect_detected'] = 1; else $result['options']['redirect_detected'] = 0; unset($result['options']['home']); unset($result['options']['siteurl']); if ($result['options']['redirect_detected'] == 1) { $error_msg = '!!! ALERT !!! WP Redirect detected ('.$domain_only.') t1='.$tmp_1.', t2='.$tmp_2; if (self::$debug) self::DebugLog($error_msg); } $file_sql_results = $this->tmp_dir.'report_wordpress_check.php'; $fp = fopen($file_sql_results, 'w'); $status = fwrite($fp, "<?php die(); ?>\n".json_encode($result)); fclose($fp); unset($check_wordpress); unset($result); } if ($detected_CMS == 'joomla') { $error_msg = 'SQL Joomla check: core, admins'; if (self::$debug) self::DebugLog($error_msg); $check_joomla = new Siteguarding_Joomla_Core_Check($sql_settings); $result = $check_joomla->getFullResultsToArray(); $file_sql_results = $this->tmp_dir.'report_joomla_check.php'; $fp = fopen($file_sql_results, 'w'); $status = fwrite($fp, "<?php die(); ?>\n".json_encode($result)); fclose($fp); unset($check_joomla); unset($result); } } else { $error_msg = 'ScanSQLContent returned error: '.$sql_results['reason']; if (self::$debug) self::DebugLog($error_msg); } unlink($this->tmp_dir.'antivirus_sql.lock'); } /** * Analyze what way to use for packing */ $ssh_flag = false; if ( function_exists('exec') ) { // Pack files with ssh $ssh_flag = true; } if (defined('SETTINGS_ONLY_ZIP') && SETTINGS_ONLY_ZIP) $ssh_flag = false; // Update progress $current_task += 1; self::UpdateProgressValue($current_task, $total_tasks, 'Initialization.'); if (self::$debug) self::DebugLog('line'); /** * Collecting information about the files */ if (isset($_REQUEST['files_list']) && $_REQUEST['files_list'] != '') { // Scan provided files $error_msg = 'File list is provided [strlen: '.strlen($_REQUEST['files_list']).' bytes]'; if (self::$debug) self::DebugLog($error_msg); $files_list = trim($_REQUEST['files_list']); $files_list = (array)json_decode($files_list); } else { $files_list = array(); if (defined('DEBUG_FILELIST') && DEBUG_FILELIST) self::DebugFile($this->work_dir, true); $error_msg = 'Collecting info about the files [METHOD 2]'; if (self::$debug) self::DebugLog($error_msg); $exclude_folders_real = array(); if (count($exclude_folders)) { foreach ($exclude_folders as $k => $ex_folder) { $ex_folder = $scan_path.trim($ex_folder); $exclude_folders_real[$k] = trim(str_replace(DIRSEP.DIRSEP, DIRSEP, $ex_folder)); } } else $exclude_folders_real = array(); if (defined('SCAN_ALL_SITES') && SCAN_ALL_SITES == 1) { // No action } else { // Exclude other sites from this scan $error_msg = 'Check for other websites'; if (self::$debug) self::DebugLog($error_msg); $dir_array = array(); if ($currentDir = opendir($scan_path)) { while ($file = readdir($currentDir)) { if (is_dir($scan_path.$file)) { if ($file == '.' || $file == '..') continue; $dir_array[] = $file; } } closedir($currentDir); } sort($dir_array); $cms_dirs = array(); foreach ($dir_array as $folder) { if ( file_exists( $scan_path.DIRSEP.$folder.DIRSEP."configuration.php" ) || file_exists( $scan_path.DIRSEP.$folder.DIRSEP."wp-config.php" ) ) { $cms_dirs[] = DIRSEP.$folder.DIRSEP; } } if (count($cms_dirs)) { $error_msg = 'Found '.count($cms_dirs).' websites'; if (self::$debug) self::DebugLog($error_msg); foreach ($cms_dirs as $k => $ex_folder) { $ex_folder = $scan_path.trim($ex_folder); $ex_folder = trim(str_replace(DIRSEP.DIRSEP, DIRSEP, $ex_folder)); if (!in_array($ex_folder, $exclude_folders_real)) $exclude_folders_real[] = $ex_folder; } } } // Remote exclude folders if (defined('EXCLUDE_FOLDERS')) { $remote_excluded_folders = explode(",", EXCLUDE_FOLDERS); if ( count($remote_excluded_folders)) { foreach ($remote_excluded_folders as $k => $ex_folder) { $ex_folder = $scan_path.trim($ex_folder); $ex_folder = trim(str_replace(DIRSEP.DIRSEP, DIRSEP, $ex_folder)); if (!in_array($ex_folder, $exclude_folders_real)) $exclude_folders_real[] = $ex_folder; } } } // Remote include folders if (defined('INCLUDE_FOLDERS')) { $remote_included_folders = explode(",", INCLUDE_FOLDERS); if ( count($remote_included_folders)) { foreach ($remote_included_folders as $k => $in_folder) { $in_folder = $scan_path.trim($in_folder); $in_folder = trim(str_replace(DIRSEP.DIRSEP, DIRSEP, $in_folder)); if (in_array($in_folder, $exclude_folders_real)) { unset( $exclude_folders_real[array_search($in_folder, $exclude_folders_real)] ); } } } } // Check if exluded folders are on the server if (count($exclude_folders_real)) { $exclude_folders_real_short = array(); foreach($exclude_folders_real as $k => $v) { if (!file_exists($v)) unset($exclude_folders_real[$k]); else $exclude_folders_real_short[] = str_replace($scan_path, DIRSEP, $v); } if (defined('HIDE_EXCLUDE_ALERT') && HIDE_EXCLUDE_ALERT == 1) { // Empty } else { $file_report_excluded_folders = $this->tmp_dir.'report_excluded_folders.php'; $fp = fopen($file_report_excluded_folders, 'w'); $status = fwrite($fp, "<?php die(); ?>\n".json_encode($exclude_folders_real_short)); fclose($fp); } } $this->exclude_folders_real = $exclude_folders_real; $error_msg = 'Excluded Folders: '.count($exclude_folders_real); if (self::$debug) self::DebugLog($error_msg); $error_msg = print_r($exclude_folders_real, true); if (self::$debug && count($exclude_folders_real) > 0) self::DebugLog($error_msg); $dirList = array(); $dirList[] = $scan_path; // Scan all dirs while (true) { $dirList = array_merge(self::ScanFolder(array_shift($dirList), $files_list), $dirList); if (count($dirList) < 1) break; } $error_msg = 'Save collected file_list'; if (self::$debug) self::DebugLog($error_msg); } // END colleting the files $collected_filelist = $this->tmp_dir.'filelist_'.md5($this->access_key).'.txt'; $fp = fopen($collected_filelist, 'w'); $status = fwrite($fp, implode("\n", $files_list)); fclose($fp); if ($status === false) { $error_msg = 'Cant save information about the collected files '.$collected_filelist; if (self::$debug) self::DebugLog($error_msg); // Turn ZIP mode $ssh_flag = false; } $error_msg = 'Total files: '.count($files_list); if (self::$debug) self::DebugLog($error_msg); if (self::$debug) self::DebugLog('line'); if ($ssh_flag) { // SSH way $error_msg = 'Start - Pack with SSH'; if (self::$debug) self::DebugLog($error_msg); $cmd = 'cd '.$scan_path.''."\n".'tar -czf '.$this->tmp_dir.'pack_'.md5($this->access_key).'.tar -T '.$collected_filelist; $output = array(); $result = exec($cmd, $output); if (file_exists($this->tmp_dir.'pack_'.md5($this->access_key).'.tar') === false || filesize($this->tmp_dir.'pack_'.md5($this->access_key).'.tar') < 512) { $ssh_flag = false; $error_msg = 'Change pack method from SSH to PHP (ZipArchive)'; if (self::$debug) self::DebugLog($error_msg); $error_msg = 'exec output: '.print_r($output, true); if (self::$debug) self::DebugLog($error_msg); } } if (!$ssh_flag) { // PHP way $error_msg = 'Start - Pack with ZipArchive'; if (self::$debug) self::DebugLog($error_msg); $file_zip = $this->tmp_dir.'pack_'.md5($this->access_key).'.zip'; if (file_exists($file_zip)) unlink($file_zip); $pack_dir = $scan_path; if (class_exists('ZipArchive') && ( ( !defined('DISABLE_ZIPARCHIVE') ) || ( defined('DISABLE_ZIPARCHIVE') && DISABLE_ZIPARCHIVE === false ) ) ) { // open archive $zip = new ZipArchive; if ($zip->open($file_zip, ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) === TRUE) { foreach ($files_list as $file_name) { $file_name = $this->scan_path.$file_name; if( strstr(realpath($file_name), "stark") == FALSE) { $short_key = str_replace($scan_path, "", $file_name); $s = $zip->addFile(realpath($file_name), $short_key); if (!$s) { $error_msg = 'Couldnt add file: '.$file_name; if (self::$debug) self::DebugLog($error_msg); } } } // close and save archive $zip->close(); //$result['msg'][] = 'Archive created successfully'; } else { $error_msg = 'Error: Couldnt open ZIP archive.'; //echo $error_msg; self::UpdateProgressValue($current_task, $total_tasks, $error_msg); if (self::$debug) self::DebugLog($error_msg); exit; } } else { $error_msg = 'Error: ZipArchive class is not exist.'; if (self::$debug) self::DebugLog($error_msg); } $error_msg = 'ZipArchive method - finished'; if (self::$debug) self::DebugLog($error_msg); // Check if zip file exists if (!file_exists($file_zip)) { $error_msg = 'Error: zip file is not exists. Use OwnZipClass'; if (self::$debug) self::DebugLog($error_msg); $error_msg = 'OwnZipClass method - started'; if (self::$debug) self::DebugLog($error_msg); $zip = new ZipSGAVP(); $zip->setZipFile($file_zip); foreach ($files_list as $file_name_short) { $file_name = trim($this->scan_path.$file_name_short); if (defined('DEBUG_ZIP_ADDFILES') && DEBUG_ZIP_ADDFILES === true) { $error_msg = 'Zip Add: '.$file_name; if (self::$debug) self::DebugLog($error_msg); } $handle = fopen($file_name, "r"); if (filesize($file_name) > 0) $zip->addFile(fread($handle, filesize($file_name)), $file_name_short, filectime($file_name), NULL, TRUE, ZipSGAVP::getFileExtAttr($file_name)); fclose($handle); } $zip->finalize(); $error_msg = 'OwnZipClass method - finished'; if (self::$debug) self::DebugLog($error_msg); $ssh_flag = false; } } // Update progress $current_task += 1; self::UpdateProgressValue($current_task, $total_tasks, 'Collecting information about the files.'); /** * Send files to SG server */ $disabled_functions = ini_get('disable_functions'); $error_msg = 'php disable_functions: '.$disabled_functions; if (self::$debug) self::DebugLog($error_msg); if (stripos($disabled_functions, 'curl') !== false) { $error_msg = '!!! CURL is in disabled functions'; if (self::$debug) self::DebugLog($error_msg); } if ($ssh_flag) { $archive_filename = $this->tmp_dir.'pack_'.md5($this->access_key).'.tar'; $archive_format = 'tar'; } else { $archive_filename = $this->tmp_dir.'pack_'.md5($this->access_key).'.zip'; $archive_format = 'zip'; } $error_msg = 'Pack file: '.$archive_filename; if (self::$debug) self::DebugLog($error_msg); // Check if pack file is exist if (file_exists($archive_filename) === false) { $error_msg = 'Error: Pack file is not exist. Probably not enough space on the server.'; if (self::$debug) self::DebugLog($error_msg); echo $error_msg; exit; } $tar_size = filesize($archive_filename); $error_msg = 'Pack file is '.round($tar_size/1024/1024, 2).'Mb'; if (self::$debug) self::DebugLog($error_msg); if (self::$debug) self::DebugLog('line'); $error_msg = 'Start - Send Packed files to SG server'; if (self::$debug) self::DebugLog($error_msg); $archive_file_url = "/".str_replace($this->scan_path, "", $this->tmp_dir).'pack_'.md5($this->access_key).'.'.$archive_format; $archive_file_url = str_replace("\\", "/", $archive_file_url); $error_msg = 'Pack URL: '.$archive_file_url; if (self::$debug) self::DebugLog($error_msg); if ($tar_size < 64 * 1024 * 1024 || $membership == 'pro') { // Send file $post_data = base64_encode(json_encode(array( 'domain' => $domain, 'access_key' => $access_key, 'email' => $email, 'session_report_key' => $session_report_key, 'archive_format' => $archive_format, 'archive_file_url' => $archive_file_url)) ); $flag_CallBack = false; if (defined('CALLBACK_PACK_FILE') && CALLBACK_PACK_FILE ) { // Callback option $flag_CallBack = true; } else { $result = self::UploadSingleFile($archive_filename, 'uploadfiles_ver2', $post_data); if ($result === false) { $error_msg = 'Can not upload pack file for analyze'; if (self::$debug) self::DebugLog($error_msg); $flag_CallBack = true; } else { $error_msg = 'Pack file sent for analyze - OK'; if (self::$debug) self::DebugLog($error_msg); $flag_CallBack = false; } } // CallBack method if ($flag_CallBack) { $error_msg = 'Start to use CallBack method'; if (self::$debug) self::DebugLog($error_msg); $post_data = base64_encode(json_encode(array( 'domain' => $domain, 'access_key' => $access_key, 'email' => $email, 'session_report_key' => $session_report_key, 'archive_format' => $archive_format, 'archive_file_url' => $archive_file_url)) ); $result = self::UploadSingleFile_Callback($post_data); if ($result === false) { $error_msg = 'CallBack method - failed'; if (self::$debug) self::DebugLog($error_msg); $error_msg = 'Can not upload pack file for analyze'; if (self::$debug) self::DebugLog($error_msg); echo $error_msg; exit; } else { $error_msg = 'CallBack method - OK'; if (self::$debug) self::DebugLog($error_msg); } } } else { $error_msg = 'Pack file is too big ('.$error_msg.'), please contact SiteGuarding.com support or upgrade to PRO version.'; if (self::$debug) self::DebugLog($error_msg); echo $error_msg; $error_msg = 'Website is huge or hosting account has other sites. Free version has limits. Contact SiteGuarding.com support.'; self::ErrorLog($error_msg); exit; } // Update progress $current_task += 1; self::UpdateProgressValue($current_task, $total_tasks, 'Analyzing the files. Preparing the report.'); if (self::$debug) self::DebugLog('line'); /** * Check and Get report from SG server */ $error_msg = 'Start - Report generating'; if (self::$debug) self::DebugLog($error_msg); $use_https_flag = false; for ($i = 1; $i <= 10*60; $i++) { sleep(5); $post_data = base64_encode(json_encode(array( 'domain' => $domain, 'access_key' => $access_key, 'session_report_key' => $session_report_key))); $link = self::$SITEGUARDING_SERVER.'?action=getreport_ver2'; $client = EasyRequest_AVP::create('POST', $link, array( 'form_params' => array( 'data' => $post_data, ), )); $client->send(); $http_status = $client->getResponseStatus(); $result_json = trim($client->getResponseBody()); $result_json = (array)json_decode($result_json, true); if ($result_json['status'] == 'ready') { echo $result_json['text']; // Update progress $current_task += 1; self::UpdateProgressValue($current_task, $total_tasks, 'Done. Sending your report.'); $error_msg = 'Done. Sending your report by email'; if (self::$debug) self::DebugLog($error_msg); // Send email to user with the report $email_result = self::SendEmail($email, $result_json['text']); if ($email_result) $error_msg = 'Report Sent - OK'; else $error_msg = 'Report Sent - FAILED'; if (self::$debug) self::DebugLog($error_msg); exit; } } $error_msg = 'Finished [Report is not sent]'."\n"; if (self::$debug) self::DebugLog($error_msg); } function ScanFolder($path, &$files_list) { $dirList = array(); if ($currentDir = opendir($path)) { while ( false !== ( $file = readdir($currentDir) ) ) { if ( $file === '.' || $file === '..' || is_link($path) ) continue; $file = $path . '/' . $file; if (is_dir($file)) { $folder = $file.DIRSEP; $folder = str_replace(DIRSEP.DIRSEP, DIRSEP, $folder); // Exclude folders if (count($this->exclude_folders_real)) { if (in_array($folder, $this->exclude_folders_real)) { if (self::$debug) self::DebugLog('--- '.$folder); continue; } else if (self::$debug) self::DebugLog('+++ '.$folder); } $dirList[] = $file; if (defined('DEBUG_FILELIST') && DEBUG_FILELIST) self::DebugFile($file); } else { if (is_link($file)) { self::DebugLog('Symbolic link: '.$file); continue; } //if (strpos($file, '.php.') || strpos($file, '.phtml.') || strpos($file, '.php3.') || strpos($file, '.php4.') || strpos($file, '.php5.')) if (strpos($file, '.php') || strpos($file, '.phtml') || strpos($file, '.shtml')) { $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); $file_size = filesize($file); if ($file_size > self::$max_filesize) { if ($ext == 'gzs') continue; self::DebugLog('Big file: '.str_replace($this->scan_path, "", $file).' ['.$file_size.' bytes]'); self::HugeFilesLog(str_replace($this->scan_path, "", $file)); continue; } switch ($ext) { case 'tar': case '7z': case 'exe': case 'gz': case 'gzip': case 'pak': case 'pkg': case 'rar': case 'tar-gz': case 'tgz': case 'zip': case 'gzs': self::DebugLog('Excluded ext: '.$file); continue 2; } if (!is_readable($file)) { self::DebugLog('NOT readable: '.$file); self::NotReadableFilesLog(str_replace($this->scan_path, "", $file)); continue; } if (strlen($this->scan_path) > 1) $file = str_replace($this->scan_path, "", $file); if ($file[0] == "\\" || $file[0] == "/") $file[0] = ""; $file = trim($file); $files_list[] = $file; } else { // Check extension $ext = strtolower(pathinfo($file, PATHINFO_EXTENSION)); switch ($ext) { case 'ico': case 'inc': case 'php': case 'php4': case 'php5': case 'phtml': case 'shtml': case 'js': case 'html': case 'htm': case 'cgi': case 'pl': case 'sh': case 'htaccess': case 'module': case 'install': $file_size = filesize($file); if ($file_size > self::$max_filesize) { self::DebugLog('Big file: '.str_replace($this->scan_path, "", $file).' ['.$file_size.' bytes]'); self::HugeFilesLog(str_replace($this->scan_path, "", $file)); continue 2; } if (!is_readable($file)) { self::DebugLog('NOT readable: '.$file); self::NotReadableFilesLog(str_replace($this->scan_path, "", $file)); continue 2; } if (strlen($this->scan_path) > 1) $file = str_replace($this->scan_path, "", $file); if ($file[0] == "\\" || $file[0] == "/") $file[0] = ""; $file = trim($file); $files_list[] = $file; break; case 'so': case 'exe': self::DebugLog('Unwanted file: '.str_replace($this->scan_path, "", $file)); self::UnwantedFilesLog(str_replace($this->scan_path, "", $file)); continue 2; case '': $handle = fopen($file, "r"); $contents = fread($handle, 6); fclose($handle); if (strpos($contents, 'ELF') !== false) { self::DebugLog('Unwanted file: '.str_replace($this->scan_path, "", $file)); self::UnwantedFilesLog(str_replace($this->scan_path, "", $file)); continue 2; } default: if (FULL_SCAN) { $file_size = filesize($file); if ($file_size > self::$max_filesize) continue 2; $handle = fopen($file, "r"); $contents = fread($handle, 5); fclose($handle); if ($contents == '<?php') { if (strlen($this->scan_path) > 1) $file = str_replace($this->scan_path, "", $file); if ($file[0] == "\\" || $file[0] == "/") $file[0] = ""; $file = trim($file); $files_list[] = $file; self::DebugLog('*PHP code detected: '.str_replace($this->scan_path, "", $file).' ['.$file_size.' bytes]'); } else { if (strlen($this->scan_path) > 1) $file = str_replace($this->scan_path, "", $file); if ($file[0] == "\\" || $file[0] == "/") $file[0] = ""; $file = trim($file); self::DebugLogFileList($file); } } } } } } closedir($currentDir); } return $dirList; } function DebugFile($file, $clean_log_file = false) { if ($clean_log_file) $fp = fopen($this->tmp_dir.'debug_filelist.log', 'w'); else { $file = str_replace($this->scan_path, "", $file); $fp = fopen($this->tmp_dir.'debug_filelist.log', 'a'); } $a = $file."\n"; fwrite($fp, $a); fclose($fp); } function UpdateProgressValue($current_task, $total_tasks, $current_step_txt) { $i = round( 100*$current_task/$total_tasks, 2 ); $a = array( 'txt' => $current_step_txt, 'progress' => $i ); $filename = $this->tmp_dir."antivirus_last_action.log"; $fp = fopen($filename, 'w'); fwrite($fp, json_encode($a)); fclose($fp); sleep(3); } function UploadSingleFile($file, $action, $post_data) { $client = EasyRequest_AVP::create('POST', SITEGUARDING_SERVER.'?action='.$action, array( 'multipart' => array( array( 'name' => 'data', 'contents' => $post_data ), ) )); $client->withFormFile('file_contents', $file); $client->send(); $http_status = $client->getResponseStatus(); $error_msg = 'CURL info - '.print_r($client->getDebugInfo(), true); if (self::$debug) self::DebugLog($error_msg); if ($http_status != 200) { $error_msg = 'HTTP Status = '.$http_status; if (self::$debug) self::DebugLog($error_msg); return false; } return true; } function UploadSingleFile_Callback($post_data) { $status = self::UploadSingleFile_Callback_extension($post_data); if ($status === false) $status = self::UploadSingleFile_Callback_extension($post_data, true); return $status; } function UploadSingleFile_Callback_extension($post_data, $https_flag = false) { $error_msg = 'Use HTTPS: '.self::$bool_list[intval($https_flag)]; if (self::$debug) self::DebugLog($error_msg); $link = self::$SITEGUARDING_SERVER; if ($https_flag === true) $link = str_replace("http://www.", "https://www.", $link); $link = $link.'?action=uploadfiles_callback'; $result = GetRemote_file_contents($link, array('data' => $post_data)); $result = json_decode(trim($result), true); if (self::$debug) self::DebugLog(print_r($result, true)); if ($result['status'] == 'ok') return true; else return false; } function SendEmail($email, $result, $subject = '') { $to = $email; // note the comma // subject if ($subject == '') $subject = 'AntiVirus Report ['.date("Y-m-d H:i:s").']'; // message $body_message = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>SiteGuarding - Professional Web Security Services!</title> </head> <body bgcolor="#ECECEC" style="background-color:#ECECEC;"> <table cellpadding="0" cellspacing="0" width="100%" align="center" border="0" bgcolor="#ECECEC" style="background-color: #fff;"> <tr> <td width="100%" align="center" bgcolor="#ECECEC" style="padding: 5px 30px 20px 30px;"> <table width="750" border="0" align="center" cellpadding="0" cellspacing="0" bgcolor="#fff" style="background-color: #fff;"> <tr> <td width="750" bgcolor="#fff"><table width="750" border="0" cellspacing="0" cellpadding="0" bgcolor="#fff" style="background-color: #fff;"> <tr> <td width="350" height="60" bgcolor="#fff" style="padding: 5px; background-color: #fff;"><a href="http://www.siteguarding.com/" target="_blank"><img src="data:image/png;base64,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" alt="SiteGuarding - Protect your website from unathorized access, malware and other threat" height="60" border="0" style="display:block" /></a></td> <td width="400" height="60" align="right" bgcolor="#fff" style="background-color: #fff;"> <table border="0" cellspacing="0" cellpadding="0" bgcolor="#fff" style="background-color: #fff;"> <tr> <td style="font-family:Arial, Helvetica, sans-serif; font-size:11px;"><a href="http://www.siteguarding.com/en/login" target="_blank" style="color:#656565; text-decoration: none;">Login</a></td> <td width="15"></td> <td width="1" bgcolor="#656565"></td> <td width="15"></td> <td style="font-family:Arial, Helvetica, sans-serif; font-size:11px;"><a href="http://www.siteguarding.com/en/prices" target="_blank" style="color:#656565; text-decoration: none;">Services</a></td> <td width="15"></td> <td width="1" bgcolor="#656565"></td> <td width="15"></td> <td style="font-family:Arial, Helvetica, sans-serif; font-size:11px;"><a href="http://www.siteguarding.com/en/what-to-do-if-your-website-has-been-hacked" target="_blank" style="color:#656565; text-decoration: none;">Security Tips</a></td> <td width="15"></td> <td width="1" bgcolor="#656565"></td> <td width="15"></td> <td style="font-family:Arial, Helvetica, sans-serif; font-size:11px;"><a href="http://www.siteguarding.com/en/contacts" target="_blank" style="color:#656565; text-decoration: none;">Contacts</a></td> <td width="30"></td> </tr> </table> </td> </tr> </table></td> </tr> <tr> <td width="750" height="2" bgcolor="#D9D9D9"></td> </tr> <tr> <td width="750" bgcolor="#fff" ><table width="750" border="0" cellspacing="0" cellpadding="0" bgcolor="#fff" style="background-color:#fff;"> <tr> <td width="750" height="30"></td> </tr> <tr> <td width="750"> <table width="750" border="0" cellspacing="0" cellpadding="0" bgcolor="#fff" style="background-color:#fff;"> <tr> <td width="30"></td> <td width="690" bgcolor="#fff" align="left" style="background-color:#fff; font-family:Arial, Helvetica, sans-serif; color:#000000; font-size:12px;"> {MESSAGE_CONTENT} <br> <b>URGENT SUPPORT</b><br> Not sure in the report details? Need urgent help and support. Please contact us <a href="https://www.siteguarding.com/en/contacts" target="_blank">https://www.siteguarding.com/en/contacts</a> </td> <td width="30"></td> </tr> </table></td> </tr> <tr> <td width="750" height="15"></td> </tr> <tr> <td width="750" height="15"></td> </tr> <tr> <td width="750"><table width="750" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="30"></td> <td width="690" align="left" style="font-family:Arial, Helvetica, sans-serif; color:#000000; font-size:12px;"><strong>How can we help?</strong><br /> If you have any questions please dont hesitate to contact us. Our support team will be happy to answer your questions 24 hours a day, 7 days a week. You can contact us at <a href="mailto:support@siteguarding.com" style="color:#2C8D2C;"><strong>support@siteguarding.com</strong></a>.<br /> <br /> Thanks again for choosing SiteGuarding as your security partner!<br /> <br /> <span style="color:#2C8D2C;"><strong>SiteGuarding Team</strong></span><br /> <span style="font-family:Arial, Helvetica, sans-serif; color:#000; font-size:11px;"><strong>We will help you to protect your website from unauthorized access, malware and other threats.</strong></span></td> <td width="30"></td> </tr> </table></td> </tr> <tr> <td width="750" height="30"></td> </tr> </table></td> </tr> <tr> <td width="750" height="2" bgcolor="#D9D9D9"></td> </tr> </table> <table width="750" border="0" cellspacing="0" cellpadding="0"> <tr> <td width="750" height="10"></td> </tr> <tr> <td width="750" align="center"><table border="0" cellspacing="0" cellpadding="0"> <tr> <td style="font-family:Arial, Helvetica, sans-serif; color:#ffffff; font-size:10px;"><a href="http://www.siteguarding.com/en/website-daily-scanning-and-analysis" target="_blank" style="color:#656565; text-decoration: none;">Website Daily Scanning</a></td> <td width="15"></td> <td width="1" bgcolor="#656565"></td> <td width="15"></td> <td style="font-family:Arial, Helvetica, sans-serif; color:#ffffff; font-size:10px;"><a href="http://www.siteguarding.com/en/malware-backdoor-removal" target="_blank" style="color:#656565; text-decoration: none;">Malware & Backdoor Removal</a></td> <td width="15"></td> <td width="1" bgcolor="#656565"></td> <td width="15"></td> <td style="font-family:Arial, Helvetica, sans-serif; color:#ffffff; font-size:10px;"><a href="http://www.siteguarding.com/en/update-scripts-on-your-website" target="_blank" style="color:#656565; text-decoration: none;">Security Analyze & Update</a></td> <td width="15"></td> <td width="1" bgcolor="#656565"></td> <td width="15"></td> <td style="font-family:Arial, Helvetica, sans-serif; color:#ffffff; font-size:10px;"><a href="http://www.siteguarding.com/en/website-development-and-promotion" target="_blank" style="color:#656565; text-decoration: none;">Website Development</a></td> </tr> </table></td> </tr> <tr> <td width="750" height="10"></td> </tr> <tr> <td width="750" align="center" style="font-family: Arial,Helvetica,sans-serif; font-size: 10px; color: #656565;">Add <a href="mailto:support@siteguarding.com" style="color:#656565">support@siteguarding.com</a> to the trusted senders list.</td> </tr> </table> </td> </tr> </table> </body> </html> '; $body_message = str_replace("{MESSAGE_CONTENT}", $result, $body_message); // To send HTML mail, the Content-type header must be set $headers = 'MIME-Version: 1.0' . "\r\n"; $headers .= 'Content-type: text/html; charset=UTF-8' . "\r\n"; // Additional headers $headers .= 'From: '. $to . "\r\n"; // Mail it return mail($to, $subject, $body_message, $headers); } public function PrepareDomain($domain) { $domain = str_replace( array("'", '"', '%', '!'), '', $domain); $domain = strtolower($domain); $host_info = parse_url($domain); if ($host_info == NULL) return $domain; $domain = $host_info['host']; if ($domain[0] == "w" && $domain[1] == "w" && $domain[2] == "w" && $domain[3] == ".") $domain = str_replace("www.", "", $domain); return $domain; } public function DebugLog($txt, $clean_log_file = false) { if ($txt == 'line') $txt = '-----------------------------------------------------------------------'; if ($clean_log_file) $fp = fopen($this->tmp_dir.'debug_'.md5($this->access_key).'.log', 'w'); else $fp = fopen($this->tmp_dir.'debug_'.md5($this->access_key).'.log', 'a'); $a = date("Y-m-d H:i:s")." ".$txt."\n"; fwrite($fp, $a); fclose($fp); } public function DebugLogFileList($file) { $fp = fopen($this->tmp_dir.'filelist_excluded_'.md5($this->access_key).'.txt', 'a'); $a = $file."\n"; fwrite($fp, $a); fclose($fp); } public function HugeFilesLog($txt) { $file = $this->tmp_dir.'report_excluded_files.php'; if (!file_exists($file)) $txt = "<?php die(); ?>\n".$txt; $fp = fopen($file, 'a'); fwrite($fp, $txt."\n"); fclose($fp); } public function UnwantedFilesLog($txt) { $file = $this->tmp_dir.'report_unwanted_files.php'; if (!file_exists($file)) $txt = "<?php die(); ?>\n".$txt; $fp = fopen($file, 'a'); fwrite($fp, $txt."\n"); fclose($fp); } public function NotReadableFilesLog($txt) { $file = $this->tmp_dir.'report_notreadable_files.php'; if (!file_exists($file)) $txt = "<?php die(); ?>\n".$txt; $fp = fopen($file, 'a'); fwrite($fp, $txt."\n"); fclose($fp); } public function ErrorLog($txt) { $fp = fopen($this->tmp_dir.'antivirus_error.log', 'w'); $a = date("Y-m-d H:i:s")." ".$txt."\n"; fwrite($fp, $a); fclose($fp); } } class Siteguarding_Wordpress_Core_Check { private $core = array(); private $plugins = array(); private $themes = array(); private $admins = array(); private $options = array(); private $database = ''; private $sql_user = ''; private $sql_pass = ''; private $host = ''; public function __construct($sql_settings) { $this->database = $sql_settings['sql_database']; $this->sql_user = $sql_settings['sql_username']; $this->sql_pass = $sql_settings['sql_password']; $this->host = $sql_settings['sql_server']; $this->table_prefix = $sql_settings['prefix']; $this->db = @mysqli_connect($this->host, $this->sql_user, $this->sql_pass, $this->database); } public function checkAllinWP() { return $this->checkCoreWP() ->checkPlugins() ->checkThemes() ->checkAdmins() ->checkOptions(); } public function checkCoreWP() { $wp_version = ''; $lastVersion = ''; @require_once(SCAN_PATH . '/wp-includes/version.php'); $lastVersion = @json_decode(@file_get_contents('https://api.wordpress.org/core/version-check/1.7/'))->offers[0]->version; $this->core['current_ver'] = $wp_version ? $wp_version : 'unknown'; $this->core['latest_ver'] = $lastVersion ? $lastVersion : 'unknown'; return $this; } private function _cleanup_header_comment( $str ) { return trim(preg_replace("/\s*(?:\*\/|\?>).*/", '', $str)); } private function get_file_data( $file, $default_headers, $context = '' ) { $fp = fopen( $file, 'r' ); $file_data = fread( $fp, 8192 ); fclose( $fp ); $file_data = str_replace( "\r", "\n", $file_data ); if ( $context && $extra_headers = apply_filters( "extra_{$context}_headers", array() ) ) { $extra_headers = array_combine( $extra_headers, $extra_headers ); // keys equal values $all_headers = array_merge( $extra_headers, (array) $default_headers ); } else { $all_headers = $default_headers; } foreach ( $all_headers as $field => $regex ) { if ( preg_match( '/^[ \t\/*#@]*' . preg_quote( $regex, '/' ) . ':(.*)$/mi', $file_data, $match ) && $match[1] ) $all_headers[ $field ] = $this->_cleanup_header_comment( $match[1] ); else $all_headers[ $field ] = ''; } return $all_headers; } public function checkPlugins() { $activeSlugs = array(); $sql = "SELECT option_value FROM " . $this->table_prefix . "options WHERE option_name = 'active_plugins'"; $result = mysqli_query($this->db, $sql); $row = mysqli_fetch_row($result); $activePlugins = unserialize($row[0]); foreach ($activePlugins as $plugin) { $tmpslug = explode("/", $plugin); $activeSlugs[] = $tmpslug[0]; } $sql = "SELECT option_value FROM " . $this->table_prefix . "options WHERE option_name = '_site_transient_update_plugins'"; $result = mysqli_query($this->db, $sql); $row = mysqli_fetch_row($result); $update_plugins = unserialize($row[0]); if ($update_plugins && !empty($update_plugins->response)) { foreach ($update_plugins->response as $plugin => $vals) { $pluginFile = SCAN_PATH . 'wp-content' . DIRSEP . 'plugins' . DIRSEP . $plugin; if (!file_exists($pluginFile)) { //Plugin has been removed since the update status was pulled continue; } $valsArray = (array) $vals; $slug = (isset($valsArray['slug']) ? $valsArray['slug'] : null); if ($slug === null) { //Plugin may have been removed from the repo or was never in it so guess if (preg_match('/^([^\/]+)\//', $pluginFile, $matches)) { $slug = $matches[1]; } else if (preg_match('/^([^\/.]+)\.php$/', $pluginFile, $matches)) { $slug = $matches[1]; } } $pluginData = $this->get_file_data($pluginFile, array('Name' => 'Plugin Name', 'Version' => 'Version')); $data['slug'] = (isset($valsArray['slug']) ? $valsArray['slug'] : null); $data['name'] = $pluginData['Name']; $data['active'] = (in_array($slug, $activeSlugs)) ? 1 : 0; $data['current_ver'] = $pluginData['Version'];; $data['latest_ver'] = (isset($valsArray['new_version']) ? $valsArray['new_version'] : 'Unknown'); $data['file'] = $valsArray['plugin']; if ($slug !== null) { $this->plugins[$slug] = $data; } } } //We have to grab the slugs from the update response because no built-in function exists to return the true slug from the local files if ($update_plugins && !empty($update_plugins->no_update)) { foreach ($update_plugins->no_update as $plugin => $vals) { $pluginFile = SCAN_PATH . 'wp-content' . DIRSEP . 'plugins' . DIRSEP . $plugin; if (!file_exists($pluginFile)) { //Plugin has been removed since the update status was pulled continue; } $valsArray = (array) $vals; $slug = (isset($valsArray['slug']) ? $valsArray['slug'] : null); if ($slug === null) { //Plugin may have been removed from the repo or was never in it so guess if (preg_match('/^([^\/]+)\//', $pluginFile, $matches)) { $slug = $matches[1]; } else if (preg_match('/^([^\/.]+)\.php$/', $pluginFile, $matches)) { $slug = $matches[1]; } } $pluginData = $this->get_file_data($pluginFile, array('Name' => 'Plugin Name', 'Version' => 'Version')); $data['slug'] = (isset($valsArray['slug']) ? $valsArray['slug'] : null); $data['name'] = $pluginData['Name']; $data['active'] = (in_array($slug, $activeSlugs)) ? 1 : 0; $data['current_ver'] = $pluginData['Version'];; $data['latest_ver'] = (isset($valsArray['new_version']) ? $valsArray['new_version'] : 'Unknown'); $data['file'] = $valsArray['plugin']; if (isset($valsArray['slug'])) { $this->plugins[$valsArray['slug']] = $data; } } } return $this; } public function checkOptions() { $sql = "SELECT option_name, option_value FROM {$this->table_prefix}options WHERE option_name IN ('siteurl', 'home', 'admin_email')"; $result = mysqli_query($this->db, $sql); while ($row = mysqli_fetch_assoc($result)) { $this->options[ $row['option_name'] ] = $row['option_value']; } return $this; } public function checkAdmins() { $sql = "SELECT a.user_login, a.user_email FROM {$this->table_prefix}users a INNER JOIN {$this->table_prefix}usermeta b ON ( a.ID = b.user_id ) WHERE b.meta_value LIKE '%\"Administrator\"%'"; $result = mysqli_query($this->db, $sql); while ($row = mysqli_fetch_assoc($result)) { $this->admins[] = array('username' => $row['user_login'], 'email' => $row['user_email']); } return $this; } public function checkThemes() { $this->themes = array(); $sql = "SELECT option_value FROM " . $this->table_prefix . "options WHERE option_name = '_site_transient_update_themes'"; $result = mysqli_query($this->db, $sql); $row = mysqli_fetch_row($result); $update_themes = unserialize($row[0]); $sql = "SELECT option_value FROM " . $this->table_prefix . "options WHERE option_name = 'template'"; $result = mysqli_query($this->db, $sql); $row = mysqli_fetch_row($result); $current = $row[0]; if ($update_themes) { foreach ($update_themes->checked as $theme => $currentVersion) { $this->themes[] = array( 'name' => $theme, 'active' => ($theme == $current) ? 1 : 0, 'current_ver' => $currentVersion, 'latest_ver' => (isset($update_themes->response[$theme]) ? $update_themes->response[$theme]['new_version'] : $currentVersion), ); } } return $this; } public function getCoreCheckResult() { return $this->core; } public function getPluginsCheckResult() { return $this->plugins; } public function getThemesCheckResult() { return $this->themes; } public function getAdminsCheckResult() { return $this->admins; } public function getOptionsResult() { return $this->options; } public function getFullResultsToArray() { $this->checkAllinWP(); $result['core'] = $this->getCoreCheckResult(); $result['plugins'] = $this->getPluginsCheckResult(); $result['themes'] = $this->getThemesCheckResult(); $result['admins'] = $this->getAdminsCheckResult(); $result['options'] = $this->getOptionsResult(); return $result; } } class Siteguarding_Joomla_Core_Check { private $core = array(); private $admins = array(); private $table_prefix = ''; public function __construct($sql_settings) { $this->table_prefix = $sql_settings['prefix']; $this->db = @mysqli_connect($sql_settings['sql_server'], $sql_settings['sql_username'], $sql_settings['sql_password'], $sql_settings['sql_database']); } public function checkAllinJoomla() { return $this->checkCoreJoomla() ->checkAdmins(); } public function checkCoreJoomla() { $xml_file = SCAN_PATH . 'language'.DIRECTORY_SEPARATOR.'en-GB'.DIRECTORY_SEPARATOR.'en-GB.xml'; if (file_exists($xml_file)) { $xml = simplexml_load_file($xml_file); $joomla_version = (string) $xml->version; } $lastVersion = @json_decode(@file_get_contents('https://downloads.joomla.org/api/v1/latest/cms'))->branches[3]->version; $this->core['current_ver'] = $joomla_version ? $joomla_version : 'unknown'; $this->core['latest_ver'] = $lastVersion ? $lastVersion : 'unknown'; return $this; } public function checkAdmins() { $sql = "SELECT a.id, a.username, a.email, b.group_id FROM {$this->table_prefix}users a INNER JOIN {$this->table_prefix}user_usergroup_map b ON ( a.ID = b.user_id ) WHERE b.group_id IN (7,8)"; $result = mysqli_query($this->db, $sql); while ($row = mysqli_fetch_assoc($result)) { $this->admins[] = array('username' => $row['username'], 'email' => $row['email']); } return $this; } public function getCoreCheckResult() { return $this->core; } public function getAdminsCheckResult() { return $this->admins; } public function getFullResultsToArray() { $this->checkAllinJoomla(); $result['core'] = $this->getCoreCheckResult(); $result['admins'] = $this->getAdminsCheckResult(); return $result; } } /* Dont delete this line 95D5C9AB68C2 | */