/** * Core tracking functionality */ public static function slimtrack($_argument = '') { // Don't track self::$stat['dt'] = date_i18n('U'); self::$stat['notes'] = ''; $referer = array(); if (self::$options['javascript_mode'] != 'yes' && !empty($_SERVER['HTTP_REFERER']) || !empty(self::$data_js['ref'])) { if (!empty(self::$data_js['ref'])) { self::$stat['referer'] = base64_decode(self::$data_js['ref']); } else { self::$stat['referer'] = $_SERVER['HTTP_REFERER']; } $referer = parse_url(self::$stat['referer']); // This must be a 'seriously malformed' URL if (!$referer) { self::$stat['id'] = -208; return $_argument; } if (isset($referer['host'])) { self::$stat['domain'] = $referer['host']; // Fix Google Images referring domain if (strpos(self::$stat['domain'], 'www.google') !== false && strpos(self::$stat['referer'], '/imgres?') !== false) { self::$stat['domain'] = str_replace('www.google', 'images.google', self::$stat['domain']); } } } // Is this referer blacklisted? if (!empty(self::$stat['referer'])) { foreach (self::string_to_array(self::$options['ignore_referers']) as $a_filter) { $pattern = str_replace(array('\\*', '\\!'), array('(.*)', '.'), preg_quote($a_filter, '/')); if (preg_match("@^{$pattern}\$@i", self::$stat['referer'])) { self::$stat['id'] = -207; return $_argument; } } } // We want to record both hits and searches (performed through the site search form) if (is_array(self::$data_js) && isset(self::$data_js['res'])) { $parsed_permalink = parse_url(base64_decode(self::$data_js['res'])); self::$stat['searchterms'] = self::_get_search_terms($referer); // Was this an internal search? if (empty(self::$stat['searchterms'])) { self::$stat['searchterms'] = self::_get_search_terms($parsed_permalink); } self::$stat['resource'] = !is_array($parsed_permalink) ? self::$data_js['res'] : $parsed_permalink['path'] . (!empty($parsed_permalink['query']) ? '?' . urldecode($parsed_permalink['query']) : ''); } elseif (empty($_REQUEST['s'])) { self::$stat['searchterms'] = self::_get_search_terms($referer); if (isset($_SERVER['REQUEST_URI'])) { self::$stat['resource'] = urldecode($_SERVER['REQUEST_URI']); } elseif (isset($_SERVER['SCRIPT_NAME'])) { self::$stat['resource'] = isset($_SERVER['QUERY_STRING']) ? $_SERVER['SCRIPT_NAME'] . "?" . $_SERVER['QUERY_STRING'] : $_SERVER['SCRIPT_NAME']; } else { self::$stat['resource'] = isset($_SERVER['QUERY_STRING']) ? $_SERVER['PHP_SELF'] . "?" . $_SERVER['QUERY_STRING'] : $_SERVER['PHP_SELF']; } } else { self::$stat['searchterms'] = str_replace('\\', '', $_REQUEST['s']); self::$stat['resource'] = ''; // Mark the resource to remember that this is a 'local search' } if (strpos(self::$stat['resource'], 'wp-admin/admin-ajax.php') !== false || !empty($_GET['page']) && strpos($_GET['page'], 'wp-slim-') !== false) { return $_argument; } // Is this resource blacklisted? if (!empty(self::$stat['resource'])) { foreach (self::string_to_array(self::$options['ignore_resources']) as $a_filter) { $pattern = str_replace(array('\\*', '\\!'), array('(.*)', '.'), preg_quote($a_filter, '/')); if (preg_match("@^{$pattern}\$@i", self::$stat['resource'])) { self::$stat['id'] = -209; return $_argument; } } } // User's IP address list(self::$stat['ip'], $long_other_ip) = self::_get_ip2long_remote_ip(); if (empty(self::$stat['ip'])) { self::$stat['id'] = -203; return $_argument; } // Should we ignore this user? if (!empty($GLOBALS['current_user']->ID)) { // Don't track logged-in users, if the corresponding option is enabled if (self::$options['track_users'] == 'no') { self::$stat['id'] = -214; return $_argument; } // Don't track users with given capabilities foreach (self::string_to_array(self::$options['ignore_capabilities']) as $a_capability) { if (array_key_exists(strtolower($a_capability), $GLOBALS['current_user']->allcaps)) { self::$stat['id'] = -200; return $_argument; } } if (is_string(self::$options['ignore_users']) && strpos(self::$options['ignore_users'], $GLOBALS['current_user']->data->user_login) !== false) { self::$stat['id'] = -201; return $_argument; } self::$stat['user'] = $GLOBALS['current_user']->data->user_login; self::$stat['notes'] .= 'user:'******'current_user']->data->ID . ';'; $not_spam = true; } elseif (isset($_COOKIE['comment_author_' . COOKIEHASH])) { // Is this a spammer? $spam_comment = self::$wpdb->get_row("SELECT comment_author, COUNT(*) comment_count FROM {$GLOBALS['wpdb']->prefix}comments WHERE INET_ATON(comment_author_IP) = '" . sprintf("%u", self::$stat['ip']) . "' AND comment_approved = 'spam' GROUP BY comment_author LIMIT 0,1", ARRAY_A); if (isset($spam_comment['comment_count']) && $spam_comment['comment_count'] > 0) { if (self::$options['ignore_spammers'] == 'yes') { self::$stat['id'] = -202; return $_argument; } else { self::$stat['notes'] .= 'spam:yes;'; self::$stat['user'] = $spam_comment['comment_author']; } } else { self::$stat['user'] = $_COOKIE['comment_author_' . COOKIEHASH]; } } // Should we ignore this IP address? foreach (self::string_to_array(self::$options['ignore_ip']) as $a_ip_range) { $mask = 32; $ip_to_ignore = $a_ip_range; if (strpos($ip_to_ignore, '/') !== false) { list($ip_to_ignore, $mask) = @explode('/', trim($ip_to_ignore)); if (empty($mask) || !is_numeric($mask)) { $mask = 32; } } $long_ip_to_ignore = ip2long($ip_to_ignore); $long_mask = bindec(str_pad('', $mask, '1') . str_pad('', 32 - $mask, '0')); $long_masked_user_ip = self::$stat['ip'] & $long_mask; $long_masked_other_ip = $long_other_ip & $long_mask; $long_masked_ip_to_ignore = $long_ip_to_ignore & $long_mask; if ($long_masked_user_ip == $long_masked_ip_to_ignore || $long_masked_other_ip == $long_masked_ip_to_ignore) { self::$stat['id'] = -204; return $_argument; } } // Country and Language self::$stat['language'] = self::_get_language(); self::$stat['country'] = self::_get_country(self::$stat['ip']); // Anonymize IP Address? if (self::$options['anonymize_ip'] == 'yes') { self::$stat['ip'] = self::$stat['ip'] & 4294967040; $long_other_ip = $long_other_ip & 4294967040; } // Is this country blacklisted? if (is_string(self::$options['ignore_countries']) && stripos(self::$options['ignore_countries'], self::$stat['country']) !== false) { self::$stat['id'] = -206; return $_argument; } // Mark or ignore Firefox/Safari prefetching requests (X-Moz: Prefetch and X-purpose: Preview) if (isset($_SERVER['HTTP_X_MOZ']) && strtolower($_SERVER['HTTP_X_MOZ']) == 'prefetch' || isset($_SERVER["HTTP_X_PURPOSE"]) && strtolower($_SERVER['HTTP_X_PURPOSE']) == 'preview') { if (self::$options['ignore_prefetch'] == 'yes') { self::$stat['id'] = -210; return $_argument; } else { self::$stat['notes'] .= 'pre:yes;'; } } // Information about this resource $content_info = is_array(self::$data_js) && isset(self::$data_js['ci']) ? unserialize(base64_decode(self::$data_js['ci'])) : self::_get_content_info(); if (!is_array($content_info)) { $content_info = array('content_type' => 'unknown'); } // Detect user agent $browser = self::_get_browser(); // Are we ignoring bots? if (self::$options['javascript_mode'] == 'yes' && $browser['type'] % 2 != 0) { self::$stat['id'] = -211; return $_argument; } // Is this browser blacklisted? foreach (self::string_to_array(self::$options['ignore_browsers']) as $a_filter) { $pattern = str_replace(array('\\*', '\\!'), array('(.*)', '.'), preg_quote($a_filter, '/')); if (preg_match("~^{$pattern}\$~i", $browser['browser'] . '/' . $browser['version']) || preg_match("~^{$pattern}\$~i", $browser['browser']) || preg_match("~^{$pattern}\$~i", $browser['user_agent'])) { self::$stat['id'] = -212; return $_argument; } } // Do we need to assign a visit_id to this user? $cookie_has_been_set = self::_set_visit_id(false); // Allow third-party tools to modify all the data we've gathered so far self::$stat = apply_filters('slimstat_filter_pageview_stat', self::$stat, $browser, $content_info); $browser = apply_filters('slimstat_filter_pageview_browser', $browser, self::$stat, $content_info); $content_info = apply_filters('slimstat_filter_pageview_content_info', $content_info, self::$stat, $browser); do_action('slimstat_track_pageview', self::$stat, $browser, $content_info); // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero if (empty(self::$stat) || empty(self::$stat['dt'])) { self::$stat['id'] = -213; return $_argument; } // Because PHP's integer type is signed, and many IP addresses will result in negative integers on 32-bit architectures, we need to use the "%u" formatter self::$stat['ip'] = sprintf("%u", self::$stat['ip']); if (!empty($long_other_ip) && $long_other_ip != self::$stat['ip']) { self::$stat['other_ip'] = sprintf("%u", $long_other_ip); } // Now let's save this information in the database if (!empty($content_info)) { self::$stat['content_info_id'] = self::maybe_insert_row($content_info, $GLOBALS['wpdb']->base_prefix . 'slim_content_info', 'content_info_id', array()); } self::$stat['browser_id'] = self::maybe_insert_row($browser, $GLOBALS['wpdb']->base_prefix . 'slim_browsers', 'browser_id', array('user_agent' => $browser['user_agent'])); self::$stat['id'] = self::insert_row(self::$stat, $GLOBALS['wpdb']->prefix . 'slim_stats'); // Something went wrong during the insert if (empty(self::$stat['id'])) { self::$stat['id'] = -215; // Attempt to init the environment (new blog in a MU network?) include_once WP_PLUGIN_DIR . '/wp-slimstat/admin/wp-slimstat-admin.php'; wp_slimstat_admin::init_environment(true); return $_argument; } // Is this a new visitor? $is_set_cookie = apply_filters('slimstat_set_visit_cookie', true); if ($is_set_cookie) { if (empty(self::$stat['visit_id']) && !empty(self::$stat['id'])) { // Set a cookie to track this visit (Google and other non-human engines will just ignore it) @setcookie('slimstat_tracking_code', self::$stat['id'] . 'id.' . md5(self::$stat['id'] . 'id' . self::$options['secret']), time() + 2678400, COOKIEPATH); // one month } elseif (!$cookie_has_been_set && self::$options['extend_session'] == 'yes' && self::$stat['visit_id'] > 0) { @setcookie('slimstat_tracking_code', self::$stat['visit_id'] . '.' . md5(self::$stat['visit_id'] . self::$options['secret']), time() + self::$options['session_duration'], COOKIEPATH); } } return $_argument; }
/** * Core tracking functionality */ public static function slimtrack($_argument = '') { self::$stat['dt'] = date_i18n('U'); self::$stat['notes'] = array(); // Allow third-party tools to initialize the stat array self::$stat = apply_filters('slimstat_filter_pageview_stat_init', self::$stat); // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero if (empty(self::$stat) || empty(self::$stat['dt'])) { self::$stat['id'] = -213; self::_set_error_array(__('Pageview filtered by third-party code', 'wp-slimstat')); return $_argument; } if (!empty(self::$data_js['ref'])) { self::$stat['referer'] = base64_decode(self::$data_js['ref']); } else { if (!empty($_SERVER['HTTP_REFERER'])) { self::$stat['referer'] = $_SERVER['HTTP_REFERER']; } } if (!empty(self::$stat['referer'])) { // Is this a 'seriously malformed' URL? $referer = parse_url(self::$stat['referer']); if (!$referer) { self::$stat['id'] = -208; self::_set_error_array(__('Malformed URL', 'wp-slimstat')); return $_argument; } // Fix Google Images referring domain if (strpos(self::$stat['referer'], 'www.google') !== false) { if (strpos(self::$stat['referer'], '/imgres?') !== false) { self::$stat['referer'] = str_replace('www.google', 'images.google', self::$stat['referer']); } if (strpos(self::$stat['referer'], '/url?') !== false) { self::$stat['referer'] = str_replace('/url?', '/search?', self::$stat['referer']); } } // Is this referer blacklisted? foreach (self::string_to_array(self::$options['ignore_referers']) as $a_filter) { $pattern = str_replace(array('\\*', '\\!'), array('(.*)', '.'), preg_quote($a_filter, '/')); if (preg_match("@^{$pattern}\$@i", self::$stat['referer'])) { self::$stat['id'] = -207; self::_set_error_array(__('Referrer is blacklisted', 'wp-slimstat')); return $_argument; } } } $content_info = self::_get_content_info(); // Did we receive data from an Ajax request? if (!empty(self::$data_js['id'])) { // Are we tracking a new pageview? (pos is empty = no event was triggered) if (empty(self::$data_js['pos'])) { $content_info = unserialize(base64_decode(self::$data_js['id'])); if ($content_info === false || empty($content_info['content_type'])) { $content_info = array(); } } else { if (!empty(self::$data_js['res'])) { $download_url = base64_decode(self::$data_js['res']); if (is_string($download_url)) { $download_extension = pathinfo($download_url, PATHINFO_EXTENSION); if (in_array($download_extension, self::string_to_array(self::$options['extensions_to_track']))) { unset(self::$stat['id']); $content_info = array('content_type' => 'download'); } } } } } self::$stat = self::$stat + $content_info; // We want to record both hits and searches (performed through the site search form) if (self::$stat['content_type'] == 'external') { self::$stat['resource'] = $_SERVER['HTTP_REFERER']; self::$stat['referer'] = ''; } else { if (is_array(self::$data_js) && isset(self::$data_js['res'])) { $parsed_permalink = parse_url(base64_decode(self::$data_js['res'])); self::$stat['searchterms'] = self::_get_search_terms($referer); // Was this an internal search? if (empty(self::$stat['searchterms'])) { self::$stat['searchterms'] = self::_get_search_terms($parsed_permalink); } self::$stat['resource'] = !is_array($parsed_permalink) ? self::$data_js['res'] : $parsed_permalink['path'] . (!empty($parsed_permalink['query']) ? '?' . urldecode($parsed_permalink['query']) : ''); } elseif (empty($_REQUEST['s'])) { if (!empty($referer)) { self::$stat['searchterms'] = self::_get_search_terms($referer); } self::$stat['resource'] = self::get_request_uri(); } else { self::$stat['searchterms'] = str_replace('\\', '', $_REQUEST['s']); } } // Don't store empty values in the database if (empty(self::$stat['searchterms'])) { unset(self::$stat['searchterms']); } // Do not track report pages in the admin if (!empty(self::$stat['resource']) && strpos(self::$stat['resource'], 'wp-admin/admin-ajax.php') !== false || !empty($_GET['page']) && strpos($_GET['page'], 'wp-slim-view') !== false) { return $_argument; } // Is this resource blacklisted? if (!empty(self::$stat['resource'])) { foreach (self::string_to_array(self::$options['ignore_resources']) as $a_filter) { $pattern = str_replace(array('\\*', '\\!'), array('(.*)', '.'), preg_quote($a_filter, '/')); if (preg_match("@^{$pattern}\$@i", self::$stat['resource'])) { self::$stat['id'] = -209; self::_set_error_array(__('Permalink is blacklisted', 'wp-slimstat')); return $_argument; } } } // User's IP address list(self::$stat['ip'], self::$stat['other_ip']) = self::_get_remote_ip(); if (empty(self::$stat['ip']) || self::$stat['ip'] == '0.0.0.0') { self::$stat['id'] = -203; self::_set_error_array(__('Empty or not supported IP address format (IPv6)', 'wp-slimstat')); return $_argument; } // Should we ignore this user? if (!empty($GLOBALS['current_user']->ID)) { // Don't track logged-in users, if the corresponding option is enabled if (self::$options['track_users'] == 'no') { self::$stat['id'] = -214; self::_set_error_array(__('Logged in user not tracked', 'wp-slimstat')); return $_argument; } // Don't track users with given capabilities foreach (self::string_to_array(self::$options['ignore_capabilities']) as $a_capability) { if (array_key_exists(strtolower($a_capability), $GLOBALS['current_user']->allcaps)) { self::$stat['id'] = -200; self::_set_error_array(__('User with given capability not tracked', 'wp-slimstat')); return $_argument; } } if (is_string(self::$options['ignore_users']) && strpos(self::$options['ignore_users'], $GLOBALS['current_user']->data->user_login) !== false) { self::$stat['id'] = -201; self::_set_error_array(sprintf(__('User %s is blacklisted', 'wp-slimstat'), $GLOBALS['current_user']->data->user_login)); return $_argument; } self::$stat['username'] = $GLOBALS['current_user']->data->user_login; self::$stat['notes'][] = 'user:'******'current_user']->data->ID; $not_spam = true; } elseif (isset($_COOKIE['comment_author_' . COOKIEHASH])) { // Is this a spammer? $spam_comment = self::$wpdb->get_row(self::$wpdb->prepare("\n\t\t\t\tSELECT comment_author, COUNT(*) comment_count\n\t\t\t\tFROM {$GLOBALS['wpdb']->prefix}comments\n\t\t\t\tWHERE comment_author_IP = %s AND comment_approved = 'spam'\n\t\t\t\tGROUP BY comment_author\n\t\t\t\tLIMIT 0,1", self::$stat['ip']), ARRAY_A); if (!empty($spam_comment['comment_count'])) { if (self::$options['ignore_spammers'] == 'yes') { self::$stat['id'] = -202; self::_set_error_array(sprintf(__('Spammer %s not tracked', 'wp-slimstat'), $spam_comment['comment_author'])); return $_argument; } else { self::$stat['notes'][] = 'spam:yes'; self::$stat['username'] = $spam_comment['comment_author']; } } else { self::$stat['username'] = $_COOKIE['comment_author_' . COOKIEHASH]; } } // Should we ignore this IP address? foreach (self::string_to_array(self::$options['ignore_ip']) as $a_ip_range) { $ip_to_ignore = $a_ip_range; if (strpos($ip_to_ignore, '/') !== false) { list($ip_to_ignore, $cidr_mask) = explode('/', trim($ip_to_ignore)); } else { $cidr_mask = self::get_mask_length($ip_to_ignore); } $long_masked_ip_to_ignore = substr(self::dtr_pton($ip_to_ignore), 0, $cidr_mask); $long_masked_user_ip = substr(self::dtr_pton(self::$stat['ip']), 0, $cidr_mask); $long_masked_user_other_ip = substr(self::dtr_pton(self::$stat['other_ip']), 0, $cidr_mask); if ($long_masked_user_ip === $long_masked_ip_to_ignore || $long_masked_user_other_ip === $long_masked_ip_to_ignore) { self::$stat['id'] = -204; self::_set_error_array(sprintf(__('IP address %s is blacklisted', 'wp-slimstat'), self::$stat['ip'] . (!empty(self::$stat['other_ip']) ? ' (' . self::$stat['other_ip'] . ')' : ''))); return $_argument; } } // Country and Language self::$stat['language'] = self::_get_language(); self::$stat['country'] = self::get_country(self::$stat['ip']); // Anonymize IP Address? if (self::$options['anonymize_ip'] == 'yes') { // IPv4 or IPv6 $needle = '.'; $replace = '.0'; if (self::get_mask_length(self::$stat['ip']) == 128) { $needle = ':'; $replace = ':0000'; } self::$stat['ip'] = substr(self::$stat['ip'], 0, strrpos(self::$stat['ip'], $needle)) . $replace; if (!empty(self::$stat['other_ip'])) { self::$stat['other_ip'] = substr(self::$stat['other_ip'], 0, strrpos(self::$stat['other_ip'], $needle)) . $replace; } } // Is this country blacklisted? if (is_string(self::$options['ignore_countries']) && stripos(self::$options['ignore_countries'], self::$stat['country']) !== false) { self::$stat['id'] = -206; self::_set_error_array(sprintf(__('Country %s is blacklisted', 'wp-slimstat'), self::$stat['country'])); return $_argument; } // Mark or ignore Firefox/Safari prefetching requests (X-Moz: Prefetch and X-purpose: Preview) if (isset($_SERVER['HTTP_X_MOZ']) && strtolower($_SERVER['HTTP_X_MOZ']) == 'prefetch' || isset($_SERVER['HTTP_X_PURPOSE']) && strtolower($_SERVER['HTTP_X_PURPOSE']) == 'preview') { if (self::$options['ignore_prefetch'] == 'yes') { self::$stat['id'] = -210; self::_set_error_array(__('Prefetch requests are ignored', 'wp-slimstat')); return $_argument; } else { self::$stat['notes'][] = 'pre:yes'; } } // Detect user agent if (empty(self::$browser)) { self::$browser = self::_get_browser(); } // Are we ignoring bots? if ((self::$options['javascript_mode'] == 'yes' || self::$options['ignore_bots'] == 'yes') && self::$browser['browser_type'] % 2 != 0) { self::$stat['id'] = -211; self::_set_error_array(__('Bot not tracked', 'wp-slimstat')); return $_argument; } // Is this browser blacklisted? foreach (self::string_to_array(self::$options['ignore_browsers']) as $a_filter) { $pattern = str_replace(array('\\*', '\\!'), array('(.*)', '.'), preg_quote($a_filter, '/')); if (preg_match("~^{$pattern}\$~i", self::$browser['browser'] . '/' . self::$browser['version']) || preg_match("~^{$pattern}\$~i", self::$browser['browser']) || preg_match("~^{$pattern}\$~i", self::$browser['user_agent'])) { self::$stat['id'] = -212; self::_set_error_array(sprintf(__('Browser %s is blacklisted', 'wp-slimstat'), self::$browser['browser'])); return $_argument; } } self::$stat = self::$stat + self::$browser; // Do we need to assign a visit_id to this user? $cookie_has_been_set = self::_set_visit_id(false); // Allow third-party tools to modify all the data we've gathered so far self::$stat = apply_filters('slimstat_filter_pageview_stat', self::$stat); do_action('slimstat_track_pageview', self::$stat); // Third-party tools can decide that this pageview should not be tracked, by setting its datestamp to zero if (empty(self::$stat) || empty(self::$stat['dt'])) { self::$stat['id'] = -213; self::_set_error_array(__('Pageview filtered by third-party code', 'wp-slimstat')); return $_argument; } // Implode the notes self::$stat['notes'] = implode(';', self::$stat['notes']); // Now let's save this information in the database self::$stat['id'] = self::insert_row(self::$stat, $GLOBALS['wpdb']->prefix . 'slim_stats'); // Something went wrong during the insert if (empty(self::$stat['id'])) { self::$stat['id'] = -215; self::_set_error_array(self::$wpdb->last_error); // Attempt to init the environment (new blog in a MU network?) include_once WP_PLUGIN_DIR . '/wp-slimstat/admin/wp-slimstat-admin.php'; wp_slimstat_admin::init_environment(true); return $_argument; } // Is this a new visitor? $is_set_cookie = apply_filters('slimstat_set_visit_cookie', true); if ($is_set_cookie) { $unique_id = get_current_user_id(); if (empty($unique_id)) { $unique_id = ''; } else { $unique_id = '_' . $unique_id; } if (empty(self::$stat['visit_id']) && !empty(self::$stat['id'])) { // Set a cookie to track this visit (Google and other non-human engines will just ignore it) @setcookie('slimstat_tracking_code' . $unique_id, self::$stat['id'] . 'id.' . md5(self::$stat['id'] . 'id' . self::$options['secret']), time() + 2678400, COOKIEPATH); } elseif (!$cookie_has_been_set && self::$options['extend_session'] == 'yes' && self::$stat['visit_id'] > 0) { @setcookie('slimstat_tracking_code' . $unique_id, self::$stat['visit_id'] . '.' . md5(self::$stat['visit_id'] . self::$options['secret']), time() + self::$options['session_duration'], COOKIEPATH); } } return $_argument; }