PageRenderTime 44ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/wp-security-scan/res/inc/WsdLiveTraffic.php

https://gitlab.com/edgarze188/sunrise
PHP | 330 lines | 257 code | 49 blank | 24 comment | 63 complexity | a8757aa05f9d07a924c30e171579203a MD5 | raw file
  1. <?php if(! defined('WPS_PLUGIN_PREFIX')) return;
  2. /**
  3. * Class WsdLiveTraffic
  4. */
  5. class WsdLiveTraffic
  6. {
  7. private function __construct(){}
  8. private function __clone(){}
  9. final public static function clearEvents()
  10. {
  11. wssLog(__METHOD__."() triggered.");
  12. global $wpdb;
  13. $settings = WsdPlugin::getSettings();
  14. $keepMaxEntries = (int)WpsOption::getOption('WPS_KEEP_NUM_ENTRIES_LT');
  15. if($keepMaxEntries < 1){
  16. $query = "TRUNCATE ".WsdPlugin::getTableName(WpsSettings::LIVE_TRAFFIC_TABLE_NAME);
  17. $result = $wpdb->query($query);
  18. wssLog("Deleting live traffic entries.", array('query'=>$query, 'result'=>$result));
  19. return;
  20. }
  21. $optData = WpsOption::getOption(WpsSettings::LIVE_TRAFFIC_ENTRIES);
  22. if(empty($optData)){
  23. wssLog("Option (".WpsSettings::LIVE_TRAFFIC_ENTRIES.") not found.");
  24. return;
  25. }
  26. $numEntries = $wpdb->get_var("SELECT COUNT(entryId) FROM ".WsdPlugin::getTableName(WpsSettings::LIVE_TRAFFIC_TABLE_NAME));
  27. if($numEntries <> $keepMaxEntries){
  28. WpsOption::updateOption(WpsSettings::LIVE_TRAFFIC_ENTRIES, $numEntries);
  29. }
  30. if(intval($optData) <= $keepMaxEntries){
  31. return;
  32. }
  33. $tableName = WsdPlugin::getTableName(WpsSettings::LIVE_TRAFFIC_TABLE_NAME);
  34. $querySelect = "SELECT min(t.entryTime)
  35. FROM
  36. (
  37. SELECT
  38. entryTime
  39. FROM
  40. ".$tableName."
  41. ORDER BY
  42. entryTime DESC
  43. LIMIT ".$keepMaxEntries."
  44. ) AS t";
  45. $deleteFromTime = $wpdb->get_var($querySelect);
  46. $queryDelete = "DELETE FROM ".$tableName." WHERE entryTime < %s";
  47. $result = $wpdb->query($wpdb->prepare($queryDelete,$deleteFromTime));
  48. wssLog("Deleting live traffic entries.", array('query'=>"DELETE FROM $tableName WHERE entryTime < $deleteFromTime", 'deleted'=>$result));
  49. if(false === $result){
  50. return;
  51. }
  52. // update option
  53. $numEntries = $wpdb->get_var("SELECT COUNT(entryId) FROM ".WsdPlugin::getTableName(WpsSettings::LIVE_TRAFFIC_TABLE_NAME));
  54. WpsOption::updateOption(WpsSettings::LIVE_TRAFFIC_ENTRIES, $numEntries);
  55. }
  56. final public static function registerHit()
  57. {
  58. // check if live traffic tool is enabled
  59. $liveTrafficToolEnabled = WpsOption::getOption(WpsSettings::ENABLE_LIVE_TRAFFIC);
  60. if(! $liveTrafficToolEnabled){
  61. return;
  62. }
  63. if(is_admin()){ return; }
  64. global $wpdb;
  65. $blogID = $wpdb->blogid;
  66. $url = self::getRequestedUrl();
  67. if(self::isUrlExcluded($url)){ return; }
  68. $ip = self::getIP();
  69. $referrer = self::getReferrer();
  70. $ua = self::getUserAgent();
  71. $geoIpInfo = self::_getGeoIpInfo($ip);
  72. $country = $geoIpInfo['country'];
  73. $city = $geoIpInfo['city'];
  74. $query = $wpdb->prepare("INSERT INTO ".WsdPlugin::getTableName(WpsSettings::LIVE_TRAFFIC_TABLE_NAME)." (entryTime, entryIp, entryReferrer, entryUA, entryRequestedUrl, entryCountry, entryCity, blogId)
  75. VALUES(CURRENT_TIMESTAMP, %s, %s, %s, %s, %s, %s, %d)", $ip, $referrer, $ua, $url, $country, $city, $blogID);
  76. if(false === @$wpdb->query($query)){
  77. return;
  78. }
  79. $numEvents = 0;
  80. $optData = WpsOption::getOption(WpsSettings::LIVE_TRAFFIC_ENTRIES);
  81. if(empty($optData)){
  82. WpsOption::addOption(WpsSettings::LIVE_TRAFFIC_ENTRIES, $numEvents);
  83. }
  84. else { $numEvents = intval($optData); }
  85. WpsOption::updateOption(WpsSettings::LIVE_TRAFFIC_ENTRIES, $numEvents + 1);
  86. }
  87. final public static function getIP()
  88. {
  89. $ip = null;
  90. if ( isset($_SERVER["REMOTE_ADDR"]) ) { $ip = $_SERVER["REMOTE_ADDR"]; }
  91. else if ( isset($_SERVER["HTTP_X_FORWARDED_FOR"]) ) { $ip = $_SERVER["HTTP_X_FORWARDED_FOR"]; }
  92. else if ( isset($_SERVER["HTTP_CLIENT_IP"]) ) { $ip = $_SERVER["HTTP_CLIENT_IP"]; }
  93. if(! is_null($ip) && self::isValidIp($ip)){ return $ip; }
  94. return 'unknown';
  95. }
  96. final public static function getReferrer() { return (empty($_SERVER['HTTP_REFERER']) ? '' : htmlentities($_SERVER['HTTP_REFERER'],ENT_QUOTES)); }
  97. final public static function getUserAgent() { return (empty($_SERVER['HTTP_USER_AGENT']) ? '' : htmlentities($_SERVER['HTTP_USER_AGENT'],ENT_QUOTES)); }
  98. final public static function isValidIp($ip){
  99. if(preg_match('/^(\d+)\.(\d+)\.(\d+)\.(\d+)$/', $ip, $m)){
  100. if(
  101. $m[0] >= 0 && $m[0] <= 255 &&
  102. $m[1] >= 0 && $m[1] <= 255 &&
  103. $m[2] >= 0 && $m[2] <= 255 &&
  104. $m[3] >= 0 && $m[3] <= 255
  105. ){
  106. return true;
  107. }
  108. }
  109. return false;
  110. }
  111. final public static function getRequestedUrl(){
  112. if(isset($_SERVER['HTTP_HOST']) && $_SERVER['HTTP_HOST']){
  113. $host = $_SERVER['HTTP_HOST']; }
  114. else {
  115. $host = $_SERVER['SERVER_NAME'];
  116. }
  117. $url = (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' . $host . $_SERVER['REQUEST_URI'];
  118. return esc_url($url);
  119. }
  120. /**
  121. * @param int $maxEntries If $maxEntries is 0 it means to load all entries, otherwise it will limit the select to that number
  122. * @return mixed
  123. */
  124. final public static function getTrafficData($maxEntries = 0)
  125. {
  126. global $wpdb;
  127. if(empty($maxEntries)){
  128. return $wpdb->get_results("SELECT entryId,entryTime,entryIp,entryReferrer,entryUA,entryRequestedUrl,entryCountry,entryCity FROM ".WsdPlugin::getTableName(WpsSettings::LIVE_TRAFFIC_TABLE_NAME)." ORDER BY entryId DESC");
  129. }
  130. else { return $wpdb->get_results("SELECT entryId,entryTime,entryIp,entryReferrer,entryUA,entryRequestedUrl,entryCountry,entryCity FROM ".WsdPlugin::getTableName(WpsSettings::LIVE_TRAFFIC_TABLE_NAME)." ORDER BY entryId DESC LIMIT 0, ".$maxEntries);}
  131. }
  132. final public static function getLastID()
  133. {
  134. global $wpdb;
  135. return $wpdb->get_var("SELECT entryId FROM ".WsdPlugin::getTableName(WpsSettings::LIVE_TRAFFIC_TABLE_NAME)." ORDER BY entryId DESC");
  136. }
  137. final public static function ajaxGetTrafficData()
  138. {
  139. if(! isset($_REQUEST['nonce'])){ exit('Invalid request'); }
  140. if ( !wp_verify_nonce( $_REQUEST['nonce'], "wpsTrafficScan_nonce")) { exit('Invalid request'); }
  141. if ( !isset( $_REQUEST['getFrom'])) { exit(__('Invalid request',WpsSettings::TEXT_DOMAIN)); }
  142. if ( !isset( $_REQUEST['maxEntries'])) { exit(__('Invalid request',WpsSettings::TEXT_DOMAIN)); }
  143. $lastID = intval($_REQUEST['getFrom']);
  144. $maxEntries = intval($_REQUEST['maxEntries']);
  145. if(!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest')
  146. {
  147. echo self::_ajaxGetFrom($maxEntries, $lastID);
  148. exit;
  149. }
  150. exit('Invalid request!');
  151. }
  152. /**
  153. * @internal
  154. * @param $maxEntries
  155. * @param int $lastID
  156. * @return mixed|string|void
  157. */
  158. final public static function _ajaxGetFrom($maxEntries, $lastID = 0)
  159. {
  160. $result = array(
  161. 'type' => 'success',
  162. 'data' => array()
  163. );
  164. // get the last ID from db
  165. $dbLastID = self::getLastID();
  166. if(empty($dbLastID)){
  167. $result['data'][] = '<tr data-id="0"><td><p style="margin: 5px 5px; font-weight: bold; color: #cc0000">'.__('No data yet.',WpsSettings::TEXT_DOMAIN).'</p></td></tr>';
  168. return json_encode($result);
  169. }
  170. // no change - nothing to display
  171. if($lastID == $dbLastID)
  172. {
  173. return json_encode($result);
  174. }
  175. if($lastID == 0){
  176. $getFrom = $maxEntries;
  177. }
  178. else {
  179. $getFrom = $dbLastID - $lastID;
  180. if ($getFrom < 1){
  181. return json_encode($result);
  182. }
  183. }
  184. $data = self::getTrafficData($getFrom);
  185. if(empty($data)){ $result['data'][] = '<tr data-id="0"><td><p style="margin: 5px 5px; font-weight: bold; color: #cc0000">'.__('No data yet.',WpsSettings::TEXT_DOMAIN).'</p></td></tr>'; }
  186. else {
  187. $data = array_reverse($data);
  188. foreach($data as $entry)
  189. {
  190. $req = trim($entry->entryRequestedUrl);
  191. $e = '<tr data-id="'.$entry->entryId.'"><td class="wsd-scan-entry">';
  192. $e .= '<div>';
  193. if(empty($entry->entryReferrer)){
  194. $ref = '';
  195. }
  196. else {
  197. // Ignore page refresh
  198. $ref = trim($entry->entryReferrer);
  199. if(strcasecmp($req,$ref)==0){
  200. continue;
  201. }
  202. $url = strip_tags(urldecode($req));
  203. $url = esc_html($url,ENT_QUOTES);
  204. $ref = ' '.__('coming from',WpsSettings::TEXT_DOMAIN).' <span class="w-entry"><span>'. $url . '</span></span>';
  205. }
  206. // add geo-location + flag
  207. $country = '';
  208. $city = '';
  209. $flag = '';
  210. if(!empty($entry->entryCountry)){
  211. $country = $entry->entryCountry;
  212. $pos = strpos($country,',');
  213. if(false !== $pos){
  214. $code = substr($country, $pos+1);
  215. $flag = WsdUtil::imageUrl('flags/'.strtolower($code).'.png');
  216. $country = substr($country, 0, $pos);
  217. }
  218. }
  219. if(!empty($entry->entryCity)){ $city = $entry->entryCity; }
  220. if(!empty($flag))
  221. {
  222. $flag = trim($flag);
  223. if(false !== ($pos = strpos($flag, ' republic of,kr.png'))){
  224. $flag = WsdUtil::imageUrl('flags/kr.png');
  225. }
  226. $flag = '<img src="'.$flag.'" alt="'.$flag.'" title="'.$flag.'"/>';
  227. }
  228. $ipInfoUrl = "http://dnsquery.org/ipwhois/{$entry->entryIp}";
  229. $ipInfoTitle = __('Lookup this IP. Opens in a new window/tab',WpsSettings::TEXT_DOMAIN);
  230. $geoInfo = '<span>';
  231. if(! empty($country)){
  232. if(! empty($flag)){ $geoInfo .= $flag; }
  233. if(! empty($city)) { $geoInfo .= ' '.$city.',';}
  234. if(! empty($country)) { $geoInfo .= ' '.$country; }
  235. $geoInfo .= ' (<span class="w-ip"><a href="'.$ipInfoUrl.'" title="'.$ipInfoTitle.'" target="_blank">'.$entry->entryIp.'</a></span>)';
  236. }
  237. else { $geoInfo = __('Unknown location',WpsSettings::TEXT_DOMAIN).' (<span class="w-ip"><a href="'.$ipInfoUrl.'" title="'.$ipInfoTitle.'" target="_blank">'.$entry->entryIp.'</a></span>)'; }
  238. $geoInfo .= '</span>';
  239. $reqUrl = strip_tags(urldecode($req));
  240. $reqUrl = esc_html($reqUrl,ENT_QUOTES);
  241. $e .= '<p style="margin-bottom: 1px;">'.$geoInfo;
  242. $e .= $ref.' '.__('requested',WpsSettings::TEXT_DOMAIN).' <span class="w-entry"><span>'.$reqUrl.'</span></span></p>';
  243. $e .= '<p style="margin-bottom: 1px;"><strong>'.__('Date',WpsSettings::TEXT_DOMAIN).'</strong>: <span class="w-date">'.$entry->entryTime.'</span></p>';
  244. $e .= '<p style="margin-bottom: 1px;"><strong>'.__('Agent',WpsSettings::TEXT_DOMAIN).'</strong>: <span class="w-ua">'.htmlentities($entry->entryUA,ENT_QUOTES).'</span></p>';
  245. $e .= '</div>';
  246. $e .= '</td></tr>';
  247. $result['data'][] = $e;
  248. }
  249. }
  250. return json_encode($result);
  251. }
  252. /**
  253. * @param $url
  254. * @return bool
  255. * Exclude urls
  256. */
  257. private static function isUrlExcluded($url)
  258. {
  259. if(false !==(strpos($url, 'wp-cron.php?doing_wp_cron'))) { return true; }
  260. return false;
  261. }
  262. private static function _getGeoIpInfo($ip)
  263. {
  264. $data = array(
  265. 'country' => '',
  266. 'city' => ''
  267. );
  268. if($ip == '0.0.0.0'){
  269. return $data;
  270. }
  271. $infoUrl = 'http://www.geoplugin.net/json.gp?ip='.$ip;
  272. $result = @file_get_contents($infoUrl);
  273. if(empty($result)){
  274. return $data;
  275. }
  276. $result = json_decode($result);
  277. $data['country'] = $result->geoplugin_countryName. (empty($result->geoplugin_countryCode) ? '' : sanitize_text_field(','.$result->geoplugin_countryCode));
  278. $data['city'] = (empty($result->geoplugin_city) ? '' : sanitize_text_field($result->geoplugin_city));
  279. return $data;
  280. }
  281. }