Version Description
- [New] As those who have been using Slimstat for a while know, we never stop doing our good share of research and development to improve our plugin. One feature on our wishlist was to make the geolocation functionality more accurate. Specifically, users have been asking us to track not just the Country of origin, but possibly the state and city. In order to geolocate visitors, our code has been leveraging a third-party data file provided by MaxMind.com. A while ago, they launched a new data format, which improves performance and offers a way to quickly determine the city of origin. However, the new library required a higher version of PHP, and up until now we had been hesitant to adopt it, to allow more people to use our plugin, over the chance of offering this feature. Now, after spending some time combing through their code, we found a way to get the best of both worlds: by customizing their PHP library, we were able to make it work with PHP 5.3! Which means that now Slimstat is able to tell you your visitors' city of origin (and State, when applicable) right out of the box. This information is available in the Access Log report and in a new 'Top Cities' report under the Audience tab. Please note: the MaxMind data file to enable this feature is approximately 60 Mb, and for this reason this new functionality is not enabled by default. You must go to Slimstat > Settings > Tracker and turn on the corresponding option. Then go to Slimstat > Settings > Maintenance and uninstall/install the GeoLite file to download the one that contains the city data. Please feel free to contact us if you have any questions.
- [Update] Removed backward compatibility code for those updating from a version prior to 4.2. Hopefully most of our users are using a newer version that that. If you're not, please contact our support service for instructions on how to upgrade.
- [Update] The format used to save your settings in the database has been changed. You MUST update your premium add-ons as soon as possible, and get the version compatible with this new format, or you might notice unexpected behaviors. Please contact us if you experience difficulties updating your add-ons.
- [Update] Cleaned up some old CSS code affecting the reports.
Download this release
Release Info
Developer | coolmann |
Plugin | Slimstat Analytics |
Version | 4.7.2 |
Comparing to | |
See all releases |
Code changes from version 4.7.1 to 4.7.2
- admin/config/index.php +1 -0
- admin/config/maintenance.php +6 -9
- admin/css/slimstat.css +1 -2
- admin/view/index.php +4 -4
- admin/view/layout.php +1 -1
- admin/view/right-now.php +17 -9
- admin/view/wp-slimstat-db.php +23 -16
- admin/view/wp-slimstat-reports.php +25 -40
- admin/wp-slimstat-admin.php +43 -267
- maxmind.php +656 -653
- readme.txt +7 -1
- wp-slimstat.php +79 -119
admin/config/index.php
CHANGED
@@ -116,6 +116,7 @@ $settings = array(
|
|
116 |
'track_users' => array( 'description' => __( 'Track WP Users', 'wp-slimstat' ), 'type' => 'toggle', 'long_description' => __( 'Enable this option to track logged in users.', 'wp-slimstat' ) ),
|
117 |
'session_duration' => array('description' => __( 'Session Duration', 'wp-slimstat' ), 'type' => 'integer', 'long_description' => __( 'How many seconds should a human session last? Google Analytics sets it to 1800 seconds.', 'wp-slimstat' ), 'after_input_field' => __( 'seconds', 'wp-slimstat' ) ),
|
118 |
'extend_session' => array( 'description' => __( 'Extend Session', 'wp-slimstat' ), 'type' => 'toggle', 'long_description' => __( 'Extend the duration of a session each time the user visits a new page.', 'wp-slimstat' ) ),
|
|
|
119 |
'enable_cdn' => array('description' => __('Enable CDN','wp-slimstat'), 'type' => 'toggle', 'long_description' => __("Use <a href='http://www.jsdelivr.com/' target='_blank'>JSDelivr</a>'s CDN, by serving our tracking code from their fast and reliable network (free service).",'wp-slimstat')),
|
120 |
|
121 |
'advanced_external_pages_header' => array('description' => __('External Pages','wp-slimstat'), 'type' => 'section_header'),
|
116 |
'track_users' => array( 'description' => __( 'Track WP Users', 'wp-slimstat' ), 'type' => 'toggle', 'long_description' => __( 'Enable this option to track logged in users.', 'wp-slimstat' ) ),
|
117 |
'session_duration' => array('description' => __( 'Session Duration', 'wp-slimstat' ), 'type' => 'integer', 'long_description' => __( 'How many seconds should a human session last? Google Analytics sets it to 1800 seconds.', 'wp-slimstat' ), 'after_input_field' => __( 'seconds', 'wp-slimstat' ) ),
|
118 |
'extend_session' => array( 'description' => __( 'Extend Session', 'wp-slimstat' ), 'type' => 'toggle', 'long_description' => __( 'Extend the duration of a session each time the user visits a new page.', 'wp-slimstat' ) ),
|
119 |
+
'geolocation_country' => array( 'description' => __( 'Geolocation Precision', 'wp-slimstat' ), 'type' => 'toggle', 'long_description' => __( "When Slimstat determines your visitors' Country of origin, it uses a third-party data file <a href='https://dev.maxmind.com/geoip/geoip2/geolite2/' target='_blank'>provided by MaxMind</a>. They offer two precision levels: country and city. By default, Slimstat will install the smaller one (country), and you can decide to use the other one, if you don't mind its 60 Mb average size. After you change this option, please <strong>go to the Maintenance tab</strong> and reload (uninstall/install) the MaxMind GeoLite DB by clicking on the corresponding button.", 'wp-slimstat' ), 'custom_label_on' => __( 'Country', 'wp-slimstat' ), 'custom_label_off' => __( 'City', 'wp-slimstat' ) ),
|
120 |
'enable_cdn' => array('description' => __('Enable CDN','wp-slimstat'), 'type' => 'toggle', 'long_description' => __("Use <a href='http://www.jsdelivr.com/' target='_blank'>JSDelivr</a>'s CDN, by serving our tracking code from their fast and reliable network (free service).",'wp-slimstat')),
|
121 |
|
122 |
'advanced_external_pages_header' => array('description' => __('External Pages','wp-slimstat'), 'type' => 'section_header'),
|
admin/config/maintenance.php
CHANGED
@@ -17,7 +17,7 @@ if ( !empty( $_REQUEST[ 'action' ] ) ) {
|
|
17 |
break;
|
18 |
|
19 |
case 'activate-sql-debug-mode':
|
20 |
-
wp_slimstat::$settings[ 'show_sql_debug' ] = '
|
21 |
break;
|
22 |
|
23 |
case 'deactivate-indexes':
|
@@ -81,12 +81,9 @@ if ( !empty( $_REQUEST[ 'action' ] ) ) {
|
|
81 |
case 'import-settings':
|
82 |
$new_settings = @json_decode( stripslashes( $_POST[ 'import-slimstat-settings' ] ), true );
|
83 |
|
84 |
-
if ( is_array( $new_settings ) ) {
|
85 |
-
$new_settings
|
86 |
-
|
87 |
-
foreach ( $new_settings as $a_setting_name => $a_setting_value ) {
|
88 |
-
wp_slimstat::$settings[ $a_setting_name ] = $a_setting_value;
|
89 |
-
}
|
90 |
}
|
91 |
wp_slimstat_admin::show_alert_message( __( 'Your new Slimstat settings have been imported and installed.', 'wp-slimstat' ) );
|
92 |
}
|
@@ -176,7 +173,7 @@ $slim_browsers_exists =wp_slimstat::$wpdb->get_col( "SHOW TABLES LIKE '{$GLOBALS
|
|
176 |
</td>
|
177 |
</tr>
|
178 |
<tr class="alternate">
|
179 |
-
<?php if ( wp_slimstat::$settings[ 'show_sql_debug' ] != '
|
180 |
<th scope="row">
|
181 |
<a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&action=activate-sql-debug-mode"><?php _e("Enable SQL Debug",'wp-slimstat'); ?></a>
|
182 |
</th>
|
@@ -313,7 +310,7 @@ $slim_browsers_exists =wp_slimstat::$wpdb->get_col( "SHOW TABLES LIKE '{$GLOBALS
|
|
313 |
<form action="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>" method="post">
|
314 |
<?php wp_nonce_field( 'maintenance_wp_slimstat', 'maintenance_wp_slimstat_nonce', true, true ) ?>
|
315 |
<input type="hidden" name="action" value="import-settings" />
|
316 |
-
<textarea name="import-slimstat-settings" style="width:100%" rows="
|
317 |
<input type="submit" value="<?php _e('Import','wp-slimstat') ?>" class="button-secondary"
|
318 |
onclick="return(confirm('<?php _e('Are you sure you want to OVERWRITE your current settings?','wp-slimstat'); ?>'))">
|
319 |
</form>
|
17 |
break;
|
18 |
|
19 |
case 'activate-sql-debug-mode':
|
20 |
+
wp_slimstat::$settings[ 'show_sql_debug' ] = 'on';
|
21 |
break;
|
22 |
|
23 |
case 'deactivate-indexes':
|
81 |
case 'import-settings':
|
82 |
$new_settings = @json_decode( stripslashes( $_POST[ 'import-slimstat-settings' ] ), true );
|
83 |
|
84 |
+
if ( is_array( $new_settings ) && !empty( $new_settings ) ) {
|
85 |
+
foreach ( $new_settings as $a_setting_name => $a_setting_value ) {
|
86 |
+
wp_slimstat::$settings[ $a_setting_name ] = $a_setting_value;
|
|
|
|
|
|
|
87 |
}
|
88 |
wp_slimstat_admin::show_alert_message( __( 'Your new Slimstat settings have been imported and installed.', 'wp-slimstat' ) );
|
89 |
}
|
173 |
</td>
|
174 |
</tr>
|
175 |
<tr class="alternate">
|
176 |
+
<?php if ( wp_slimstat::$settings[ 'show_sql_debug' ] != 'on' ): ?>
|
177 |
<th scope="row">
|
178 |
<a class="button-secondary" href="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>&action=activate-sql-debug-mode"><?php _e("Enable SQL Debug",'wp-slimstat'); ?></a>
|
179 |
</th>
|
310 |
<form action="<?php echo wp_slimstat_admin::$config_url.$current_tab ?>" method="post">
|
311 |
<?php wp_nonce_field( 'maintenance_wp_slimstat', 'maintenance_wp_slimstat_nonce', true, true ) ?>
|
312 |
<input type="hidden" name="action" value="import-settings" />
|
313 |
+
<textarea name="import-slimstat-settings" style="width:100%" rows="10"><?php echo json_encode( wp_slimstat::$settings ) ?></textarea><br/>
|
314 |
<input type="submit" value="<?php _e('Import','wp-slimstat') ?>" class="button-secondary"
|
315 |
onclick="return(confirm('<?php _e('Are you sure you want to OVERWRITE your current settings?','wp-slimstat'); ?>'))">
|
316 |
</form>
|
admin/css/slimstat.css
CHANGED
@@ -265,11 +265,10 @@
|
|
265 |
background-position: 0 0;
|
266 |
background-repeat: no-repeat;
|
267 |
display: inline-block;
|
268 |
-
font-size: 18px;
|
269 |
height: 18px;
|
270 |
line-height: 18px;
|
271 |
margin-right: 5px;
|
272 |
-
vertical-align:
|
273 |
width: 16px;
|
274 |
}
|
275 |
[id^=slim_] .spaced{
|
265 |
background-position: 0 0;
|
266 |
background-repeat: no-repeat;
|
267 |
display: inline-block;
|
|
|
268 |
height: 18px;
|
269 |
line-height: 18px;
|
270 |
margin-right: 5px;
|
271 |
+
vertical-align: middle;
|
272 |
width: 16px;
|
273 |
}
|
274 |
[id^=slim_] .spaced{
|
admin/view/index.php
CHANGED
@@ -21,7 +21,7 @@
|
|
21 |
|
22 |
$filter_value_html = '<label for="slimstat-filter-value">Filter value</label><input type="text" class="text" name="v" id="slimstat-filter-value" value="" size="20">';
|
23 |
|
24 |
-
if (wp_slimstat::$settings['enable_sov'] == '
|
25 |
echo $filter_value_html.$filter_operator_html.$filter_name_html;
|
26 |
}
|
27 |
else{
|
@@ -138,15 +138,15 @@
|
|
138 |
<?php endif; endforeach; ?>
|
139 |
</form>
|
140 |
<?php
|
141 |
-
if ( !file_exists( wp_slimstat::$maxmind_path ) && ( empty( wp_slimstat::$settings[ 'no_maxmind_warning' ] ) || wp_slimstat::$settings[ 'no_maxmind_warning' ] != '
|
142 |
wp_slimstat_admin::show_alert_message( sprintf( __( "<a href='%s' class='noslimstat'>Install MaxMind's GeoLite DB</a> to determine your visitors' country of origin.", 'wp-slimstat' ), self::$config_url . '6#wp-slimstat-external-data-files' ) . '<a id="slimstat-hide-geolite-notice" class="slimstat-font-cancel slimstat-float-right noslimstat" title="Hide this notice" href="#"></a>', 'wp-ui-text-notification below-h2' );
|
143 |
}
|
144 |
|
145 |
-
if ( !file_exists( slim_browser::$browscap_autoload_path ) && ( empty( wp_slimstat::$settings[ 'no_browscap_warning' ] ) || wp_slimstat::$settings[ 'no_browscap_warning' ] != '
|
146 |
wp_slimstat_admin::show_alert_message( sprintf( __( "Install the Browscap <a href='%s' class='noslimstat'>User Agent Database</a> to accurately determine your visitors' browser and operating system.", 'wp-slimstat' ), self::$config_url . '6#wp-slimstat-external-data-files' ) . '<a id="slimstat-hide-browscap-notice" class="slimstat-font-cancel slimstat-float-right noslimstat" title="Hide this notice" href="#"></a>', 'wp-ui-text-notification below-h2' );
|
147 |
}
|
148 |
|
149 |
-
if ( wp_slimstat::$advanced_cache_exists && ( empty( wp_slimstat::$settings[ 'no_caching_warning' ] ) || wp_slimstat::$settings[ 'no_caching_warning' ] != '
|
150 |
wp_slimstat_admin::show_alert_message( sprintf( __( "A caching plugin has been detected on your website. Please <a href='%s' target='_blank' class='noslimstat'>make sure to configure</a> Slimstat Analytics accordingly, to get accurate information.", 'wp-slimstat' ), 'https://slimstat.freshdesk.com/support/solutions/articles/5000528524-i-am-using-w3-total-cache-or-wp-super-cache-hypercache-etc-and-it-looks-like-slimstat-is-not-tra' ) . '<a id="slimstat-hide-caching-notice" class="slimstat-font-cancel slimstat-float-right" title="Hide this notice" href="#"></a>', 'wp-ui-text-notification below-h2' );
|
151 |
}
|
152 |
|
21 |
|
22 |
$filter_value_html = '<label for="slimstat-filter-value">Filter value</label><input type="text" class="text" name="v" id="slimstat-filter-value" value="" size="20">';
|
23 |
|
24 |
+
if ( wp_slimstat::$settings[ 'enable_sov' ] == 'on' ) {
|
25 |
echo $filter_value_html.$filter_operator_html.$filter_name_html;
|
26 |
}
|
27 |
else{
|
138 |
<?php endif; endforeach; ?>
|
139 |
</form>
|
140 |
<?php
|
141 |
+
if ( !file_exists( wp_slimstat::$maxmind_path ) && ( empty( wp_slimstat::$settings[ 'no_maxmind_warning' ] ) || wp_slimstat::$settings[ 'no_maxmind_warning' ] != 'on' ) ) {
|
142 |
wp_slimstat_admin::show_alert_message( sprintf( __( "<a href='%s' class='noslimstat'>Install MaxMind's GeoLite DB</a> to determine your visitors' country of origin.", 'wp-slimstat' ), self::$config_url . '6#wp-slimstat-external-data-files' ) . '<a id="slimstat-hide-geolite-notice" class="slimstat-font-cancel slimstat-float-right noslimstat" title="Hide this notice" href="#"></a>', 'wp-ui-text-notification below-h2' );
|
143 |
}
|
144 |
|
145 |
+
if ( !file_exists( slim_browser::$browscap_autoload_path ) && ( empty( wp_slimstat::$settings[ 'no_browscap_warning' ] ) || wp_slimstat::$settings[ 'no_browscap_warning' ] != 'on' ) ) {
|
146 |
wp_slimstat_admin::show_alert_message( sprintf( __( "Install the Browscap <a href='%s' class='noslimstat'>User Agent Database</a> to accurately determine your visitors' browser and operating system.", 'wp-slimstat' ), self::$config_url . '6#wp-slimstat-external-data-files' ) . '<a id="slimstat-hide-browscap-notice" class="slimstat-font-cancel slimstat-float-right noslimstat" title="Hide this notice" href="#"></a>', 'wp-ui-text-notification below-h2' );
|
147 |
}
|
148 |
|
149 |
+
if ( wp_slimstat::$advanced_cache_exists && ( empty( wp_slimstat::$settings[ 'no_caching_warning' ] ) || wp_slimstat::$settings[ 'no_caching_warning' ] != 'on' ) && ( empty( wp_slimstat::$settings[ 'javascript_mode' ] ) || wp_slimstat::$settings[ 'javascript_mode' ] != 'on' ) ) {
|
150 |
wp_slimstat_admin::show_alert_message( sprintf( __( "A caching plugin has been detected on your website. Please <a href='%s' target='_blank' class='noslimstat'>make sure to configure</a> Slimstat Analytics accordingly, to get accurate information.", 'wp-slimstat' ), 'https://slimstat.freshdesk.com/support/solutions/articles/5000528524-i-am-using-w3-total-cache-or-wp-super-cache-hypercache-etc-and-it-looks-like-slimstat-is-not-tra' ) . '<a id="slimstat-hide-caching-notice" class="slimstat-font-cancel slimstat-float-right" title="Hide this notice" href="#"></a>', 'wp-ui-text-notification below-h2' );
|
151 |
}
|
152 |
|
admin/view/layout.php
CHANGED
@@ -55,7 +55,7 @@
|
|
55 |
$already_seen = array();
|
56 |
|
57 |
$current_user = wp_get_current_user();
|
58 |
-
$page_location = ( wp_slimstat::$settings[ 'use_separate_menu' ] == '
|
59 |
?>
|
60 |
|
61 |
<div class="wrap slimstat-layout">
|
55 |
$already_seen = array();
|
56 |
|
57 |
$current_user = wp_get_current_user();
|
58 |
+
$page_location = ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'on' ) ? 'slimstat' : 'admin';
|
59 |
?>
|
60 |
|
61 |
<div class="wrap slimstat-layout">
|
admin/view/right-now.php
CHANGED
@@ -4,7 +4,7 @@ if ( !function_exists( 'add_action' ) ) {
|
|
4 |
exit(0);
|
5 |
}
|
6 |
|
7 |
-
if ( wp_slimstat::$settings[ 'async_load' ] == '
|
8 |
return '';
|
9 |
}
|
10 |
|
@@ -36,7 +36,7 @@ echo wp_slimstat_db::$debug_message;
|
|
36 |
if ( isset( $_args[ 'echo' ] ) && $_args[ 'echo' ] === false ) {
|
37 |
|
38 |
// Massage the data before returning it
|
39 |
-
if ( wp_slimstat::$settings[ 'convert_ip_addresses' ] == '
|
40 |
for ( $i = 0; $i < $count_page_results; $i++ ) {
|
41 |
$gethostbyaddr = gethostbyaddr( $results[ $i ][ 'ip' ] );
|
42 |
if ( $gethostbyaddr != $host_by_ip && !empty( $gethostbyaddr ) ) {
|
@@ -63,7 +63,7 @@ else {
|
|
63 |
// Loop through the results
|
64 |
for ( $i=0; $i < $count_page_results; $i++ ) {
|
65 |
$host_by_ip = $results[ $i ][ 'ip' ];
|
66 |
-
if ( wp_slimstat::$settings[ 'convert_ip_addresses' ] == '
|
67 |
$gethostbyaddr = gethostbyaddr( $results[ $i ][ 'ip' ] );
|
68 |
if ( $gethostbyaddr != $host_by_ip && !empty( $gethostbyaddr ) ) {
|
69 |
$host_by_ip .= ', ' . $gethostbyaddr;
|
@@ -79,11 +79,17 @@ else {
|
|
79 |
$highlight_row = !empty($results[$i]['searchterms'])?' is-search-engine':(($results[$i]['browser_type'] != 1)?' is-direct':'');
|
80 |
|
81 |
// Country
|
82 |
-
$
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
// Browser
|
85 |
if ($results[$i]['browser_version'] == 0) $results[$i]['browser_version'] = '';
|
86 |
-
$browser_title = ( wp_slimstat::$settings[ 'show_complete_user_agent_tooltip' ] != '
|
87 |
$browser_icon = $plugin_url.'/images/browsers/other-browsers-and-os.png';
|
88 |
if (in_array($results[$i]['browser'], $supported_browser_icons)){
|
89 |
$browser_icon = $plugin_url.'/images/browsers/'.sanitize_title($results[$i]['browser']).'.png';
|
@@ -109,7 +115,7 @@ else {
|
|
109 |
}
|
110 |
else{
|
111 |
$display_user_name = $results[ $i ][ 'username' ];
|
112 |
-
if ( wp_slimstat::$settings[ 'show_display_name' ] == '
|
113 |
$display_real_name = get_user_by('login', $results[$i]['username']);
|
114 |
if (is_object($display_real_name)) $display_user_name = $display_real_name->display_name;
|
115 |
}
|
@@ -118,8 +124,10 @@ else {
|
|
118 |
$highlight_row = (strpos( $results[$i]['notes'], 'user:') !== false)?' is-known-user':' is-known-visitor';
|
119 |
|
120 |
}
|
121 |
-
|
122 |
-
|
|
|
|
|
123 |
}
|
124 |
|
125 |
// Originating IP Address
|
@@ -147,7 +155,7 @@ else {
|
|
147 |
$screen_resolution = "<span class='pageview-screenres'>{$results[ $i ][ 'screen_width' ]}x{$results[ $i ][ 'screen_height' ]}</span>";
|
148 |
}
|
149 |
|
150 |
-
$row_output = "<p class='header$highlight_row'
|
151 |
|
152 |
// Strip all the filter links, if this information is shown on the frontend
|
153 |
if ( !is_admin() ) {
|
4 |
exit(0);
|
5 |
}
|
6 |
|
7 |
+
if ( wp_slimstat::$settings[ 'async_load' ] == 'on' && ( !defined( 'DOING_AJAX' ) || !DOING_AJAX ) ) {
|
8 |
return '';
|
9 |
}
|
10 |
|
36 |
if ( isset( $_args[ 'echo' ] ) && $_args[ 'echo' ] === false ) {
|
37 |
|
38 |
// Massage the data before returning it
|
39 |
+
if ( wp_slimstat::$settings[ 'convert_ip_addresses' ] == 'on' ) {
|
40 |
for ( $i = 0; $i < $count_page_results; $i++ ) {
|
41 |
$gethostbyaddr = gethostbyaddr( $results[ $i ][ 'ip' ] );
|
42 |
if ( $gethostbyaddr != $host_by_ip && !empty( $gethostbyaddr ) ) {
|
63 |
// Loop through the results
|
64 |
for ( $i=0; $i < $count_page_results; $i++ ) {
|
65 |
$host_by_ip = $results[ $i ][ 'ip' ];
|
66 |
+
if ( wp_slimstat::$settings[ 'convert_ip_addresses' ] == 'on' ) {
|
67 |
$gethostbyaddr = gethostbyaddr( $results[ $i ][ 'ip' ] );
|
68 |
if ( $gethostbyaddr != $host_by_ip && !empty( $gethostbyaddr ) ) {
|
69 |
$host_by_ip .= ', ' . $gethostbyaddr;
|
79 |
$highlight_row = !empty($results[$i]['searchterms'])?' is-search-engine':(($results[$i]['browser_type'] != 1)?' is-direct':'');
|
80 |
|
81 |
// Country
|
82 |
+
$country_filtered = "<a class='slimstat-filter-link inline-icon' href='".wp_slimstat_reports::fs_url('country equals '.$results[$i]['country'])."'><img class='slimstat-tooltip-trigger' src='$plugin_url/images/flags/{$results[$i]['country']}.png' width='16' height='16' title='" . __('c-'.$results[$i]['country'],'wp-slimstat') . "'></a>";
|
83 |
+
|
84 |
+
// City, if tracked
|
85 |
+
$city_filtered = '';
|
86 |
+
if ( !empty( $results[ $i ][ 'city' ] ) ) {
|
87 |
+
$city_filtered = "<a class='slimstat-filter-link' href='" . wp_slimstat_reports::fs_url( 'city equals ' . $results[ $i ][ 'city' ] ) . "'>{$results[ $i ][ 'city' ]}</a>";
|
88 |
+
}
|
89 |
|
90 |
// Browser
|
91 |
if ($results[$i]['browser_version'] == 0) $results[$i]['browser_version'] = '';
|
92 |
+
$browser_title = ( wp_slimstat::$settings[ 'show_complete_user_agent_tooltip' ] != 'on' ) ? "{$results[ $i ][ 'browser' ]} {$results[ $i ][ 'browser_version' ]}" : $results[ $i ][ 'user_agent' ];
|
93 |
$browser_icon = $plugin_url.'/images/browsers/other-browsers-and-os.png';
|
94 |
if (in_array($results[$i]['browser'], $supported_browser_icons)){
|
95 |
$browser_icon = $plugin_url.'/images/browsers/'.sanitize_title($results[$i]['browser']).'.png';
|
115 |
}
|
116 |
else{
|
117 |
$display_user_name = $results[ $i ][ 'username' ];
|
118 |
+
if ( wp_slimstat::$settings[ 'show_display_name' ] == 'on' && strpos( $results[ $i ][ 'notes' ], 'user:' ) !== false ) {
|
119 |
$display_real_name = get_user_by('login', $results[$i]['username']);
|
120 |
if (is_object($display_real_name)) $display_user_name = $display_real_name->display_name;
|
121 |
}
|
124 |
$highlight_row = (strpos( $results[$i]['notes'], 'user:') !== false)?' is-known-user':' is-known-visitor';
|
125 |
|
126 |
}
|
127 |
+
|
128 |
+
$whois_pin = '';
|
129 |
+
if ( is_admin() && !empty( wp_slimstat::$settings[ 'ip_lookup_service' ] ) && !in_array( $results[ $i ][ 'country' ], array( 'xx', 'xy' ) ) ) {
|
130 |
+
$whois_pin = "<a class='slimstat-font-location-1 whois' href='" . wp_slimstat::$settings[ 'ip_lookup_service' ] . "{$results[ $i ][ 'ip' ]}' target='_blank' title='WHOIS: {$results[ $i ][ 'ip' ]}'></a>";
|
131 |
}
|
132 |
|
133 |
// Originating IP Address
|
155 |
$screen_resolution = "<span class='pageview-screenres'>{$results[ $i ][ 'screen_width' ]}x{$results[ $i ][ 'screen_height' ]}</span>";
|
156 |
}
|
157 |
|
158 |
+
$row_output = "<p class='header$highlight_row'>$browser_filtered $platform_filtered $browser_type_filtered $country_filtered $whois_pin $city_filtered $ip_address $other_ip_address <span class='plugins'>$plugins</span> $screen_resolution</p>";
|
159 |
|
160 |
// Strip all the filter links, if this information is shown on the frontend
|
161 |
if ( !is_admin() ) {
|
admin/view/wp-slimstat-db.php
CHANGED
@@ -48,6 +48,8 @@ class wp_slimstat_db {
|
|
48 |
'browser_version' => array( __( 'Browser Version', 'wp-slimstat' ), 'varchar' ),
|
49 |
'browser_type' => array( __( 'Browser Type', 'wp-slimstat' ), 'int' ),
|
50 |
'user_agent' => array( __( 'User Agent', 'wp-slimstat' ), 'varchar' ),
|
|
|
|
|
51 |
'notes' => array( __( 'Annotations', 'wp-slimstat' ), 'varchar' ),
|
52 |
'server_latency' => array( __( 'Server Latency', 'wp-slimstat' ), 'int' ),
|
53 |
'author' => array( __( 'Post Author', 'wp-slimstat' ), 'varchar' ),
|
@@ -61,6 +63,11 @@ class wp_slimstat_db {
|
|
61 |
'visit_id' => array( __( 'Visit ID', 'wp-slimstat' ), 'int' )
|
62 |
);
|
63 |
|
|
|
|
|
|
|
|
|
|
|
64 |
// List of supported filters and their friendly names
|
65 |
self::$operator_names = array(
|
66 |
'equals' => __( 'equals', 'wp-slimstat' ),
|
@@ -143,7 +150,7 @@ class wp_slimstat_db {
|
|
143 |
}
|
144 |
|
145 |
// Hidden Filters
|
146 |
-
if ( wp_slimstat::$settings[ 'restrict_authors_view' ] == '
|
147 |
$filters_array[ 'author' ] = 'author equals ' . $GLOBALS[ 'current_user' ]->user_login;
|
148 |
}
|
149 |
|
@@ -281,7 +288,7 @@ class wp_slimstat_db {
|
|
281 |
$where = array( '', $_value );
|
282 |
switch ( $_operator ) {
|
283 |
case 'is_not_equal_to':
|
284 |
-
$where[0] = "$column_with_alias <> %s";
|
285 |
break;
|
286 |
|
287 |
case 'contains':
|
@@ -289,7 +296,7 @@ class wp_slimstat_db {
|
|
289 |
break;
|
290 |
|
291 |
case 'includes_in_set':
|
292 |
-
$where[0] = "FIND_IN_SET(%s, $column_with_alias) > 0";
|
293 |
break;
|
294 |
|
295 |
case 'does_not_contain':
|
@@ -305,7 +312,7 @@ class wp_slimstat_db {
|
|
305 |
break;
|
306 |
|
307 |
case 'sounds_like':
|
308 |
-
$where[0] = "SOUNDEX($column_with_alias) = SOUNDEX(%s)";
|
309 |
break;
|
310 |
|
311 |
case 'is_empty':
|
@@ -317,32 +324,32 @@ class wp_slimstat_db {
|
|
317 |
break;
|
318 |
|
319 |
case 'is_greater_than':
|
320 |
-
$where[0] = "$column_with_alias > %d";
|
321 |
break;
|
322 |
|
323 |
case 'is_less_than':
|
324 |
-
$where[0] = "$column_with_alias < %d";
|
325 |
break;
|
326 |
|
327 |
case 'between':
|
328 |
-
$range = explode(',', $_value);
|
329 |
-
$where = array( "$column_with_alias BETWEEN %d AND %d", array( $range[0], $range[1] ) );
|
330 |
break;
|
331 |
|
332 |
case 'matches':
|
333 |
-
$where[0] = "$column_with_alias REGEXP %s";
|
334 |
break;
|
335 |
|
336 |
case 'does_not_match':
|
337 |
-
$where[0] = "$column_with_alias NOT REGEXP %s";
|
338 |
break;
|
339 |
|
340 |
default:
|
341 |
-
$where[0] = "$column_with_alias = %s";
|
342 |
break;
|
343 |
}
|
344 |
|
345 |
-
if (
|
346 |
return $GLOBALS[ 'wpdb' ]->prepare( $where[ 0 ], $where[ 1 ] );
|
347 |
}
|
348 |
else {
|
@@ -353,7 +360,7 @@ class wp_slimstat_db {
|
|
353 |
public static function get_results( $_sql = '', $_select_no_aggregate_values = '', $_order_by = '', $_group_by = '', $_aggregate_values_add = '' ) {
|
354 |
$_sql = apply_filters( 'slimstat_get_results_sql', $_sql, $_select_no_aggregate_values, $_order_by, $_group_by, $_aggregate_values_add );
|
355 |
|
356 |
-
if ( wp_slimstat::$settings[ 'show_sql_debug' ] == '
|
357 |
self::$debug_message .= "<p class='debug'>$_sql</p>";
|
358 |
}
|
359 |
|
@@ -363,7 +370,7 @@ class wp_slimstat_db {
|
|
363 |
public static function get_var( $_sql = '', $_aggregate_value = '' ) {
|
364 |
$_sql = apply_filters( 'slimstat_get_var_sql', $_sql, $_aggregate_value );
|
365 |
|
366 |
-
if ( wp_slimstat::$settings[ 'show_sql_debug' ] == '
|
367 |
self::$debug_message .= "<p class='debug'>$_sql</p>";
|
368 |
}
|
369 |
|
@@ -482,7 +489,7 @@ class wp_slimstat_db {
|
|
482 |
}
|
483 |
|
484 |
// If the setting to use the last X days as default time span is enabled, we need to setup the "interval" variables
|
485 |
-
if ( ( empty( wp_slimstat::$settings[ 'use_current_month_timespan' ] ) || wp_slimstat::$settings[ 'use_current_month_timespan' ] != '
|
486 |
// Do not set the interval if another date filter has already been set
|
487 |
$is_date_filter_empty = true;
|
488 |
if ( !empty( $filters_normalized[ 'date' ] ) ) {
|
@@ -884,7 +891,7 @@ class wp_slimstat_db {
|
|
884 |
$columns .= ', ip, dt';
|
885 |
}
|
886 |
else {
|
887 |
-
$columns = 'id, ip, other_ip, username, country, referer, resource, searchterms, plugins, notes, visit_id, server_latency, page_performance, browser, browser_version, browser_type, platform, language, user_agent, resolution, screen_width, screen_height, content_type, category, author, content_id, outbound_resource, dt_out, dt';
|
888 |
}
|
889 |
|
890 |
if ( !empty( $_more_columns ) ) {
|
48 |
'browser_version' => array( __( 'Browser Version', 'wp-slimstat' ), 'varchar' ),
|
49 |
'browser_type' => array( __( 'Browser Type', 'wp-slimstat' ), 'int' ),
|
50 |
'user_agent' => array( __( 'User Agent', 'wp-slimstat' ), 'varchar' ),
|
51 |
+
'city' => array( __( 'City', 'wp-slimstat' ), 'varchar' ),
|
52 |
+
'location' => array( __( 'Coordinates', 'wp-slimstat' ), 'varchar' ),
|
53 |
'notes' => array( __( 'Annotations', 'wp-slimstat' ), 'varchar' ),
|
54 |
'server_latency' => array( __( 'Server Latency', 'wp-slimstat' ), 'int' ),
|
55 |
'author' => array( __( 'Post Author', 'wp-slimstat' ), 'varchar' ),
|
63 |
'visit_id' => array( __( 'Visit ID', 'wp-slimstat' ), 'int' )
|
64 |
);
|
65 |
|
66 |
+
if ( wp_slimstat::$settings[ 'geolocation_country' ] == 'on' ) {
|
67 |
+
unset( self::$columns_names[ 'city' ] );
|
68 |
+
unset( self::$columns_names[ 'location' ] );
|
69 |
+
}
|
70 |
+
|
71 |
// List of supported filters and their friendly names
|
72 |
self::$operator_names = array(
|
73 |
'equals' => __( 'equals', 'wp-slimstat' ),
|
150 |
}
|
151 |
|
152 |
// Hidden Filters
|
153 |
+
if ( wp_slimstat::$settings[ 'restrict_authors_view' ] == 'on' && !current_user_can( 'manage_options' ) && !empty( $GLOBALS[ 'current_user' ]->user_login ) ) {
|
154 |
$filters_array[ 'author' ] = 'author equals ' . $GLOBALS[ 'current_user' ]->user_login;
|
155 |
}
|
156 |
|
288 |
$where = array( '', $_value );
|
289 |
switch ( $_operator ) {
|
290 |
case 'is_not_equal_to':
|
291 |
+
$where[ 0 ] = "$column_with_alias <> %s";
|
292 |
break;
|
293 |
|
294 |
case 'contains':
|
296 |
break;
|
297 |
|
298 |
case 'includes_in_set':
|
299 |
+
$where[ 0 ] = "FIND_IN_SET(%s, $column_with_alias) > 0";
|
300 |
break;
|
301 |
|
302 |
case 'does_not_contain':
|
312 |
break;
|
313 |
|
314 |
case 'sounds_like':
|
315 |
+
$where[ 0 ] = "SOUNDEX($column_with_alias) = SOUNDEX(%s)";
|
316 |
break;
|
317 |
|
318 |
case 'is_empty':
|
324 |
break;
|
325 |
|
326 |
case 'is_greater_than':
|
327 |
+
$where[ 0 ] = "$column_with_alias > %d";
|
328 |
break;
|
329 |
|
330 |
case 'is_less_than':
|
331 |
+
$where[ 0 ] = "$column_with_alias < %d";
|
332 |
break;
|
333 |
|
334 |
case 'between':
|
335 |
+
$range = explode( ',', $_value );
|
336 |
+
$where = array( "$column_with_alias BETWEEN %d AND %d", array( $range[ 0 ], $range[ 1 ] ) );
|
337 |
break;
|
338 |
|
339 |
case 'matches':
|
340 |
+
$where[ 0 ] = "$column_with_alias REGEXP %s";
|
341 |
break;
|
342 |
|
343 |
case 'does_not_match':
|
344 |
+
$where[ 0 ] = "$column_with_alias NOT REGEXP %s";
|
345 |
break;
|
346 |
|
347 |
default:
|
348 |
+
$where[ 0 ] = "$column_with_alias = %s";
|
349 |
break;
|
350 |
}
|
351 |
|
352 |
+
if ( !empty( $where[ 1 ] ) ) {
|
353 |
return $GLOBALS[ 'wpdb' ]->prepare( $where[ 0 ], $where[ 1 ] );
|
354 |
}
|
355 |
else {
|
360 |
public static function get_results( $_sql = '', $_select_no_aggregate_values = '', $_order_by = '', $_group_by = '', $_aggregate_values_add = '' ) {
|
361 |
$_sql = apply_filters( 'slimstat_get_results_sql', $_sql, $_select_no_aggregate_values, $_order_by, $_group_by, $_aggregate_values_add );
|
362 |
|
363 |
+
if ( wp_slimstat::$settings[ 'show_sql_debug' ] == 'on' ) {
|
364 |
self::$debug_message .= "<p class='debug'>$_sql</p>";
|
365 |
}
|
366 |
|
370 |
public static function get_var( $_sql = '', $_aggregate_value = '' ) {
|
371 |
$_sql = apply_filters( 'slimstat_get_var_sql', $_sql, $_aggregate_value );
|
372 |
|
373 |
+
if ( wp_slimstat::$settings[ 'show_sql_debug' ] == 'on' ) {
|
374 |
self::$debug_message .= "<p class='debug'>$_sql</p>";
|
375 |
}
|
376 |
|
489 |
}
|
490 |
|
491 |
// If the setting to use the last X days as default time span is enabled, we need to setup the "interval" variables
|
492 |
+
if ( ( empty( wp_slimstat::$settings[ 'use_current_month_timespan' ] ) || wp_slimstat::$settings[ 'use_current_month_timespan' ] != 'on' ) ) {
|
493 |
// Do not set the interval if another date filter has already been set
|
494 |
$is_date_filter_empty = true;
|
495 |
if ( !empty( $filters_normalized[ 'date' ] ) ) {
|
891 |
$columns .= ', ip, dt';
|
892 |
}
|
893 |
else {
|
894 |
+
$columns = 'id, ip, other_ip, username, country, city, location, referer, resource, searchterms, plugins, notes, visit_id, server_latency, page_performance, browser, browser_version, browser_type, platform, language, user_agent, resolution, screen_width, screen_height, content_type, category, author, content_id, outbound_resource, dt_out, dt';
|
895 |
}
|
896 |
|
897 |
if ( !empty( $_more_columns ) ) {
|
admin/view/wp-slimstat-reports.php
CHANGED
@@ -527,20 +527,6 @@ class wp_slimstat_reports {
|
|
527 |
'screens' => array( 'slimview5', 'dashboard' )
|
528 |
),
|
529 |
|
530 |
-
/*
|
531 |
-
'slim_p3_11' => array(
|
532 |
-
'title' => __( 'Recent Exit Pages', 'wp-slimstat' ),
|
533 |
-
'callback' => array( __CLASS__, 'raw_results_to_html' ),
|
534 |
-
'callback_args' => array(
|
535 |
-
'type' => 'recent',
|
536 |
-
'columns' => 'visit_id, resource', // raw_results_to_html knows to display the resource, when the column is visit_id
|
537 |
-
'raw' => array( 'wp_slimstat_db', 'get_recent' )
|
538 |
-
),
|
539 |
-
'classes' => array( 'normal' ),
|
540 |
-
'screens' => array( 'slimview5' )
|
541 |
-
),
|
542 |
-
*/
|
543 |
-
|
544 |
'slim_p4_01' => array(
|
545 |
'title' => __( 'Recent Outbound Links', 'wp-slimstat' ),
|
546 |
'callback' => array( __CLASS__, 'raw_results_to_html' ),
|
@@ -565,22 +551,6 @@ class wp_slimstat_reports {
|
|
565 |
'classes' => array( 'normal' ),
|
566 |
'screens' => array( 'slimview4' )
|
567 |
),
|
568 |
-
/*
|
569 |
-
'slim_p4_03' => array(
|
570 |
-
'title' => __( 'Recent Bounce Pages', 'wp-slimstat' ),
|
571 |
-
'callback' => array( __CLASS__, 'raw_results_to_html' ),
|
572 |
-
'callback_args' => array(
|
573 |
-
'type' => 'recent',
|
574 |
-
'columns' => 'resource',
|
575 |
-
'where' => 'content_type <> "404"',
|
576 |
-
'having' => 'HAVING COUNT(visit_id) = 1',
|
577 |
-
'raw' => array( 'wp_slimstat_db', 'get_recent' )
|
578 |
-
),
|
579 |
-
'classes' => array( 'normal', 'hidden' ),
|
580 |
-
'screens' => array( 'slimview4' ),
|
581 |
-
'tooltip' => __( 'A <em>bounce page</em> is a single-page visit, or visit in which the person left your site from the entrance (landing) page.', 'wp-slimstat' )
|
582 |
-
),
|
583 |
-
*/
|
584 |
'slim_p4_04' => array(
|
585 |
'title' => __( 'Recent Feeds', 'wp-slimstat' ),
|
586 |
'callback' => array( __CLASS__, 'raw_results_to_html' ),
|
@@ -844,6 +814,21 @@ class wp_slimstat_reports {
|
|
844 |
)
|
845 |
);
|
846 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
847 |
// Allow third party tools to manipulate this list here above: please use unique report IDs that don't interfere with built-in ones, if you add your own custom report
|
848 |
self::$reports_info = apply_filters( 'slimstat_reports_info', self::$reports_info );
|
849 |
|
@@ -866,7 +851,7 @@ class wp_slimstat_reports {
|
|
866 |
|
867 |
// Retrieve this user's list of active reports,
|
868 |
$current_user = wp_get_current_user();
|
869 |
-
$page_location = ( wp_slimstat::$settings[ 'use_separate_menu' ] == '
|
870 |
|
871 |
// Superadmins can customize the layout at network level, to override per-site settings
|
872 |
self::$user_reports = get_user_option( "meta-box-order_slimstat_page_slimlayout-network", 1 );
|
@@ -998,7 +983,7 @@ class wp_slimstat_reports {
|
|
998 |
}
|
999 |
|
1000 |
public static function raw_results_to_html( $_args = array() ) {
|
1001 |
-
if ( wp_slimstat::$settings[ 'async_load' ] == '
|
1002 |
return '';
|
1003 |
}
|
1004 |
|
@@ -1020,7 +1005,7 @@ class wp_slimstat_reports {
|
|
1020 |
echo "{$a_result[ 'metric' ]} <span>{$a_result[ 'value' ]}</span>";
|
1021 |
|
1022 |
if ( !empty( $a_result[ 'details' ] ) ) {
|
1023 |
-
$is_expanded = ( wp_slimstat::$settings[ 'expand_details' ] == '
|
1024 |
echo "<b class='slimstat-tooltip-content$is_expanded'>{$a_result[ 'details' ]}</b>";
|
1025 |
}
|
1026 |
|
@@ -1064,7 +1049,7 @@ class wp_slimstat_reports {
|
|
1064 |
|
1065 |
echo self::report_pagination( $count_page_results, count( $all_results ) );
|
1066 |
|
1067 |
-
$is_expanded = ( is_admin() && wp_slimstat::$settings[ 'expand_details' ] == '
|
1068 |
$permalinks_enabled = get_option( 'permalink_structure' );
|
1069 |
$column_not_calculated = str_replace( '_calculated', '', $_args[ 'columns' ] );
|
1070 |
|
@@ -1077,7 +1062,7 @@ class wp_slimstat_reports {
|
|
1077 |
switch ( $column_not_calculated ){
|
1078 |
|
1079 |
case 'browser':
|
1080 |
-
if ( !empty( $results[ $i ][ 'user_agent' ] ) && wp_slimstat::$settings[ 'show_complete_user_agent_tooltip' ] == '
|
1081 |
$element_pre_value = self::inline_help($results[$i]['user_agent'], false);
|
1082 |
}
|
1083 |
$element_value = $results[$i]['browser'].((isset($results[$i]['browser_version']) && intval($results[$i]['browser_version']) != 0)?' '.$results[$i]['browser_version']:'');
|
@@ -1094,7 +1079,7 @@ class wp_slimstat_reports {
|
|
1094 |
break;
|
1095 |
|
1096 |
case 'ip':
|
1097 |
-
if ( wp_slimstat::$settings[ 'convert_ip_addresses' ] == '
|
1098 |
$element_value = gethostbyaddr( $results[ $i ][ $_args[ 'columns' ] ] );
|
1099 |
}
|
1100 |
else{
|
@@ -1150,7 +1135,7 @@ class wp_slimstat_reports {
|
|
1150 |
|
1151 |
case 'username':
|
1152 |
$element_value = $results[ $i ][ 'username' ];
|
1153 |
-
if ( wp_slimstat::$settings[ 'show_display_name' ] == '
|
1154 |
$element_custom_value = get_user_by( 'login', $results[ $i ][ 'username' ] );
|
1155 |
if ( is_object( $element_custom_value ) ) {
|
1156 |
$element_value = $element_custom_value->display_name;
|
@@ -1210,7 +1195,7 @@ class wp_slimstat_reports {
|
|
1210 |
$element_value = '<a target="_blank" class="slimstat-font-logout" title="'.__('Open this URL in a new window','wp-slimstat').'" href="'.$element_url.'"></a> '.$element_value;
|
1211 |
}
|
1212 |
|
1213 |
-
if ( is_admin() && !empty( $results[ $i ][ 'ip' ]) && $_args[ 'columns' ] != 'ip' && wp_slimstat::$settings[ 'convert_ip_addresses' ] != '
|
1214 |
$row_details .= '<br> IP: <a class="slimstat-filter-link" href="'.self::fs_url( 'ip equals ' . $results[ $i ][ 'ip' ] ) . '">' . $results[ $i ][ 'ip' ] . '</a>' . ( !empty( $results[ $i ][ 'other_ip' ] ) ? ' / ' . $results[ $i ][ 'other_ip' ] : '' ) . '<a title="WHOIS: ' . $results[ $i ][ 'ip' ] . '" class="slimstat-font-location-1 whois" href="' . wp_slimstat::$settings[ 'ip_lookup_service' ] . $results[ $i ][ 'ip' ] . '"></a>';
|
1215 |
}
|
1216 |
if ( !empty( $row_details ) ) {
|
@@ -1821,7 +1806,7 @@ class wp_slimstat_reports {
|
|
1821 |
}
|
1822 |
|
1823 |
echo self::report_pagination( $count_page_results, count( $all_results ) );
|
1824 |
-
$is_expanded = ( wp_slimstat::$settings[ 'expand_details' ] == '
|
1825 |
|
1826 |
foreach ( $results as $a_result ) {
|
1827 |
echo "<p class='slimstat-tooltip-trigger'>{$a_result[ 'notes' ]} <b class='slimstat-tooltip-content$is_expanded'>" . __( 'Type', 'wp-slimstat' ) . ": {$a_result[ 'type' ]}";
|
@@ -2037,7 +2022,7 @@ class wp_slimstat_reports {
|
|
2037 |
public static function get_resource_title( $_resource = '' ) {
|
2038 |
$resource_title = $_resource;
|
2039 |
|
2040 |
-
if ( wp_slimstat::$settings[ 'convert_resource_urls_to_titles' ] != '
|
2041 |
return htmlentities( urldecode( $resource_title ), ENT_QUOTES, 'UTF-8' );
|
2042 |
}
|
2043 |
|
527 |
'screens' => array( 'slimview5', 'dashboard' )
|
528 |
),
|
529 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
530 |
'slim_p4_01' => array(
|
531 |
'title' => __( 'Recent Outbound Links', 'wp-slimstat' ),
|
532 |
'callback' => array( __CLASS__, 'raw_results_to_html' ),
|
551 |
'classes' => array( 'normal' ),
|
552 |
'screens' => array( 'slimview4' )
|
553 |
),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
554 |
'slim_p4_04' => array(
|
555 |
'title' => __( 'Recent Feeds', 'wp-slimstat' ),
|
556 |
'callback' => array( __CLASS__, 'raw_results_to_html' ),
|
814 |
)
|
815 |
);
|
816 |
|
817 |
+
if ( wp_slimstat::$settings[ 'geolocation_country' ] != 'on' ) {
|
818 |
+
self::$reports_info [ 'slim_p2_23' ] = array(
|
819 |
+
'title' => __( 'Top Cities', 'wp-slimstat' ),
|
820 |
+
'callback' => array( __CLASS__, 'raw_results_to_html' ),
|
821 |
+
'callback_args' => array(
|
822 |
+
'type' => 'top',
|
823 |
+
'columns' => 'city',
|
824 |
+
|
825 |
+
'raw' => array( 'wp_slimstat_db', 'get_top' )
|
826 |
+
),
|
827 |
+
'classes' => array( 'normal' ),
|
828 |
+
'screens' => array( 'slimview3' )
|
829 |
+
);
|
830 |
+
}
|
831 |
+
|
832 |
// Allow third party tools to manipulate this list here above: please use unique report IDs that don't interfere with built-in ones, if you add your own custom report
|
833 |
self::$reports_info = apply_filters( 'slimstat_reports_info', self::$reports_info );
|
834 |
|
851 |
|
852 |
// Retrieve this user's list of active reports,
|
853 |
$current_user = wp_get_current_user();
|
854 |
+
$page_location = ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'on' ) ? 'slimstat' : 'admin';
|
855 |
|
856 |
// Superadmins can customize the layout at network level, to override per-site settings
|
857 |
self::$user_reports = get_user_option( "meta-box-order_slimstat_page_slimlayout-network", 1 );
|
983 |
}
|
984 |
|
985 |
public static function raw_results_to_html( $_args = array() ) {
|
986 |
+
if ( wp_slimstat::$settings[ 'async_load' ] == 'on' && ( !defined( 'DOING_AJAX' ) || !DOING_AJAX ) ) {
|
987 |
return '';
|
988 |
}
|
989 |
|
1005 |
echo "{$a_result[ 'metric' ]} <span>{$a_result[ 'value' ]}</span>";
|
1006 |
|
1007 |
if ( !empty( $a_result[ 'details' ] ) ) {
|
1008 |
+
$is_expanded = ( wp_slimstat::$settings[ 'expand_details' ] == 'on' ) ? ' expanded' : '';
|
1009 |
echo "<b class='slimstat-tooltip-content$is_expanded'>{$a_result[ 'details' ]}</b>";
|
1010 |
}
|
1011 |
|
1049 |
|
1050 |
echo self::report_pagination( $count_page_results, count( $all_results ) );
|
1051 |
|
1052 |
+
$is_expanded = ( is_admin() && wp_slimstat::$settings[ 'expand_details' ] == 'on' ) ? ' expanded' : '';
|
1053 |
$permalinks_enabled = get_option( 'permalink_structure' );
|
1054 |
$column_not_calculated = str_replace( '_calculated', '', $_args[ 'columns' ] );
|
1055 |
|
1062 |
switch ( $column_not_calculated ){
|
1063 |
|
1064 |
case 'browser':
|
1065 |
+
if ( !empty( $results[ $i ][ 'user_agent' ] ) && wp_slimstat::$settings[ 'show_complete_user_agent_tooltip' ] == 'on' ) {
|
1066 |
$element_pre_value = self::inline_help($results[$i]['user_agent'], false);
|
1067 |
}
|
1068 |
$element_value = $results[$i]['browser'].((isset($results[$i]['browser_version']) && intval($results[$i]['browser_version']) != 0)?' '.$results[$i]['browser_version']:'');
|
1079 |
break;
|
1080 |
|
1081 |
case 'ip':
|
1082 |
+
if ( wp_slimstat::$settings[ 'convert_ip_addresses' ] == 'on' ) {
|
1083 |
$element_value = gethostbyaddr( $results[ $i ][ $_args[ 'columns' ] ] );
|
1084 |
}
|
1085 |
else{
|
1135 |
|
1136 |
case 'username':
|
1137 |
$element_value = $results[ $i ][ 'username' ];
|
1138 |
+
if ( wp_slimstat::$settings[ 'show_display_name' ] == 'on' ) {
|
1139 |
$element_custom_value = get_user_by( 'login', $results[ $i ][ 'username' ] );
|
1140 |
if ( is_object( $element_custom_value ) ) {
|
1141 |
$element_value = $element_custom_value->display_name;
|
1195 |
$element_value = '<a target="_blank" class="slimstat-font-logout" title="'.__('Open this URL in a new window','wp-slimstat').'" href="'.$element_url.'"></a> '.$element_value;
|
1196 |
}
|
1197 |
|
1198 |
+
if ( is_admin() && !empty( $results[ $i ][ 'ip' ]) && $_args[ 'columns' ] != 'ip' && wp_slimstat::$settings[ 'convert_ip_addresses' ] != 'on' ) {
|
1199 |
$row_details .= '<br> IP: <a class="slimstat-filter-link" href="'.self::fs_url( 'ip equals ' . $results[ $i ][ 'ip' ] ) . '">' . $results[ $i ][ 'ip' ] . '</a>' . ( !empty( $results[ $i ][ 'other_ip' ] ) ? ' / ' . $results[ $i ][ 'other_ip' ] : '' ) . '<a title="WHOIS: ' . $results[ $i ][ 'ip' ] . '" class="slimstat-font-location-1 whois" href="' . wp_slimstat::$settings[ 'ip_lookup_service' ] . $results[ $i ][ 'ip' ] . '"></a>';
|
1200 |
}
|
1201 |
if ( !empty( $row_details ) ) {
|
1806 |
}
|
1807 |
|
1808 |
echo self::report_pagination( $count_page_results, count( $all_results ) );
|
1809 |
+
$is_expanded = ( wp_slimstat::$settings[ 'expand_details' ] == 'on' ) ? ' expanded' : '';
|
1810 |
|
1811 |
foreach ( $results as $a_result ) {
|
1812 |
echo "<p class='slimstat-tooltip-trigger'>{$a_result[ 'notes' ]} <b class='slimstat-tooltip-content$is_expanded'>" . __( 'Type', 'wp-slimstat' ) . ": {$a_result[ 'type' ]}";
|
2022 |
public static function get_resource_title( $_resource = '' ) {
|
2023 |
$resource_title = $_resource;
|
2024 |
|
2025 |
+
if ( wp_slimstat::$settings[ 'convert_resource_urls_to_titles' ] != 'on' ) {
|
2026 |
return htmlentities( urldecode( $resource_title ), ENT_QUOTES, 'UTF-8' );
|
2027 |
}
|
2028 |
|
admin/wp-slimstat-admin.php
CHANGED
@@ -11,9 +11,7 @@ class wp_slimstat_admin {
|
|
11 |
* Init -- Sets things up.
|
12 |
*/
|
13 |
public static function init() {
|
14 |
-
self::$admin_notice = "
|
15 |
-
|
16 |
-
// "As those who have been using Slimstat for a while know, we never stop doing our good share of research and development to imrpove this plugin. One request that has been sitting on our wishlist for a while is to make our geolocation functionality more accurate, and track not just a user's Country of origin, but possibly his State (where applicable) and city. In order to geolocate visitors, our code has been leveraging a third-party data file provided by <a href='https://www.maxmind.com/en/home' target='_blank'>MaxMind.com</a>. A while ago, they launched a new data format, which improves performance and offers a way to determine the city of origin. However, the new library required a higher version of PHP, and up until now we had preferred allowing more people to use our plugin, over the chance of offering this feature. Now, we found a way to get the best of both worlds: by customizing their PHP library, we were able to make it work with PHP 5.3! Which means that soon Slimstat will be able to tell you your visitors' city of origin right out of the box. Please contact us if you would like to test this feature in advance."
|
17 |
|
18 |
self::$admin_notice .= '<br/><br/><a id="slimstat-hide-admin-notice" href="#" class="button-secondary">Got it, thanks</a>';
|
19 |
|
@@ -115,12 +113,12 @@ class wp_slimstat_admin {
|
|
115 |
}
|
116 |
|
117 |
// Remove spammers from the database
|
118 |
-
if (wp_slimstat::$settings['ignore_spammers'] == '
|
119 |
add_action('transition_comment_status', array(__CLASS__, 'remove_spam'), 15, 3);
|
120 |
}
|
121 |
|
122 |
// Add a menu to the admin bar ( this function is declared here and not in wp_slimstat_admin because the latter is only initialized if is_admin(), and not in the front-end )
|
123 |
-
if ( wp_slimstat::$settings[ 'use_separate_menu' ] != '
|
124 |
add_action( 'admin_bar_menu', array( __CLASS__, 'wp_slimstat_adminbar' ), 100 );
|
125 |
}
|
126 |
|
@@ -130,7 +128,7 @@ class wp_slimstat_admin {
|
|
130 |
add_action( 'admin_menu', array( __CLASS__, 'wp_slimstat_add_config_menu' ) );
|
131 |
|
132 |
// Display the column in the Edit Posts / Pages screen
|
133 |
-
if ( wp_slimstat::$settings[ 'add_posts_column' ] == '
|
134 |
$post_types = get_post_types( array( 'public' => true, 'show_ui' => true ), 'names' );
|
135 |
include_once( dirname( __FILE__ ) . '/view/wp-slimstat-reports.php' );
|
136 |
include_once( dirname( __FILE__ ) . '/view/wp-slimstat-db.php' );
|
@@ -169,7 +167,7 @@ class wp_slimstat_admin {
|
|
169 |
}
|
170 |
|
171 |
// Dashboard Widgets
|
172 |
-
if ( wp_slimstat::$settings[ 'add_dashboard_widgets' ] == '
|
173 |
$temp = strlen( $_SERVER['REQUEST_URI'] ) - 10;
|
174 |
|
175 |
if( strpos( $_SERVER['REQUEST_URI'], 'index.php' ) !== false || ( $temp >= 0 && strpos($_SERVER['REQUEST_URI'], '/wp-admin/', $temp) !== false ) ) {
|
@@ -194,7 +192,7 @@ class wp_slimstat_admin {
|
|
194 |
}
|
195 |
|
196 |
// Hide plugins
|
197 |
-
if ( wp_slimstat::$settings[ 'hide_addons' ] == '
|
198 |
add_filter( 'all_plugins', array( __CLASS__, 'hide_addons' ) );
|
199 |
}
|
200 |
}
|
@@ -352,245 +350,11 @@ class wp_slimstat_admin {
|
|
352 |
public static function update_tables_and_options(){
|
353 |
$my_wpdb = apply_filters('slimstat_custom_wpdb', $GLOBALS['wpdb']);
|
354 |
|
355 |
-
// --- Updates for version 3.8.4 ---
|
356 |
-
if ( version_compare( wp_slimstat::$settings[ 'version' ], '3.8.4', '<' ) ) {
|
357 |
-
$my_wpdb->query( "CREATE TABLE {$GLOBALS['wpdb']->prefix}slim_stats_archive LIKE {$GLOBALS['wpdb']->prefix}slim_stats" );
|
358 |
-
}
|
359 |
-
// --- END: Updates for version 3.8.4 ---
|
360 |
-
|
361 |
-
// --- Updates for version 3.9.6 ---
|
362 |
-
if ( version_compare( wp_slimstat::$settings[ 'version' ], '3.9.6', '<' ) ) {
|
363 |
-
// Consolidate some settings
|
364 |
-
$classes = wp_slimstat::string_to_array( wp_slimstat::$settings[ 'ignore_outbound_classes' ] );
|
365 |
-
$rel = wp_slimstat::string_to_array( wp_slimstat::$settings[ 'ignore_outbound_rel' ] );
|
366 |
-
$href = wp_slimstat::string_to_array( wp_slimstat::$settings[ 'ignore_outbound_href' ] );
|
367 |
-
wp_slimstat::$settings[ 'ignore_outbound_classes_rel_href' ] = implode( ',', array_merge( $classes, $rel, $href ) );
|
368 |
-
|
369 |
-
$classes = wp_slimstat::string_to_array( wp_slimstat::$settings[ 'do_not_track_outbound_classes' ] );
|
370 |
-
$rel = wp_slimstat::string_to_array( wp_slimstat::$settings[ 'do_not_track_outbound_rel' ] );
|
371 |
-
$href = wp_slimstat::string_to_array( wp_slimstat::$settings[ 'do_not_track_outbound_href' ] );
|
372 |
-
wp_slimstat::$settings[ 'do_not_track_outbound_classes_rel_href' ] = implode( ',', array_merge( $classes, $rel, $href ) );
|
373 |
-
|
374 |
-
// Make secret key really... secret!
|
375 |
-
wp_slimstat::$settings[ 'secret' ] = wp_hash( uniqid( time(), true ) );
|
376 |
-
}
|
377 |
-
// --- END: Updates for version 3.9.6 ---
|
378 |
-
|
379 |
-
// --- Updates for version 3.9.8.2 ---
|
380 |
-
if ( version_compare( wp_slimstat::$settings[ 'version' ], '3.9.8.2', '<' ) ) {
|
381 |
-
// The GeoLite DB is already installed, let's unzip it to improve the tracker's performance
|
382 |
-
if ( file_exists( wp_slimstat::$maxmind_path.'.gz' ) ) {
|
383 |
-
@unlink( wp_slimstat::$maxmind_path.'.gz' );
|
384 |
-
wp_slimstat::download_maxmind_database();
|
385 |
-
}
|
386 |
-
}
|
387 |
-
// --- END: Updates for version 3.9.8.2 ---
|
388 |
-
|
389 |
-
// --- Updates for version 4.0 ---
|
390 |
-
if ( version_compare( wp_slimstat::$settings[ 'version' ], '4.0', '<' ) ) {
|
391 |
-
$GLOBALS['wpdb']->query( "DELETE FROM {$GLOBALS[ 'wpdb' ]->prefix}usermeta WHERE meta_key LIKE 'meta-box-order_slimstat%'" );
|
392 |
-
|
393 |
-
$have_innodb = $GLOBALS[ 'wpdb' ]->get_results( "SHOW VARIABLES LIKE 'have_innodb'", ARRAY_A );
|
394 |
-
$use_innodb = ( !empty( $have_innodb[ 0 ] ) && $have_innodb[ 0 ][ 'Value' ] == 'YES' ) ? 'ENGINE=InnoDB' : '';
|
395 |
-
|
396 |
-
// Create the new table
|
397 |
-
self::_create_table ("
|
398 |
-
CREATE TABLE IF NOT EXISTS {$GLOBALS['wpdb']->prefix}slim_stats_4 (
|
399 |
-
id INT UNSIGNED NOT NULL auto_increment,
|
400 |
-
ip INT UNSIGNED DEFAULT 0,
|
401 |
-
other_ip INT UNSIGNED DEFAULT 0,
|
402 |
-
username VARCHAR(255) DEFAULT NULL,
|
403 |
-
country VARCHAR(16) DEFAULT NULL,
|
404 |
-
referer VARCHAR(2048) DEFAULT NULL,
|
405 |
-
resource VARCHAR(2048) DEFAULT NULL,
|
406 |
-
searchterms VARCHAR(2048) DEFAULT NULL,
|
407 |
-
plugins VARCHAR(255) DEFAULT NULL,
|
408 |
-
notes VARCHAR(2048) DEFAULT NULL,
|
409 |
-
visit_id INT UNSIGNED NOT NULL DEFAULT 0,
|
410 |
-
server_latency INT(10) UNSIGNED DEFAULT 0,
|
411 |
-
page_performance INT(10) UNSIGNED DEFAULT 0,
|
412 |
-
|
413 |
-
browser VARCHAR(40) DEFAULT NULL,
|
414 |
-
browser_version VARCHAR(15) DEFAULT NULL,
|
415 |
-
browser_type TINYINT UNSIGNED DEFAULT 0,
|
416 |
-
platform VARCHAR(15) DEFAULT NULL,
|
417 |
-
language VARCHAR(5) DEFAULT NULL,
|
418 |
-
user_agent VARCHAR(2048) DEFAULT NULL,
|
419 |
-
|
420 |
-
resolution VARCHAR(12) DEFAULT NULL,
|
421 |
-
screen_width SMALLINT UNSIGNED DEFAULT 0,
|
422 |
-
screen_height SMALLINT UNSIGNED DEFAULT 0,
|
423 |
-
|
424 |
-
content_type VARCHAR(64) DEFAULT NULL,
|
425 |
-
category VARCHAR(256) DEFAULT NULL,
|
426 |
-
author VARCHAR(64) DEFAULT NULL,
|
427 |
-
content_id BIGINT(20) UNSIGNED DEFAULT 0,
|
428 |
-
|
429 |
-
outbound_resource VARCHAR(2048) DEFAULT NULL,
|
430 |
-
|
431 |
-
dt INT(10) UNSIGNED DEFAULT 0,
|
432 |
-
|
433 |
-
CONSTRAINT PRIMARY KEY (id),
|
434 |
-
INDEX idx_{$GLOBALS['wpdb']->prefix}slim_stats_dt (dt)
|
435 |
-
) COLLATE utf8_general_ci $use_innodb", $GLOBALS[ 'wpdb' ]->prefix . 'slim_stats_4', $my_wpdb );
|
436 |
-
|
437 |
-
// Create the archive table
|
438 |
-
$my_wpdb->query( "CREATE TABLE IF NOT EXISTS {$GLOBALS['wpdb']->prefix}slim_stats_archive_4 LIKE {$GLOBALS['wpdb']->prefix}slim_stats_4" );
|
439 |
-
|
440 |
-
// Rename old and new tables
|
441 |
-
$my_wpdb->query( "SET foreign_key_checks = 0" );
|
442 |
-
$my_wpdb->query( "RENAME TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats TO {$GLOBALS[ 'wpdb' ]->prefix}slim_stats_3" );
|
443 |
-
$my_wpdb->query( "RENAME TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats_4 TO {$GLOBALS[ 'wpdb' ]->prefix}slim_stats" );
|
444 |
-
$my_wpdb->query( "RENAME TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats_archive TO {$GLOBALS[ 'wpdb' ]->prefix}slim_stats_archive_3" );
|
445 |
-
$my_wpdb->query( "RENAME TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats_archive_4 TO {$GLOBALS[ 'wpdb' ]->prefix}slim_stats_archive" );
|
446 |
-
|
447 |
-
// Sometimes db users are not granted the capability to rename tables
|
448 |
-
$slim_stats_4_exists = $my_wpdb->get_col( "SHOW TABLES LIKE '{$GLOBALS[ 'wpdb' ]->prefix}slim_stats_4'", 0 );
|
449 |
-
$resolution_exists = $my_wpdb->get_results( "SHOW COLUMNS FROM {$GLOBALS[ 'wpdb' ]->prefix}slim_stats LIKE 'resolution'" );
|
450 |
-
|
451 |
-
// Something went wrong during the upgrade
|
452 |
-
if ( !empty( $slim_stats_4_exists ) && empty( $resolution_exists ) ) {
|
453 |
-
self::$admin_notice = __( "Slimstat attempted to upgrade your database structure, but the procedure might not have been completed (temporary tables were detected in your database). This might be caused by restrictive user permissions that don't grant commands like RENAME, ALTER/CHANGE and others. You might need to manually consolidate your tables. No worries, we wrote a <a href='https://slimstat.freshdesk.com/support/solutions/articles/12000003148-how-do-i-update-the-table-structure-if-i-upgraded-from-a-version-prior-to-4-0' target='_blank'>step by step guide</a> on how to do that. Please feel free to contact our support team if you have any questions.", 'wp-slimstat' );
|
454 |
-
self::$admin_notice .= '<br/><br/><a id="slimstat-hide-admin-notice" href="#" class="button-secondary">Got it, thanks</a>';
|
455 |
-
return 0;
|
456 |
-
}
|
457 |
-
|
458 |
-
// Create the new events table
|
459 |
-
$my_wpdb->query( "
|
460 |
-
CREATE TABLE IF NOT EXISTS {$GLOBALS[ 'wpdb' ]->prefix}slim_events (
|
461 |
-
event_id INT(10) NOT NULL AUTO_INCREMENT,
|
462 |
-
type TINYINT UNSIGNED DEFAULT 0,
|
463 |
-
event_description VARCHAR(64) DEFAULT NULL,
|
464 |
-
notes VARCHAR(256) DEFAULT NULL,
|
465 |
-
position VARCHAR(32) DEFAULT NULL,
|
466 |
-
id INT UNSIGNED NOT NULL DEFAULT 0,
|
467 |
-
dt INT(10) UNSIGNED DEFAULT 0,
|
468 |
-
|
469 |
-
CONSTRAINT PRIMARY KEY (event_id),
|
470 |
-
INDEX idx_{$GLOBALS['wpdb']->prefix}slim_events (dt),
|
471 |
-
CONSTRAINT fk_{$GLOBALS['wpdb']->prefix}id FOREIGN KEY (id) REFERENCES {$GLOBALS['wpdb']->prefix}slim_stats(id) ON UPDATE CASCADE ON DELETE CASCADE
|
472 |
-
) COLLATE utf8_general_ci $use_innodb" );
|
473 |
-
|
474 |
-
$my_wpdb->query( "
|
475 |
-
INSERT INTO {$GLOBALS['wpdb']->prefix}slim_stats (
|
476 |
-
id,
|
477 |
-
ip,
|
478 |
-
other_ip,
|
479 |
-
username,
|
480 |
-
country,
|
481 |
-
referer,
|
482 |
-
resource,
|
483 |
-
searchterms,
|
484 |
-
plugins,
|
485 |
-
notes,
|
486 |
-
visit_id,
|
487 |
-
server_latency,
|
488 |
-
page_performance,
|
489 |
-
|
490 |
-
browser,
|
491 |
-
browser_version,
|
492 |
-
browser_type,
|
493 |
-
platform,
|
494 |
-
language,
|
495 |
-
user_agent,
|
496 |
-
|
497 |
-
screen_width,
|
498 |
-
screen_height,
|
499 |
-
|
500 |
-
content_type,
|
501 |
-
category,
|
502 |
-
author,
|
503 |
-
content_id,
|
504 |
-
|
505 |
-
outbound_resource,
|
506 |
-
|
507 |
-
dt
|
508 |
-
)
|
509 |
-
SELECT
|
510 |
-
t1.id,
|
511 |
-
t1.ip,
|
512 |
-
t1.other_ip,
|
513 |
-
NULLIF(t1.user, ''),
|
514 |
-
NULLIF(t1.country, ''),
|
515 |
-
NULLIF(t1.referer, ''),
|
516 |
-
NULLIF(t1.resource, ''),
|
517 |
-
NULLIF(t1.searchterms, ''),
|
518 |
-
NULLIF(t1.plugins, ''),
|
519 |
-
NULLIF(t1.notes, ''),
|
520 |
-
t1.visit_id,
|
521 |
-
t1.server_latency,
|
522 |
-
t1.page_performance,
|
523 |
-
|
524 |
-
NULLIF(tb.browser, ''),
|
525 |
-
NULLIF(tb.version, ''),
|
526 |
-
tb.type,
|
527 |
-
NULLIF(tb.platform, ''),
|
528 |
-
NULLIF(t1.language, ''),
|
529 |
-
NULLIF(tb.user_agent, ''),
|
530 |
-
|
531 |
-
9812,
|
532 |
-
9812,
|
533 |
-
|
534 |
-
NULLIF(tci.content_type, ''),
|
535 |
-
NULLIF(tci.category, ''),
|
536 |
-
NULLIF(tci.author, ''),
|
537 |
-
tci.content_id,
|
538 |
-
|
539 |
-
NULL,
|
540 |
-
|
541 |
-
t1.dt
|
542 |
-
|
543 |
-
FROM {$GLOBALS['wpdb']->prefix}slim_stats_3 AS t1
|
544 |
-
INNER JOIN {$GLOBALS['wpdb']->base_prefix}slim_browsers AS tb ON t1.browser_id = tb.browser_id
|
545 |
-
INNER JOIN {$GLOBALS['wpdb']->base_prefix}slim_content_info AS tci ON t1.content_info_id = tci.content_info_id" );
|
546 |
-
|
547 |
-
// Copy the events
|
548 |
-
$my_wpdb->query( "
|
549 |
-
INSERT INTO {$GLOBALS['wpdb']->prefix}slim_events (
|
550 |
-
type,
|
551 |
-
event_description,
|
552 |
-
notes,
|
553 |
-
position,
|
554 |
-
id,
|
555 |
-
dt
|
556 |
-
)
|
557 |
-
SELECT
|
558 |
-
tob.type,
|
559 |
-
SUBSTRING(tob.notes, LOCATE('Event:', tob.notes)+6, LOCATE(',', tob.notes, LOCATE('Event:', tob.notes)+6) - LOCATE('Event:', tob.notes)-6),
|
560 |
-
SUBSTRING(tob.notes, 1, LOCATE('Event:', tob.notes) - 3),
|
561 |
-
tob.position,
|
562 |
-
tob.id,
|
563 |
-
tob.dt
|
564 |
-
FROM {$GLOBALS['wpdb']->prefix}slim_outbound AS tob" );
|
565 |
-
|
566 |
-
$my_wpdb->query( "SET foreign_key_checks = 1" );
|
567 |
-
}
|
568 |
-
// --- END: Updates for version 4.0 ---
|
569 |
-
|
570 |
-
// --- Updates for version 4.1.3 ---
|
571 |
-
if ( version_compare( wp_slimstat::$settings[ 'version' ], '4.1.3', '<' ) ) {
|
572 |
-
// Change column type to add IPv6 support
|
573 |
-
$my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats ADD ip_temp VARCHAR(39) DEFAULT NULL AFTER outbound_resource, ADD other_ip_temp VARCHAR(39) DEFAULT NULL AFTER id" );
|
574 |
-
$my_wpdb->query( "UPDATE {$GLOBALS['wpdb']->prefix}slim_stats SET ip_temp = INET_NTOA(ip), other_ip_temp = INET_NTOA(other_ip)" );
|
575 |
-
$my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats CHANGE ip ip_num INT UNSIGNED DEFAULT 0" );
|
576 |
-
$my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats CHANGE other_ip other_ip_num INT UNSIGNED DEFAULT 0" );
|
577 |
-
$my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats CHANGE ip_temp ip VARCHAR(39) DEFAULT NULL AFTER id" );
|
578 |
-
$my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats CHANGE other_ip_temp other_ip VARCHAR(39) DEFAULT NULL AFTER ip" );
|
579 |
-
}
|
580 |
-
// --- END: Updates for version 4.1.3 ---
|
581 |
-
|
582 |
-
// --- Updates for version 4.1.7 ---
|
583 |
-
if ( version_compare( wp_slimstat::$settings[ 'version' ], '4.1.7', '<' ) ) {
|
584 |
-
// Change column type to add IPv6 support
|
585 |
-
$my_wpdb->query( "ALTER TABLE {$GLOBALS[ 'wpdb' ]->prefix}slim_stats ADD dt_out INT(10) UNSIGNED DEFAULT 0 AFTER outbound_resource" );
|
586 |
-
}
|
587 |
-
// --- END: Updates for version 4.1.7 ---
|
588 |
-
|
589 |
// --- Updates for version 4.2 ---
|
590 |
if ( version_compare( wp_slimstat::$settings[ 'version' ], '4.2', '<' ) ) {
|
591 |
// Report arrangements are now stored as a global usermeta value. Migrate old values to new variable
|
592 |
$current_user = wp_get_current_user();
|
593 |
-
$page_location = ( wp_slimstat::$settings[ 'use_separate_menu' ] == '
|
594 |
$new_user_reports = array();
|
595 |
|
596 |
for ( $i = 2; $i <= 5; $i++ ) {
|
@@ -618,7 +382,7 @@ class wp_slimstat_admin {
|
|
618 |
|
619 |
// --- Updates for version 4.2.6 ---
|
620 |
if ( version_compare( wp_slimstat::$settings[ 'version' ], '4.2.6', '<' ) ) {
|
621 |
-
wp_slimstat::$settings[ 'auto_purge_delete' ] = ( wp_slimstat::$settings[ 'auto_purge_delete' ] == '
|
622 |
}
|
623 |
// --- END: Updates for version 4.2.6 ---
|
624 |
|
@@ -658,6 +422,26 @@ class wp_slimstat_admin {
|
|
658 |
}
|
659 |
// --- END: Updates for version 4.4.5 ---
|
660 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
661 |
// Now we can update the version stored in the database
|
662 |
wp_slimstat::$settings[ 'version' ] = wp_slimstat::$version;
|
663 |
|
@@ -773,7 +557,7 @@ class wp_slimstat_admin {
|
|
773 |
|
774 |
// Get the current report assignments
|
775 |
$new_entry = array();
|
776 |
-
if ( wp_slimstat::$settings[ 'use_separate_menu' ] == '
|
777 |
$parent = 'slimview1';
|
778 |
$page_location = 'slimstat';
|
779 |
$new_entry[] = add_menu_page(__('Slimstat','wp-slimstat'), __('Slimstat','wp-slimstat'), $minimum_capability, $parent, array( __CLASS__, 'wp_slimstat_include_view' ) );
|
@@ -829,7 +613,7 @@ class wp_slimstat_admin {
|
|
829 |
$slimstat_view_url = get_admin_url($GLOBALS['blog_id'], "admin.php?page=");
|
830 |
$slimstat_config_url = get_admin_url($GLOBALS['blog_id'], "admin.php?page=slimconfig");
|
831 |
|
832 |
-
$page_location = ( wp_slimstat::$settings[ 'use_separate_menu' ] == '
|
833 |
$user_reports = get_user_option( "meta-box-order_{$page_location}_page_slimlayout", $GLOBALS[ 'current_user' ]->ID );
|
834 |
|
835 |
$frontend_filter = '';
|
@@ -872,7 +656,7 @@ class wp_slimstat_admin {
|
|
872 |
$minimum_capability = wp_slimstat::$settings[ 'capability_can_admin' ];
|
873 |
}
|
874 |
|
875 |
-
if ( wp_slimstat::$settings[ 'use_separate_menu' ] == '
|
876 |
$new_entry = add_submenu_page( 'slimview1', __( 'Settings','wp-slimstat' ), __( 'Settings','wp-slimstat' ), $minimum_capability, 'slimconfig', array( __CLASS__, 'wp_slimstat_include_config' ) );
|
877 |
}
|
878 |
else {
|
@@ -928,7 +712,7 @@ class wp_slimstat_admin {
|
|
928 |
wp_slimstat::$settings[ 'posts_column_day_interval' ] = 30;
|
929 |
}
|
930 |
|
931 |
-
if ( wp_slimstat::$settings[ 'posts_column_pageviews' ] == '
|
932 |
$_columns[ 'wp-slimstat' ] = '<span class="slimstat-icon" title="' . __( 'Pageviews in the last ' . wp_slimstat::$settings[ 'posts_column_day_interval' ] . ' days', 'wp-slimstat' ) . '"></span>';
|
933 |
}
|
934 |
else {
|
@@ -955,7 +739,7 @@ class wp_slimstat_admin {
|
|
955 |
$parsed_permalink = $parsed_permalink[ 'path' ] . ( !empty( $parsed_permalink[ 'query' ] ) ? '?' . $parsed_permalink[ 'query' ] : '' );
|
956 |
wp_slimstat_db::init( 'resource contains ' . $parsed_permalink . '&&&interval equals ' . wp_slimstat::$settings[ 'posts_column_day_interval' ] . '&&&interval_direction equals minus' );
|
957 |
|
958 |
-
if ( wp_slimstat::$settings[ 'posts_column_pageviews' ] == '
|
959 |
$count = wp_slimstat_db::count_records();
|
960 |
}
|
961 |
else{
|
@@ -1042,15 +826,15 @@ class wp_slimstat_admin {
|
|
1042 |
break;
|
1043 |
|
1044 |
case 'wp_ajax_slimstat_hide_geolite_notice':
|
1045 |
-
wp_slimstat::$settings[ 'no_maxmind_warning' ] = '
|
1046 |
break;
|
1047 |
|
1048 |
case 'wp_ajax_slimstat_hide_browscap_notice':
|
1049 |
-
wp_slimstat::$settings[ 'no_browscap_warning' ] = '
|
1050 |
break;
|
1051 |
|
1052 |
case 'wp_ajax_slimstat_hide_caching_notice':
|
1053 |
-
wp_slimstat::$settings[ 'no_caching_warning' ] = '
|
1054 |
break;
|
1055 |
|
1056 |
default:
|
@@ -1165,7 +949,7 @@ class wp_slimstat_admin {
|
|
1165 |
<input class="slimstat-checkbox-toggle"
|
1166 |
type="checkbox"
|
1167 |
name="options[addon_network_settings_' . $_setting_slug . ']"' .
|
1168 |
-
( ( !empty( wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] ) && wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] == '
|
1169 |
id="addon_network_settings_' . $_setting_slug . '"
|
1170 |
data-size="mini" data-handle-width="50" data-on-color="warning" data-on-text="Network" data-off-text="Site">' : '';
|
1171 |
|
@@ -1191,7 +975,7 @@ class wp_slimstat_admin {
|
|
1191 |
name="options[' . $_setting_slug . ']"
|
1192 |
id="' . $_setting_slug . '"
|
1193 |
data-size="mini" data-handle-width="50" data-on-color="success"' .
|
1194 |
-
( ( isset( wp_slimstat::$settings[ $_setting_slug ] ) && wp_slimstat::$settings[ $_setting_slug ] == '
|
1195 |
data-on-text="' . ( !empty( $_setting_info[ 'custom_label_on' ] ) ? $_setting_info[ 'custom_label_on' ] : __( 'On', 'wp-slimstat' ) ) . '"
|
1196 |
data-off-text="' . ( !empty( $_setting_info[ 'custom_label_off' ] ) ? $_setting_info[ 'custom_label_off' ] : __( 'Off', 'wp-slimstat' ) ) . '">' .
|
1197 |
$network_override_checkbox . '
|
@@ -1280,14 +1064,9 @@ class wp_slimstat_admin {
|
|
1280 |
continue;
|
1281 |
}
|
1282 |
|
1283 |
-
//
|
1284 |
-
if ( $_setting_info[ 'type' ] == 'toggle' ) {
|
1285 |
-
|
1286 |
-
wp_slimstat::$settings[ $_setting_slug ] = 'yes';
|
1287 |
-
}
|
1288 |
-
else {
|
1289 |
-
wp_slimstat::$settings[ $_setting_slug ] = 'no';
|
1290 |
-
}
|
1291 |
}
|
1292 |
else if ( isset( $_POST[ 'options' ][ $_setting_slug ] ) ) {
|
1293 |
wp_slimstat::$settings[ $_setting_slug ] = $_POST[ 'options' ][ $_setting_slug ];
|
@@ -1295,11 +1074,8 @@ class wp_slimstat_admin {
|
|
1295 |
|
1296 |
// If the Network Settings add-on is enabled, there might be a switch to decide if this option needs to override what single sites have set
|
1297 |
if ( is_network_admin() ) {
|
1298 |
-
if ( isset( $_POST[ 'options' ][ 'addon_network_settings_' . $_setting_slug ] )
|
1299 |
-
wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] = '
|
1300 |
-
}
|
1301 |
-
else {
|
1302 |
-
wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] = 'no';
|
1303 |
}
|
1304 |
}
|
1305 |
else if ( isset( wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] ) ) {
|
11 |
* Init -- Sets things up.
|
12 |
*/
|
13 |
public static function init() {
|
14 |
+
self::$admin_notice = "As those who have been using Slimstat for a while know, we never stop doing our good share of research and development to improve our plugin. One feature on our wishlist was to make the geolocation functionality more accurate. Specifically, users have been asking us to track not just the Country of origin, but possibly the state and city. In order to geolocate visitors, our code has been leveraging a third-party data file provided by <a href='https://www.maxmind.com/en/home' target='_blank'>MaxMind.com</a>. A while ago, they launched a new data format, which improves performance and offers a way to quickly determine the city of origin. However, the new library required a higher version of PHP, and up until now we had been hesitant to adopt it, to allow more people to use our plugin, over the chance of offering this feature. Now, after spending some time combing through their code, we found a way to get the best of both worlds: by customizing their PHP library, we were able to make it work with PHP 5.3! Which means that now Slimstat is able to tell you your visitors' city of origin (and State, when applicable) right out of the box. This information is available in the Access Log report and in a new 'Top Cities' report under the Audience tab. Please note: the MaxMind data file to enable this feature is approximately 60 Mb, and for this reason <strong>this new functionality is not enabled by default</strong>. You must go to Slimstat > Settings > Tracker and turn on the corresponding option. Then go to Slimstat > Settings > Maintenance and uninstall/install the GeoLite file to download the one that contains the city data. Please feel free to contact us if you have any questions.";
|
|
|
|
|
15 |
|
16 |
self::$admin_notice .= '<br/><br/><a id="slimstat-hide-admin-notice" href="#" class="button-secondary">Got it, thanks</a>';
|
17 |
|
113 |
}
|
114 |
|
115 |
// Remove spammers from the database
|
116 |
+
if ( wp_slimstat::$settings[ 'ignore_spammers' ] == 'on' ) {
|
117 |
add_action('transition_comment_status', array(__CLASS__, 'remove_spam'), 15, 3);
|
118 |
}
|
119 |
|
120 |
// Add a menu to the admin bar ( this function is declared here and not in wp_slimstat_admin because the latter is only initialized if is_admin(), and not in the front-end )
|
121 |
+
if ( wp_slimstat::$settings[ 'use_separate_menu' ] != 'on' && is_admin_bar_showing() ) {
|
122 |
add_action( 'admin_bar_menu', array( __CLASS__, 'wp_slimstat_adminbar' ), 100 );
|
123 |
}
|
124 |
|
128 |
add_action( 'admin_menu', array( __CLASS__, 'wp_slimstat_add_config_menu' ) );
|
129 |
|
130 |
// Display the column in the Edit Posts / Pages screen
|
131 |
+
if ( wp_slimstat::$settings[ 'add_posts_column' ] == 'on' ) {
|
132 |
$post_types = get_post_types( array( 'public' => true, 'show_ui' => true ), 'names' );
|
133 |
include_once( dirname( __FILE__ ) . '/view/wp-slimstat-reports.php' );
|
134 |
include_once( dirname( __FILE__ ) . '/view/wp-slimstat-db.php' );
|
167 |
}
|
168 |
|
169 |
// Dashboard Widgets
|
170 |
+
if ( wp_slimstat::$settings[ 'add_dashboard_widgets' ] == 'on' ) {
|
171 |
$temp = strlen( $_SERVER['REQUEST_URI'] ) - 10;
|
172 |
|
173 |
if( strpos( $_SERVER['REQUEST_URI'], 'index.php' ) !== false || ( $temp >= 0 && strpos($_SERVER['REQUEST_URI'], '/wp-admin/', $temp) !== false ) ) {
|
192 |
}
|
193 |
|
194 |
// Hide plugins
|
195 |
+
if ( wp_slimstat::$settings[ 'hide_addons' ] == 'on' ) {
|
196 |
add_filter( 'all_plugins', array( __CLASS__, 'hide_addons' ) );
|
197 |
}
|
198 |
}
|
350 |
public static function update_tables_and_options(){
|
351 |
$my_wpdb = apply_filters('slimstat_custom_wpdb', $GLOBALS['wpdb']);
|
352 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
353 |
// --- Updates for version 4.2 ---
|
354 |
if ( version_compare( wp_slimstat::$settings[ 'version' ], '4.2', '<' ) ) {
|
355 |
// Report arrangements are now stored as a global usermeta value. Migrate old values to new variable
|
356 |
$current_user = wp_get_current_user();
|
357 |
+
$page_location = ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'on' ) ? 'slimstat' : 'admin';
|
358 |
$new_user_reports = array();
|
359 |
|
360 |
for ( $i = 2; $i <= 5; $i++ ) {
|
382 |
|
383 |
// --- Updates for version 4.2.6 ---
|
384 |
if ( version_compare( wp_slimstat::$settings[ 'version' ], '4.2.6', '<' ) ) {
|
385 |
+
wp_slimstat::$settings[ 'auto_purge_delete' ] = ( wp_slimstat::$settings[ 'auto_purge_delete' ] == 'on' ) ? 'no' : 'on';
|
386 |
}
|
387 |
// --- END: Updates for version 4.2.6 ---
|
388 |
|
422 |
}
|
423 |
// --- END: Updates for version 4.4.5 ---
|
424 |
|
425 |
+
// --- Updates for version 4.7.2 ---
|
426 |
+
if ( version_compare( wp_slimstat::$settings[ 'version' ], '4.7.2', '<' ) ) {
|
427 |
+
// Changing our toggle option values from 'yes' to 'on'
|
428 |
+
foreach ( wp_slimstat::$settings as $a_key => $a_value ) {
|
429 |
+
if ( $a_value == 'yes' ) {
|
430 |
+
wp_slimstat::$settings[ $a_key ] = 'on';
|
431 |
+
}
|
432 |
+
}
|
433 |
+
|
434 |
+
// If MaxMind DB is enabled, download the new GeoLite 2 data file
|
435 |
+
$old_maxmind_path = str_replace( '.mmdb', '.dat', wp_slimstat::$maxmind_path );
|
436 |
+
if ( file_exists( $old_maxmind_path ) ) {
|
437 |
+
@unlink( $old_maxmind_path );
|
438 |
+
wp_slimstat::download_maxmind_database();
|
439 |
+
}
|
440 |
+
|
441 |
+
$my_wpdb->query( "ALTER TABLE {$GLOBALS['wpdb']->prefix}slim_stats ADD COLUMN city VARCHAR(255) DEFAULT NULL AFTER country, ADD COLUMN location VARCHAR(36) DEFAULT NULL AFTER country" );
|
442 |
+
}
|
443 |
+
// --- END: Updates for version 4.7.2 ---
|
444 |
+
|
445 |
// Now we can update the version stored in the database
|
446 |
wp_slimstat::$settings[ 'version' ] = wp_slimstat::$version;
|
447 |
|
557 |
|
558 |
// Get the current report assignments
|
559 |
$new_entry = array();
|
560 |
+
if ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'on' || is_network_admin() ) {
|
561 |
$parent = 'slimview1';
|
562 |
$page_location = 'slimstat';
|
563 |
$new_entry[] = add_menu_page(__('Slimstat','wp-slimstat'), __('Slimstat','wp-slimstat'), $minimum_capability, $parent, array( __CLASS__, 'wp_slimstat_include_view' ) );
|
613 |
$slimstat_view_url = get_admin_url($GLOBALS['blog_id'], "admin.php?page=");
|
614 |
$slimstat_config_url = get_admin_url($GLOBALS['blog_id'], "admin.php?page=slimconfig");
|
615 |
|
616 |
+
$page_location = ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'on' ) ? 'slimstat' : 'admin';
|
617 |
$user_reports = get_user_option( "meta-box-order_{$page_location}_page_slimlayout", $GLOBALS[ 'current_user' ]->ID );
|
618 |
|
619 |
$frontend_filter = '';
|
656 |
$minimum_capability = wp_slimstat::$settings[ 'capability_can_admin' ];
|
657 |
}
|
658 |
|
659 |
+
if ( wp_slimstat::$settings[ 'use_separate_menu' ] == 'on' ) {
|
660 |
$new_entry = add_submenu_page( 'slimview1', __( 'Settings','wp-slimstat' ), __( 'Settings','wp-slimstat' ), $minimum_capability, 'slimconfig', array( __CLASS__, 'wp_slimstat_include_config' ) );
|
661 |
}
|
662 |
else {
|
712 |
wp_slimstat::$settings[ 'posts_column_day_interval' ] = 30;
|
713 |
}
|
714 |
|
715 |
+
if ( wp_slimstat::$settings[ 'posts_column_pageviews' ] == 'on' ) {
|
716 |
$_columns[ 'wp-slimstat' ] = '<span class="slimstat-icon" title="' . __( 'Pageviews in the last ' . wp_slimstat::$settings[ 'posts_column_day_interval' ] . ' days', 'wp-slimstat' ) . '"></span>';
|
717 |
}
|
718 |
else {
|
739 |
$parsed_permalink = $parsed_permalink[ 'path' ] . ( !empty( $parsed_permalink[ 'query' ] ) ? '?' . $parsed_permalink[ 'query' ] : '' );
|
740 |
wp_slimstat_db::init( 'resource contains ' . $parsed_permalink . '&&&interval equals ' . wp_slimstat::$settings[ 'posts_column_day_interval' ] . '&&&interval_direction equals minus' );
|
741 |
|
742 |
+
if ( wp_slimstat::$settings[ 'posts_column_pageviews' ] == 'on' ) {
|
743 |
$count = wp_slimstat_db::count_records();
|
744 |
}
|
745 |
else{
|
826 |
break;
|
827 |
|
828 |
case 'wp_ajax_slimstat_hide_geolite_notice':
|
829 |
+
wp_slimstat::$settings[ 'no_maxmind_warning' ] = 'on';
|
830 |
break;
|
831 |
|
832 |
case 'wp_ajax_slimstat_hide_browscap_notice':
|
833 |
+
wp_slimstat::$settings[ 'no_browscap_warning' ] = 'on';
|
834 |
break;
|
835 |
|
836 |
case 'wp_ajax_slimstat_hide_caching_notice':
|
837 |
+
wp_slimstat::$settings[ 'no_caching_warning' ] = 'on';
|
838 |
break;
|
839 |
|
840 |
default:
|
949 |
<input class="slimstat-checkbox-toggle"
|
950 |
type="checkbox"
|
951 |
name="options[addon_network_settings_' . $_setting_slug . ']"' .
|
952 |
+
( ( !empty( wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] ) && wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] == 'on' ) ? ' checked="checked"' : '' ) . '
|
953 |
id="addon_network_settings_' . $_setting_slug . '"
|
954 |
data-size="mini" data-handle-width="50" data-on-color="warning" data-on-text="Network" data-off-text="Site">' : '';
|
955 |
|
975 |
name="options[' . $_setting_slug . ']"
|
976 |
id="' . $_setting_slug . '"
|
977 |
data-size="mini" data-handle-width="50" data-on-color="success"' .
|
978 |
+
( ( isset( wp_slimstat::$settings[ $_setting_slug ] ) && wp_slimstat::$settings[ $_setting_slug ] == 'on' ) ? ' checked="checked"' : '' ) . '
|
979 |
data-on-text="' . ( !empty( $_setting_info[ 'custom_label_on' ] ) ? $_setting_info[ 'custom_label_on' ] : __( 'On', 'wp-slimstat' ) ) . '"
|
980 |
data-off-text="' . ( !empty( $_setting_info[ 'custom_label_off' ] ) ? $_setting_info[ 'custom_label_off' ] : __( 'Off', 'wp-slimstat' ) ) . '">' .
|
981 |
$network_override_checkbox . '
|
1064 |
continue;
|
1065 |
}
|
1066 |
|
1067 |
+
// An empty toggle option is saved in the database as 'no'
|
1068 |
+
if ( $_setting_info[ 'type' ] == 'toggle' && ( !isset( $_POST[ 'options' ][ $_setting_slug ] ) || strtolower( $_POST[ 'options' ][ $_setting_slug ] != 'on' ) ) ) {
|
1069 |
+
wp_slimstat::$settings[ $_setting_slug ] = 'no';
|
|
|
|
|
|
|
|
|
|
|
1070 |
}
|
1071 |
else if ( isset( $_POST[ 'options' ][ $_setting_slug ] ) ) {
|
1072 |
wp_slimstat::$settings[ $_setting_slug ] = $_POST[ 'options' ][ $_setting_slug ];
|
1074 |
|
1075 |
// If the Network Settings add-on is enabled, there might be a switch to decide if this option needs to override what single sites have set
|
1076 |
if ( is_network_admin() ) {
|
1077 |
+
if ( !isset( $_POST[ 'options' ][ 'addon_network_settings_' . $_setting_slug ] ) || strtolower( $_POST[ 'options' ][ 'addon_network_settings_' . $_setting_slug ] != 'on' ) ) {
|
1078 |
+
wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] = 'no';
|
|
|
|
|
|
|
1079 |
}
|
1080 |
}
|
1081 |
else if ( isset( wp_slimstat::$settings[ 'addon_network_settings_' . $_setting_slug ] ) ) {
|
maxmind.php
CHANGED
@@ -1,33 +1,36 @@
|
|
1 |
<?php
|
2 |
|
3 |
class maxmind_geolite2_connector {
|
4 |
-
public static $
|
5 |
-
public static $maxmind_path = '';
|
6 |
|
7 |
-
|
|
|
8 |
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
|
|
14 |
}
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
|
|
|
|
|
|
|
|
26 |
}
|
27 |
-
}
|
28 |
|
29 |
-
|
30 |
-
// Work in progress
|
31 |
}
|
32 |
}
|
33 |
|
@@ -36,590 +39,590 @@ class maxmind_geolite2_connector {
|
|
36 |
* addresses can be looked up using the <code>get</code> method.
|
37 |
*/
|
38 |
class MaxMindReader {
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
|
95 |
-
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
|
131 |
-
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
-
|
136 |
-
|
137 |
-
|
138 |
-
|
139 |
-
|
140 |
-
|
141 |
-
|
142 |
-
|
143 |
-
|
144 |
-
|
145 |
-
|
146 |
-
|
147 |
-
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
|
157 |
-
|
158 |
-
|
159 |
-
|
160 |
-
|
161 |
-
|
162 |
-
|
163 |
-
|
164 |
-
|
165 |
-
|
166 |
-
|
167 |
-
|
168 |
-
|
169 |
-
|
170 |
-
|
171 |
-
|
172 |
-
|
173 |
-
|
174 |
-
|
175 |
-
|
176 |
-
|
177 |
-
|
178 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
198 |
-
|
199 |
-
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
206 |
-
|
207 |
-
|
208 |
-
|
209 |
-
|
210 |
-
|
211 |
-
|
212 |
-
|
213 |
-
|
214 |
-
|
215 |
-
|
216 |
-
|
217 |
-
|
218 |
-
|
219 |
-
|
220 |
-
|
221 |
-
|
222 |
-
|
223 |
-
|
224 |
-
|
225 |
-
|
226 |
-
|
227 |
-
|
228 |
-
|
229 |
-
|
230 |
-
|
231 |
-
|
232 |
-
|
233 |
-
|
234 |
-
|
235 |
-
|
236 |
-
|
237 |
-
|
238 |
-
|
239 |
-
|
240 |
-
|
241 |
-
|
242 |
-
|
243 |
-
|
244 |
-
|
245 |
-
|
246 |
-
|
247 |
-
|
248 |
-
|
249 |
-
|
250 |
-
|
251 |
-
|
252 |
-
|
253 |
-
|
254 |
-
|
255 |
-
|
256 |
-
|
257 |
-
|
258 |
-
|
259 |
-
|
260 |
-
|
261 |
-
|
262 |
-
|
263 |
-
|
264 |
-
|
265 |
-
|
266 |
-
|
267 |
-
|
268 |
-
|
269 |
-
|
270 |
-
|
271 |
-
|
272 |
-
|
273 |
-
|
274 |
-
|
275 |
-
|
276 |
-
|
277 |
-
|
278 |
-
|
279 |
-
|
280 |
-
|
281 |
-
|
282 |
-
|
283 |
-
|
284 |
-
|
285 |
-
|
286 |
-
|
287 |
-
|
288 |
-
|
289 |
-
|
290 |
-
|
291 |
-
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
|
296 |
-
|
297 |
-
|
298 |
-
|
299 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
307 |
-
|
308 |
-
|
309 |
-
|
310 |
-
|
311 |
-
|
312 |
-
|
313 |
-
|
314 |
-
|
315 |
-
|
316 |
-
|
317 |
-
|
318 |
-
|
319 |
-
|
320 |
-
|
321 |
-
|
322 |
}
|
323 |
|
324 |
class MaxMindDecoder {
|
325 |
-
|
326 |
-
|
327 |
-
|
328 |
-
|
329 |
-
|
330 |
-
|
331 |
-
|
332 |
-
|
333 |
-
|
334 |
-
|
335 |
-
|
336 |
-
|
337 |
-
|
338 |
-
|
339 |
-
|
340 |
-
|
341 |
-
|
342 |
-
|
343 |
-
|
344 |
-
|
345 |
-
|
346 |
-
|
347 |
-
|
348 |
-
|
349 |
-
|
350 |
-
|
351 |
-
|
352 |
-
|
353 |
-
|
354 |
-
|
355 |
-
|
356 |
-
|
357 |
-
|
358 |
-
|
359 |
-
|
360 |
-
|
361 |
-
|
362 |
-
|
363 |
-
|
364 |
-
|
365 |
-
|
366 |
-
|
367 |
-
|
368 |
-
|
369 |
-
|
370 |
-
|
371 |
-
|
372 |
-
|
373 |
-
|
374 |
-
|
375 |
-
|
376 |
-
|
377 |
-
|
378 |
-
|
379 |
-
|
380 |
-
|
381 |
-
|
382 |
-
|
383 |
-
|
384 |
-
|
385 |
-
|
386 |
-
|
387 |
-
|
388 |
-
|
389 |
-
|
390 |
-
|
391 |
-
|
392 |
-
|
393 |
-
|
394 |
-
|
395 |
-
|
396 |
-
|
397 |
-
|
398 |
-
|
399 |
-
|
400 |
-
|
401 |
-
|
402 |
-
|
403 |
-
|
404 |
-
|
405 |
-
|
406 |
-
|
407 |
-
|
408 |
-
|
409 |
-
|
410 |
-
|
411 |
-
|
412 |
-
|
413 |
-
|
414 |
-
|
415 |
-
|
416 |
-
|
417 |
-
|
418 |
-
|
419 |
-
|
420 |
-
|
421 |
-
|
422 |
-
|
423 |
-
|
424 |
-
|
425 |
-
|
426 |
-
|
427 |
-
|
428 |
-
|
429 |
-
|
430 |
-
|
431 |
-
|
432 |
-
|
433 |
-
|
434 |
-
|
435 |
-
|
436 |
-
|
437 |
-
|
438 |
-
|
439 |
-
|
440 |
-
|
441 |
-
|
442 |
-
|
443 |
-
|
444 |
-
|
445 |
-
|
446 |
-
|
447 |
-
|
448 |
-
|
449 |
-
|
450 |
-
|
451 |
-
|
452 |
-
|
453 |
-
|
454 |
-
|
455 |
-
|
456 |
-
|
457 |
-
|
458 |
-
|
459 |
-
|
460 |
-
|
461 |
-
|
462 |
-
|
463 |
-
|
464 |
-
|
465 |
-
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
|
478 |
-
|
479 |
-
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
|
492 |
-
|
493 |
-
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
|
508 |
-
|
509 |
-
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
|
516 |
-
|
517 |
-
|
518 |
-
|
519 |
-
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
|
525 |
-
|
526 |
-
|
527 |
-
|
528 |
-
|
529 |
-
|
530 |
-
|
531 |
-
|
532 |
-
|
533 |
-
|
534 |
-
|
535 |
-
|
536 |
-
|
537 |
-
|
538 |
-
|
539 |
-
|
540 |
-
|
541 |
-
|
542 |
-
|
543 |
-
|
544 |
-
|
545 |
-
|
546 |
-
|
547 |
-
|
548 |
-
|
549 |
-
|
550 |
-
|
551 |
-
|
552 |
-
|
553 |
-
|
554 |
-
|
555 |
-
|
556 |
-
|
557 |
-
|
558 |
-
|
559 |
-
|
560 |
-
|
561 |
-
|
562 |
-
|
563 |
-
|
564 |
-
|
565 |
-
|
566 |
-
|
567 |
-
|
568 |
-
|
569 |
-
|
570 |
-
|
571 |
-
|
572 |
-
|
573 |
-
|
574 |
-
|
575 |
-
|
576 |
-
|
577 |
-
|
578 |
-
|
579 |
-
|
580 |
-
|
581 |
-
|
582 |
-
|
583 |
-
|
584 |
-
|
585 |
-
|
586 |
-
|
587 |
-
|
588 |
-
|
589 |
-
|
590 |
-
|
591 |
-
|
592 |
-
|
593 |
-
|
594 |
-
|
595 |
-
|
596 |
-
|
597 |
-
|
598 |
-
|
599 |
-
|
600 |
-
|
601 |
-
|
602 |
-
|
603 |
-
|
604 |
-
|
605 |
-
|
606 |
-
|
607 |
-
|
608 |
-
|
609 |
-
|
610 |
-
|
611 |
-
|
612 |
-
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
}
|
624 |
|
625 |
/**
|
@@ -666,57 +669,57 @@ class InvalidDatabaseException extends \Exception
|
|
666 |
* values will be a description in that language as a UTF-8 string. May be
|
667 |
* undefined for some databases.
|
668 |
*/
|
669 |
-
class
|
670 |
-
|
671 |
-
|
672 |
-
|
673 |
-
|
674 |
-
|
675 |
-
|
676 |
-
|
677 |
-
|
678 |
-
|
679 |
-
|
680 |
-
|
681 |
-
|
682 |
-
|
683 |
-
|
684 |
-
|
685 |
-
|
686 |
-
|
687 |
-
|
688 |
-
|
689 |
-
|
690 |
-
|
691 |
-
|
692 |
-
|
693 |
-
|
694 |
-
|
695 |
-
|
696 |
-
|
697 |
-
|
698 |
-
|
699 |
-
|
700 |
-
|
701 |
}
|
702 |
|
703 |
class MaxMindUtil {
|
704 |
-
|
705 |
-
|
706 |
-
|
707 |
-
|
708 |
-
|
709 |
-
|
710 |
-
|
711 |
-
|
712 |
-
|
713 |
-
|
714 |
-
|
715 |
-
|
716 |
-
|
717 |
-
|
718 |
-
|
719 |
-
|
720 |
-
|
721 |
-
|
722 |
}
|
1 |
<?php
|
2 |
|
3 |
class maxmind_geolite2_connector {
|
4 |
+
public static function get_geolocation_info( $_ip_address = '' ) {
|
|
|
5 |
|
6 |
+
$ipnum = sprintf( '%u', ip2long( $_ip_address ) );
|
7 |
+
$geo_output = array( 'country' => array( 'iso_code' => 'xx' ) );
|
8 |
|
9 |
+
// Is this a RFC1918 (local) IP?
|
10 |
+
if ( $ipnum == 2130706433 || // 127.0.0.1
|
11 |
+
( $ipnum >= 167772160 && $ipnum <= 184549375 ) || // 10.0.0.1 - 10.255.255.255
|
12 |
+
( $ipnum >= 2886729728 && $ipnum <= 2887778303 ) || // 172.16.0.1 - 172.31.255.255
|
13 |
+
( $ipnum >= 3232235521 && $ipnum <= 3232301055 ) ) { // 192.168.0.1 - 192.168.255.255
|
14 |
+
$geo_output[ 'country' ][ 'iso_code' ] = 'xy';
|
15 |
}
|
16 |
+
else if ( file_exists( wp_slimstat::$maxmind_path ) ) {
|
17 |
+
// Do we need to update our data file?
|
18 |
+
if ( false !== ( $file_stat = stat( wp_slimstat::$maxmind_path ) ) ) {
|
19 |
+
// Is the database more than 30 days old?
|
20 |
+
if ( ( date( 'U' ) - $file_stat[ 'mtime' ] > 2629740 ) ) {
|
21 |
+
add_action( 'shutdown', array( 'wp_slimstat', 'download_maxmind_database' ) );
|
22 |
+
}
|
23 |
+
}
|
24 |
+
|
25 |
+
$reader = new MaxMindReader( wp_slimstat::$maxmind_path );
|
26 |
+
$geo_maxmind = $reader->get( $_ip_address );
|
27 |
+
|
28 |
+
if ( !empty( $geo_maxmind ) ) {
|
29 |
+
$geo_output = $geo_maxmind;
|
30 |
+
}
|
31 |
}
|
|
|
32 |
|
33 |
+
return apply_filters( 'slimstat_get_country', $geo_output, $_ip_address );
|
|
|
34 |
}
|
35 |
}
|
36 |
|
39 |
* addresses can be looked up using the <code>get</code> method.
|
40 |
*/
|
41 |
class MaxMindReader {
|
42 |
+
private static $DATA_SECTION_SEPARATOR_SIZE = 16;
|
43 |
+
private static $METADATA_START_MARKER = "\xAB\xCD\xEFMaxMind.com";
|
44 |
+
private static $METADATA_START_MARKER_LENGTH = 14;
|
45 |
+
private static $METADATA_MAX_SIZE = 131072; // 128 * 1024 = 128KB
|
46 |
+
|
47 |
+
private $decoder;
|
48 |
+
private $fileHandle;
|
49 |
+
private $fileSize;
|
50 |
+
private $ipV4Start;
|
51 |
+
private $metadata;
|
52 |
+
|
53 |
+
/**
|
54 |
+
* Constructs a MaxMindReader for the MaxMind DB format. The file passed to it must
|
55 |
+
* be a valid MaxMind DB file such as a GeoIp2 database file.
|
56 |
+
*
|
57 |
+
* @param string $database
|
58 |
+
* the MaxMind DB file to use.
|
59 |
+
* @throws \InvalidArgumentException for invalid database path or unknown arguments
|
60 |
+
* @throws \MaxMind\Db\Reader\InvalidDatabaseException
|
61 |
+
* if the database is invalid or there is an error reading
|
62 |
+
* from it.
|
63 |
+
*/
|
64 |
+
public function __construct($database)
|
65 |
+
{
|
66 |
+
if (func_num_args() != 1) {
|
67 |
+
throw new \InvalidArgumentException(
|
68 |
+
'The constructor takes exactly one argument.'
|
69 |
+
);
|
70 |
+
}
|
71 |
+
|
72 |
+
if (!is_readable($database)) {
|
73 |
+
throw new \InvalidArgumentException(
|
74 |
+
"The file \"$database\" does not exist or is not readable."
|
75 |
+
);
|
76 |
+
}
|
77 |
+
$this->fileHandle = @fopen($database, 'rb');
|
78 |
+
if ($this->fileHandle === false) {
|
79 |
+
throw new \InvalidArgumentException(
|
80 |
+
"Error opening \"$database\"."
|
81 |
+
);
|
82 |
+
}
|
83 |
+
$this->fileSize = @filesize($database);
|
84 |
+
if ($this->fileSize === false) {
|
85 |
+
throw new \UnexpectedValueException(
|
86 |
+
"Error determining the size of \"$database\"."
|
87 |
+
);
|
88 |
+
}
|
89 |
+
|
90 |
+
$start = $this->findMetadataStart($database);
|
91 |
+
$metadataDecoder = new MaxMindDecoder($this->fileHandle, $start);
|
92 |
+
list($metadataArray) = $metadataDecoder->decode($start);
|
93 |
+
$this->metadata = new MaxMindMetadata($metadataArray);
|
94 |
+
$this->decoder = new MaxMindDecoder(
|
95 |
+
$this->fileHandle,
|
96 |
+
$this->metadata->searchTreeSize + self::$DATA_SECTION_SEPARATOR_SIZE
|
97 |
+
);
|
98 |
+
}
|
99 |
+
|
100 |
+
/**
|
101 |
+
* Looks up the <code>address</code> in the MaxMind DB.
|
102 |
+
*
|
103 |
+
* @param string $ipAddress
|
104 |
+
* the IP address to look up.
|
105 |
+
* @return array the record for the IP address.
|
106 |
+
* @throws \BadMethodCallException if this method is called on a closed database.
|
107 |
+
* @throws \InvalidArgumentException if something other than a single IP address is passed to the method.
|
108 |
+
* @throws InvalidDatabaseException
|
109 |
+
* if the database is invalid or there is an error reading
|
110 |
+
* from it.
|
111 |
+
*/
|
112 |
+
public function get($ipAddress)
|
113 |
+
{
|
114 |
+
if (func_num_args() != 1) {
|
115 |
+
throw new \InvalidArgumentException(
|
116 |
+
'Method takes exactly one argument.'
|
117 |
+
);
|
118 |
+
}
|
119 |
+
|
120 |
+
if (!is_resource($this->fileHandle)) {
|
121 |
+
throw new \BadMethodCallException(
|
122 |
+
'Attempt to read from a closed MaxMind DB.'
|
123 |
+
);
|
124 |
+
}
|
125 |
+
|
126 |
+
if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
|
127 |
+
throw new \InvalidArgumentException(
|
128 |
+
"The value \"$ipAddress\" is not a valid IP address."
|
129 |
+
);
|
130 |
+
}
|
131 |
+
|
132 |
+
if ($this->metadata->ipVersion == 4 && strrpos($ipAddress, ':')) {
|
133 |
+
throw new \InvalidArgumentException(
|
134 |
+
"Error looking up $ipAddress. You attempted to look up an"
|
135 |
+
. " IPv6 address in an IPv4-only database."
|
136 |
+
);
|
137 |
+
}
|
138 |
+
$pointer = $this->findAddressInTree($ipAddress);
|
139 |
+
if ($pointer == 0) {
|
140 |
+
return null;
|
141 |
+
}
|
142 |
+
return $this->resolveDataPointer($pointer);
|
143 |
+
}
|
144 |
+
|
145 |
+
private function findAddressInTree($ipAddress)
|
146 |
+
{
|
147 |
+
// XXX - could simplify. Done as a byte array to ease porting
|
148 |
+
$rawAddress = array_merge(unpack('C*', inet_pton($ipAddress)));
|
149 |
+
|
150 |
+
$bitCount = count($rawAddress) * 8;
|
151 |
+
|
152 |
+
// The first node of the tree is always node 0, at the beginning of the
|
153 |
+
// value
|
154 |
+
$node = $this->startNode($bitCount);
|
155 |
+
|
156 |
+
for ($i = 0; $i < $bitCount; $i++) {
|
157 |
+
if ($node >= $this->metadata->nodeCount) {
|
158 |
+
break;
|
159 |
+
}
|
160 |
+
$tempBit = 0xFF & $rawAddress[$i >> 3];
|
161 |
+
$bit = 1 & ($tempBit >> 7 - ($i % 8));
|
162 |
+
|
163 |
+
$node = $this->readNode($node, $bit);
|
164 |
+
}
|
165 |
+
if ($node == $this->metadata->nodeCount) {
|
166 |
+
// Record is empty
|
167 |
+
return 0;
|
168 |
+
} elseif ($node > $this->metadata->nodeCount) {
|
169 |
+
// Record is a data pointer
|
170 |
+
return $node;
|
171 |
+
}
|
172 |
+
throw new InvalidDatabaseException("Something bad happened");
|
173 |
+
}
|
174 |
+
|
175 |
+
|
176 |
+
private function startNode($length)
|
177 |
+
{
|
178 |
+
// Check if we are looking up an IPv4 address in an IPv6 tree. If this
|
179 |
+
// is the case, we can skip over the first 96 nodes.
|
180 |
+
if ($this->metadata->ipVersion == 6 && $length == 32) {
|
181 |
+
return $this->ipV4StartNode();
|
182 |
+
}
|
183 |
+
// The first node of the tree is always node 0, at the beginning of the
|
184 |
+
// value
|
185 |
+
return 0;
|
186 |
+
}
|
187 |
+
|
188 |
+
private function ipV4StartNode()
|
189 |
+
{
|
190 |
+
// This is a defensive check. There is no reason to call this when you
|
191 |
+
// have an IPv4 tree.
|
192 |
+
if ($this->metadata->ipVersion == 4) {
|
193 |
+
return 0;
|
194 |
+
}
|
195 |
+
|
196 |
+
if ($this->ipV4Start != 0) {
|
197 |
+
return $this->ipV4Start;
|
198 |
+
}
|
199 |
+
$node = 0;
|
200 |
+
|
201 |
+
for ($i = 0; $i < 96 && $node < $this->metadata->nodeCount; $i++) {
|
202 |
+
$node = $this->readNode($node, 0);
|
203 |
+
}
|
204 |
+
$this->ipV4Start = $node;
|
205 |
+
return $node;
|
206 |
+
}
|
207 |
+
|
208 |
+
private function readNode($nodeNumber, $index)
|
209 |
+
{
|
210 |
+
$baseOffset = $nodeNumber * $this->metadata->nodeByteSize;
|
211 |
+
|
212 |
+
// XXX - probably could condense this.
|
213 |
+
switch ($this->metadata->recordSize) {
|
214 |
+
case 24:
|
215 |
+
$bytes = MaxMindUtil::read($this->fileHandle, $baseOffset + $index * 3, 3);
|
216 |
+
list(, $node) = unpack('N', "\x00" . $bytes);
|
217 |
+
return $node;
|
218 |
+
case 28:
|
219 |
+
$middleByte = MaxMindUtil::read($this->fileHandle, $baseOffset + 3, 1);
|
220 |
+
list(, $middle) = unpack('C', $middleByte);
|
221 |
+
if ($index == 0) {
|
222 |
+
$middle = (0xF0 & $middle) >> 4;
|
223 |
+
} else {
|
224 |
+
$middle = 0x0F & $middle;
|
225 |
+
}
|
226 |
+
$bytes = MaxMindUtil::read($this->fileHandle, $baseOffset + $index * 4, 3);
|
227 |
+
list(, $node) = unpack('N', chr($middle) . $bytes);
|
228 |
+
return $node;
|
229 |
+
case 32:
|
230 |
+
$bytes = MaxMindUtil::read($this->fileHandle, $baseOffset + $index * 4, 4);
|
231 |
+
list(, $node) = unpack('N', $bytes);
|
232 |
+
return $node;
|
233 |
+
default:
|
234 |
+
throw new InvalidDatabaseException(
|
235 |
+
'Unknown record size: '
|
236 |
+
. $this->metadata->recordSize
|
237 |
+
);
|
238 |
+
}
|
239 |
+
}
|
240 |
+
|
241 |
+
private function resolveDataPointer($pointer)
|
242 |
+
{
|
243 |
+
$resolved = $pointer - $this->metadata->nodeCount
|
244 |
+
+ $this->metadata->searchTreeSize;
|
245 |
+
if ($resolved > $this->fileSize) {
|
246 |
+
throw new InvalidDatabaseException(
|
247 |
+
"The MaxMind DB file's search tree is corrupt"
|
248 |
+
);
|
249 |
+
}
|
250 |
+
|
251 |
+
list($data) = $this->decoder->decode($resolved);
|
252 |
+
return $data;
|
253 |
+
}
|
254 |
+
|
255 |
+
/*
|
256 |
+
* This is an extremely naive but reasonably readable implementation. There
|
257 |
+
* are much faster algorithms (e.g., Boyer-Moore) for this if speed is ever
|
258 |
+
* an issue, but I suspect it won't be.
|
259 |
+
*/
|
260 |
+
private function findMetadataStart($filename)
|
261 |
+
{
|
262 |
+
$handle = $this->fileHandle;
|
263 |
+
$fstat = fstat($handle);
|
264 |
+
$fileSize = $fstat['size'];
|
265 |
+
$marker = self::$METADATA_START_MARKER;
|
266 |
+
$markerLength = self::$METADATA_START_MARKER_LENGTH;
|
267 |
+
$metadataMaxLengthExcludingMarker
|
268 |
+
= min(self::$METADATA_MAX_SIZE, $fileSize) - $markerLength;
|
269 |
+
|
270 |
+
for ($i = 0; $i <= $metadataMaxLengthExcludingMarker; $i++) {
|
271 |
+
for ($j = 0; $j < $markerLength; $j++) {
|
272 |
+
fseek($handle, $fileSize - $i - $j - 1);
|
273 |
+
$matchBit = fgetc($handle);
|
274 |
+
if ($matchBit != $marker[$markerLength - $j - 1]) {
|
275 |
+
continue 2;
|
276 |
+
}
|
277 |
+
}
|
278 |
+
return $fileSize - $i;
|
279 |
+
}
|
280 |
+
throw new InvalidDatabaseException(
|
281 |
+
"Error opening database file ($filename). " .
|
282 |
+
'Is this a valid MaxMind DB file?'
|
283 |
+
);
|
284 |
+
}
|
285 |
+
|
286 |
+
/**
|
287 |
+
* @throws \InvalidArgumentException if arguments are passed to the method.
|
288 |
+
* @throws \BadMethodCallException if the database has been closed.
|
289 |
+
* @return Metadata object for the database.
|
290 |
+
*/
|
291 |
+
public function metadata()
|
292 |
+
{
|
293 |
+
if (func_num_args()) {
|
294 |
+
throw new \InvalidArgumentException(
|
295 |
+
'Method takes no arguments.'
|
296 |
+
);
|
297 |
+
}
|
298 |
+
|
299 |
+
// Not technically required, but this makes it consistent with
|
300 |
+
// C extension and it allows us to change our implementation later.
|
301 |
+
if (!is_resource($this->fileHandle)) {
|
302 |
+
throw new \BadMethodCallException(
|
303 |
+
'Attempt to read from a closed MaxMind DB.'
|
304 |
+
);
|
305 |
+
}
|
306 |
+
|
307 |
+
return $this->metadata;
|
308 |
+
}
|
309 |
+
|
310 |
+
/**
|
311 |
+
* Closes the MaxMind DB and returns resources to the system.
|
312 |
+
*
|
313 |
+
* @throws \Exception
|
314 |
+
* if an I/O error occurs.
|
315 |
+
*/
|
316 |
+
public function close()
|
317 |
+
{
|
318 |
+
if (!is_resource($this->fileHandle)) {
|
319 |
+
throw new \BadMethodCallException(
|
320 |
+
'Attempt to close a closed MaxMind DB.'
|
321 |
+
);
|
322 |
+
}
|
323 |
+
fclose($this->fileHandle);
|
324 |
+
}
|
325 |
}
|
326 |
|
327 |
class MaxMindDecoder {
|
328 |
+
private $fileStream;
|
329 |
+
private $pointerBase;
|
330 |
+
// This is only used for unit testing
|
331 |
+
private $pointerTestHack;
|
332 |
+
private $switchByteOrder;
|
333 |
+
|
334 |
+
private $types = array(
|
335 |
+
0 => 'extended',
|
336 |
+
1 => 'pointer',
|
337 |
+
2 => 'utf8_string',
|
338 |
+
3 => 'double',
|
339 |
+
4 => 'bytes',
|
340 |
+
5 => 'uint16',
|
341 |
+
6 => 'uint32',
|
342 |
+
7 => 'map',
|
343 |
+
8 => 'int32',
|
344 |
+
9 => 'uint64',
|
345 |
+
10 => 'uint128',
|
346 |
+
11 => 'array',
|
347 |
+
12 => 'container',
|
348 |
+
13 => 'end_marker',
|
349 |
+
14 => 'boolean',
|
350 |
+
15 => 'float',
|
351 |
+
);
|
352 |
+
|
353 |
+
public function __construct(
|
354 |
+
$fileStream,
|
355 |
+
$pointerBase = 0,
|
356 |
+
$pointerTestHack = false
|
357 |
+
) {
|
358 |
+
$this->fileStream = $fileStream;
|
359 |
+
$this->pointerBase = $pointerBase;
|
360 |
+
$this->pointerTestHack = $pointerTestHack;
|
361 |
+
|
362 |
+
$this->switchByteOrder = $this->isPlatformLittleEndian();
|
363 |
+
}
|
364 |
+
|
365 |
+
|
366 |
+
public function decode($offset)
|
367 |
+
{
|
368 |
+
list(, $ctrlByte) = unpack(
|
369 |
+
'C',
|
370 |
+
MaxMindUtil::read($this->fileStream, $offset, 1)
|
371 |
+
);
|
372 |
+
$offset++;
|
373 |
+
|
374 |
+
$type = $this->types[$ctrlByte >> 5];
|
375 |
+
|
376 |
+
// Pointers are a special case, we don't read the next $size bytes, we
|
377 |
+
// use the size to determine the length of the pointer and then follow
|
378 |
+
// it.
|
379 |
+
if ($type == 'pointer') {
|
380 |
+
list($pointer, $offset) = $this->decodePointer($ctrlByte, $offset);
|
381 |
+
|
382 |
+
// for unit testing
|
383 |
+
if ($this->pointerTestHack) {
|
384 |
+
return array($pointer);
|
385 |
+
}
|
386 |
+
|
387 |
+
list($result) = $this->decode($pointer);
|
388 |
+
|
389 |
+
return array($result, $offset);
|
390 |
+
}
|
391 |
+
|
392 |
+
if ($type == 'extended') {
|
393 |
+
list(, $nextByte) = unpack(
|
394 |
+
'C',
|
395 |
+
MaxMindUtil::read($this->fileStream, $offset, 1)
|
396 |
+
);
|
397 |
+
|
398 |
+
$typeNum = $nextByte + 7;
|
399 |
+
|
400 |
+
if ($typeNum < 8) {
|
401 |
+
throw new InvalidDatabaseException(
|
402 |
+
"Something went horribly wrong in the decoder. An extended type "
|
403 |
+
. "resolved to a type number < 8 ("
|
404 |
+
. $this->types[$typeNum]
|
405 |
+
. ")"
|
406 |
+
);
|
407 |
+
}
|
408 |
+
|
409 |
+
$type = $this->types[$typeNum];
|
410 |
+
$offset++;
|
411 |
+
}
|
412 |
+
|
413 |
+
list($size, $offset) = $this->sizeFromCtrlByte($ctrlByte, $offset);
|
414 |
+
|
415 |
+
return $this->decodeByType($type, $offset, $size);
|
416 |
+
}
|
417 |
+
|
418 |
+
private function decodeByType($type, $offset, $size)
|
419 |
+
{
|
420 |
+
switch ($type) {
|
421 |
+
case 'map':
|
422 |
+
return $this->decodeMap($size, $offset);
|
423 |
+
case 'array':
|
424 |
+
return $this->decodeArray($size, $offset);
|
425 |
+
case 'boolean':
|
426 |
+
return array($this->decodeBoolean($size), $offset);
|
427 |
+
}
|
428 |
+
|
429 |
+
$newOffset = $offset + $size;
|
430 |
+
$bytes = MaxMindUtil::read($this->fileStream, $offset, $size);
|
431 |
+
switch ($type) {
|
432 |
+
case 'utf8_string':
|
433 |
+
return array($this->decodeString($bytes), $newOffset);
|
434 |
+
case 'double':
|
435 |
+
$this->verifySize(8, $size);
|
436 |
+
return array($this->decodeDouble($bytes), $newOffset);
|
437 |
+
case 'float':
|
438 |
+
$this->verifySize(4, $size);
|
439 |
+
return array($this->decodeFloat($bytes), $newOffset);
|
440 |
+
case 'bytes':
|
441 |
+
return array($bytes, $newOffset);
|
442 |
+
case 'uint16':
|
443 |
+
case 'uint32':
|
444 |
+
return array($this->decodeUint($bytes), $newOffset);
|
445 |
+
case 'int32':
|
446 |
+
return array($this->decodeInt32($bytes), $newOffset);
|
447 |
+
case 'uint64':
|
448 |
+
case 'uint128':
|
449 |
+
return array($this->decodeBigUint($bytes, $size), $newOffset);
|
450 |
+
default:
|
451 |
+
throw new InvalidDatabaseException(
|
452 |
+
"Unknown or unexpected type: " . $type
|
453 |
+
);
|
454 |
+
}
|
455 |
+
}
|
456 |
+
|
457 |
+
private function verifySize($expected, $actual)
|
458 |
+
{
|
459 |
+
if ($expected != $actual) {
|
460 |
+
throw new InvalidDatabaseException(
|
461 |
+
"The MaxMind DB file's data section contains bad data (unknown data type or corrupt data)"
|
462 |
+
);
|
463 |
+
}
|
464 |
+
}
|
465 |
+
|
466 |
+
private function decodeArray($size, $offset)
|
467 |
+
{
|
468 |
+
$array = array();
|
469 |
+
|
470 |
+
for ($i = 0; $i < $size; $i++) {
|
471 |
+
list($value, $offset) = $this->decode($offset);
|
472 |
+
array_push($array, $value);
|
473 |
+
}
|
474 |
+
|
475 |
+
return array($array, $offset);
|
476 |
+
}
|
477 |
+
|
478 |
+
private function decodeBoolean($size)
|
479 |
+
{
|
480 |
+
return $size == 0 ? false : true;
|
481 |
+
}
|
482 |
+
|
483 |
+
private function decodeDouble($bits)
|
484 |
+
{
|
485 |
+
// XXX - Assumes IEEE 754 double on platform
|
486 |
+
list(, $double) = unpack('d', $this->maybeSwitchByteOrder($bits));
|
487 |
+
return $double;
|
488 |
+
}
|
489 |
+
|
490 |
+
private function decodeFloat($bits)
|
491 |
+
{
|
492 |
+
// XXX - Assumes IEEE 754 floats on platform
|
493 |
+
list(, $float) = unpack('f', $this->maybeSwitchByteOrder($bits));
|
494 |
+
return $float;
|
495 |
+
}
|
496 |
+
|
497 |
+
private function decodeInt32($bytes)
|
498 |
+
{
|
499 |
+
$bytes = $this->zeroPadLeft($bytes, 4);
|
500 |
+
list(, $int) = unpack('l', $this->maybeSwitchByteOrder($bytes));
|
501 |
+
return $int;
|
502 |
+
}
|
503 |
+
|
504 |
+
private function decodeMap($size, $offset)
|
505 |
+
{
|
506 |
+
|
507 |
+
$map = array();
|
508 |
+
|
509 |
+
for ($i = 0; $i < $size; $i++) {
|
510 |
+
list($key, $offset) = $this->decode($offset);
|
511 |
+
list($value, $offset) = $this->decode($offset);
|
512 |
+
$map[$key] = $value;
|
513 |
+
}
|
514 |
+
|
515 |
+
return array($map, $offset);
|
516 |
+
}
|
517 |
+
|
518 |
+
private $pointerValueOffset = array(
|
519 |
+
1 => 0,
|
520 |
+
2 => 2048,
|
521 |
+
3 => 526336,
|
522 |
+
4 => 0,
|
523 |
+
);
|
524 |
+
|
525 |
+
private function decodePointer($ctrlByte, $offset)
|
526 |
+
{
|
527 |
+
$pointerSize = (($ctrlByte >> 3) & 0x3) + 1;
|
528 |
+
|
529 |
+
$buffer = MaxMindUtil::read($this->fileStream, $offset, $pointerSize);
|
530 |
+
$offset = $offset + $pointerSize;
|
531 |
+
|
532 |
+
$packed = $pointerSize == 4
|
533 |
+
? $buffer
|
534 |
+
: (pack('C', $ctrlByte & 0x7)) . $buffer;
|
535 |
+
|
536 |
+
$unpacked = $this->decodeUint($packed);
|
537 |
+
$pointer = $unpacked + $this->pointerBase
|
538 |
+
+ $this->pointerValueOffset[$pointerSize];
|
539 |
+
|
540 |
+
return array($pointer, $offset);
|
541 |
+
}
|
542 |
+
|
543 |
+
private function decodeUint($bytes)
|
544 |
+
{
|
545 |
+
list(, $int) = unpack('N', $this->zeroPadLeft($bytes, 4));
|
546 |
+
return $int;
|
547 |
+
}
|
548 |
+
|
549 |
+
private function decodeBigUint($bytes, $byteLength)
|
550 |
+
{
|
551 |
+
$maxUintBytes = log(PHP_INT_MAX, 2) / 8;
|
552 |
+
|
553 |
+
if ($byteLength == 0) {
|
554 |
+
return 0;
|
555 |
+
}
|
556 |
+
|
557 |
+
$numberOfLongs = ceil($byteLength / 4);
|
558 |
+
$paddedLength = $numberOfLongs * 4;
|
559 |
+
$paddedBytes = $this->zeroPadLeft($bytes, $paddedLength);
|
560 |
+
$unpacked = array_merge(unpack("N$numberOfLongs", $paddedBytes));
|
561 |
+
|
562 |
+
$integer = 0;
|
563 |
+
|
564 |
+
// 2^32
|
565 |
+
$twoTo32 = '4294967296';
|
566 |
+
|
567 |
+
foreach ($unpacked as $part) {
|
568 |
+
// We only use gmp or bcmath if the final value is too big
|
569 |
+
if ($byteLength <= $maxUintBytes) {
|
570 |
+
$integer = ($integer << 32) + $part;
|
571 |
+
} elseif (extension_loaded('gmp')) {
|
572 |
+
$integer = gmp_strval(gmp_add(gmp_mul($integer, $twoTo32), $part));
|
573 |
+
} elseif (extension_loaded('bcmath')) {
|
574 |
+
$integer = bcadd(bcmul($integer, $twoTo32), $part);
|
575 |
+
} else {
|
576 |
+
throw new \RuntimeException(
|
577 |
+
'The gmp or bcmath extension must be installed to read this database.'
|
578 |
+
);
|
579 |
+
}
|
580 |
+
}
|
581 |
+
return $integer;
|
582 |
+
}
|
583 |
+
|
584 |
+
private function decodeString($bytes)
|
585 |
+
{
|
586 |
+
// XXX - NOOP. As far as I know, the end user has to explicitly set the
|
587 |
+
// encoding in PHP. Strings are just bytes.
|
588 |
+
return $bytes;
|
589 |
+
}
|
590 |
+
|
591 |
+
private function sizeFromCtrlByte($ctrlByte, $offset)
|
592 |
+
{
|
593 |
+
$size = $ctrlByte & 0x1f;
|
594 |
+
$bytesToRead = $size < 29 ? 0 : $size - 28;
|
595 |
+
$bytes = MaxMindUtil::read($this->fileStream, $offset, $bytesToRead);
|
596 |
+
$decoded = $this->decodeUint($bytes);
|
597 |
+
|
598 |
+
if ($size == 29) {
|
599 |
+
$size = 29 + $decoded;
|
600 |
+
} elseif ($size == 30) {
|
601 |
+
$size = 285 + $decoded;
|
602 |
+
} elseif ($size > 30) {
|
603 |
+
$size = ($decoded & (0x0FFFFFFF >> (32 - (8 * $bytesToRead))))
|
604 |
+
+ 65821;
|
605 |
+
}
|
606 |
+
|
607 |
+
return array($size, $offset + $bytesToRead);
|
608 |
+
}
|
609 |
+
|
610 |
+
private function zeroPadLeft($content, $desiredLength)
|
611 |
+
{
|
612 |
+
return str_pad($content, $desiredLength, "\x00", STR_PAD_LEFT);
|
613 |
+
}
|
614 |
+
|
615 |
+
private function maybeSwitchByteOrder($bytes)
|
616 |
+
{
|
617 |
+
return $this->switchByteOrder ? strrev($bytes) : $bytes;
|
618 |
+
}
|
619 |
+
|
620 |
+
private function isPlatformLittleEndian()
|
621 |
+
{
|
622 |
+
$testint = 0x00FF;
|
623 |
+
$packed = pack('S', $testint);
|
624 |
+
return $testint === current(unpack('v', $packed));
|
625 |
+
}
|
626 |
}
|
627 |
|
628 |
/**
|
669 |
* values will be a description in that language as a UTF-8 string. May be
|
670 |
* undefined for some databases.
|
671 |
*/
|
672 |
+
class MaxMindMetadata {
|
673 |
+
private $binaryFormatMajorVersion;
|
674 |
+
private $binaryFormatMinorVersion;
|
675 |
+
private $buildEpoch;
|
676 |
+
private $databaseType;
|
677 |
+
private $description;
|
678 |
+
private $ipVersion;
|
679 |
+
private $languages;
|
680 |
+
private $nodeByteSize;
|
681 |
+
private $nodeCount;
|
682 |
+
private $recordSize;
|
683 |
+
private $searchTreeSize;
|
684 |
+
|
685 |
+
public function __construct($metadata) {
|
686 |
+
$this->binaryFormatMajorVersion =
|
687 |
+
$metadata['binary_format_major_version'];
|
688 |
+
$this->binaryFormatMinorVersion =
|
689 |
+
$metadata['binary_format_minor_version'];
|
690 |
+
$this->buildEpoch = $metadata['build_epoch'];
|
691 |
+
$this->databaseType = $metadata['database_type'];
|
692 |
+
$this->languages = $metadata['languages'];
|
693 |
+
$this->description = $metadata['description'];
|
694 |
+
$this->ipVersion = $metadata['ip_version'];
|
695 |
+
$this->nodeCount = $metadata['node_count'];
|
696 |
+
$this->recordSize = $metadata['record_size'];
|
697 |
+
$this->nodeByteSize = $this->recordSize / 4;
|
698 |
+
$this->searchTreeSize = $this->nodeCount * $this->nodeByteSize;
|
699 |
+
}
|
700 |
+
|
701 |
+
public function __get($var) {
|
702 |
+
return $this->$var;
|
703 |
+
}
|
704 |
}
|
705 |
|
706 |
class MaxMindUtil {
|
707 |
+
public static function read( $stream, $offset, $numberOfBytes ) {
|
708 |
+
if ( $numberOfBytes == 0 ) {
|
709 |
+
return '';
|
710 |
+
}
|
711 |
+
if ( fseek( $stream, $offset ) == 0 ) {
|
712 |
+
$value = fread( $stream, $numberOfBytes );
|
713 |
+
|
714 |
+
// We check that the number of bytes read is equal to the number
|
715 |
+
// asked for. We use ftell as getting the length of $value is
|
716 |
+
// much slower.
|
717 |
+
if ( ftell( $stream ) - $offset === $numberOfBytes ) {
|
718 |
+
return $value;
|
719 |
+
}
|
720 |
+
}
|
721 |
+
throw new InvalidDatabaseException(
|
722 |
+
"The MaxMind DB file contains bad data"
|
723 |
+
);
|
724 |
+
}
|
725 |
}
|
readme.txt
CHANGED
@@ -5,7 +5,7 @@ Tags: analytics, statistics, counter, tracking, reports, wassup, geolocation, on
|
|
5 |
Text Domain: wp-slimstat
|
6 |
Requires at least: 3.8
|
7 |
Tested up to: 4.8.2
|
8 |
-
Stable tag: 4.7.
|
9 |
|
10 |
== Description ==
|
11 |
The leading web analytics plugin for WordPress. Track returning customers and registered users, monitor Javascript events, detect intrusions, analyze email campaigns. Thousands of WordPress sites are already using it.
|
@@ -71,6 +71,12 @@ Our knowledge base is available on our [support center](http://docs.wp-slimstat.
|
|
71 |
5. **Responsive layout** - Keep an eye on your reports on the go
|
72 |
|
73 |
== Changelog ==
|
|
|
|
|
|
|
|
|
|
|
|
|
74 |
= 4.7.1 =
|
75 |
* [Fix] The new feature introduced in version 4.6.9.1 to allow our users to customize the default time range for the reports, had introduced a regression bug. Thank you to all our users who volunteered to test the bugfix.
|
76 |
* [Fix] A vulnerability has been disclosed by [Pluginvulnerabilities.com](pluginvulnerabilities.com): an attacker with admin credentials could leverage the import/export mechanism for the plugin's settings to inject some malicious code. We recommend that you upgrade to the latest version of Slimstat as soon as possible.
|
5 |
Text Domain: wp-slimstat
|
6 |
Requires at least: 3.8
|
7 |
Tested up to: 4.8.2
|
8 |
+
Stable tag: 4.7.2
|
9 |
|
10 |
== Description ==
|
11 |
The leading web analytics plugin for WordPress. Track returning customers and registered users, monitor Javascript events, detect intrusions, analyze email campaigns. Thousands of WordPress sites are already using it.
|
71 |
5. **Responsive layout** - Keep an eye on your reports on the go
|
72 |
|
73 |
== Changelog ==
|
74 |
+
= 4.7.2 =
|
75 |
+
* [New] As those who have been using Slimstat for a while know, we never stop doing our good share of research and development to improve our plugin. One feature on our wishlist was to make the geolocation functionality more accurate. Specifically, users have been asking us to track not just the Country of origin, but possibly the state and city. In order to geolocate visitors, our code has been leveraging a third-party data file provided by [MaxMind.com](https://www.maxmind.com/en/home). A while ago, they launched a new data format, which improves performance and offers a way to quickly determine the city of origin. However, the new library required a higher version of PHP, and up until now we had been hesitant to adopt it, to allow more people to use our plugin, over the chance of offering this feature. Now, after spending some time combing through their code, we found a way to get the best of both worlds: by customizing their PHP library, we were able to make it work with PHP 5.3! Which means that now Slimstat is able to tell you your visitors' city of origin (and State, when applicable) right out of the box. This information is available in the Access Log report and in a new 'Top Cities' report under the Audience tab. Please note: the MaxMind data file to enable this feature is approximately 60 Mb, and for this reason <strong>this new functionality is not enabled by default</strong>. You must go to Slimstat > Settings > Tracker and turn on the corresponding option. Then go to Slimstat > Settings > Maintenance and uninstall/install the GeoLite file to download the one that contains the city data. Please feel free to contact us if you have any questions.
|
76 |
+
* [Update] Removed backward compatibility code for those updating from a version prior to 4.2. Hopefully most of our users are using a newer version that that. If you're not, please contact our support service for instructions on how to upgrade.
|
77 |
+
* [Update] The format used to save your settings in the database has been changed. You MUST update your premium add-ons as soon as possible, and get the version compatible with this new format, or you might notice unexpected behaviors. Please contact us if you experience difficulties updating your add-ons.
|
78 |
+
* [Update] Cleaned up some old CSS code affecting the reports.
|
79 |
+
|
80 |
= 4.7.1 =
|
81 |
* [Fix] The new feature introduced in version 4.6.9.1 to allow our users to customize the default time range for the reports, had introduced a regression bug. Thank you to all our users who volunteered to test the bugfix.
|
82 |
* [Fix] A vulnerability has been disclosed by [Pluginvulnerabilities.com](pluginvulnerabilities.com): an attacker with admin credentials could leverage the import/export mechanism for the plugin's settings to inject some malicious code. We recommend that you upgrade to the latest version of Slimstat as soon as possible.
|
wp-slimstat.php
CHANGED
@@ -3,7 +3,7 @@
|
|
3 |
Plugin Name: Slimstat Analytics
|
4 |
Plugin URI: http://wordpress.org/plugins/wp-slimstat/
|
5 |
Description: The leading web analytics plugin for WordPress
|
6 |
-
Version: 4.7.
|
7 |
Author: Jason Crouse
|
8 |
Author URI: http://www.wp-slimstat.com/
|
9 |
Text Domain: wp-slimstat
|
@@ -15,7 +15,7 @@ if ( !empty( wp_slimstat::$settings ) ) {
|
|
15 |
}
|
16 |
|
17 |
class wp_slimstat {
|
18 |
-
public static $version = '4.7.
|
19 |
public static $settings = array();
|
20 |
|
21 |
public static $wpdb = '';
|
@@ -72,7 +72,7 @@ class wp_slimstat {
|
|
72 |
self::$upload_dir .= '/wp-slimstat';
|
73 |
self::$upload_dir = apply_filters( 'slimstat_maxmind_path', self::$upload_dir );
|
74 |
|
75 |
-
self::$maxmind_path = self::$upload_dir . '/maxmind.
|
76 |
|
77 |
// Path to wp-content folder, used to detect caching plugins via advanced-cache.php
|
78 |
if ( file_exists( dirname( dirname( plugin_dir_path( __FILE__ ) ) ) . '/advanced-cache.php' ) ) {
|
@@ -80,25 +80,25 @@ class wp_slimstat {
|
|
80 |
}
|
81 |
|
82 |
// Enable the tracker (both server- and client-side)
|
83 |
-
if ( !is_admin() || self::$settings[ 'track_admin_pages' ] == '
|
84 |
|
85 |
// Allow add-ons to turn off the tracker based on other conditions
|
86 |
$is_tracking_filter = apply_filters( 'slimstat_filter_pre_tracking', strpos( self::get_request_uri(), 'wp-admin/admin-ajax.php' ) === false );
|
87 |
$is_tracking_filter_js = apply_filters( 'slimstat_filter_pre_tracking_js', true );
|
88 |
|
89 |
// Is server-side tracking active?
|
90 |
-
if ( self::$settings[ 'javascript_mode' ] != '
|
91 |
add_action( is_admin() ? 'admin_init' : 'wp', array( __CLASS__, 'slimtrack' ), 5 );
|
92 |
|
93 |
-
if ( self::$settings[ 'track_users' ] == '
|
94 |
add_action( 'login_init', array( __CLASS__, 'slimtrack' ), 10 );
|
95 |
}
|
96 |
}
|
97 |
|
98 |
// Slimstat tracks screen resolutions, outbound links and other client-side information using javascript
|
99 |
-
if ((self::$settings['enable_javascript'] == '
|
100 |
add_action( is_admin() ? 'admin_enqueue_scripts' : 'wp_enqueue_scripts' , array(__CLASS__, 'wp_slimstat_enqueue_tracking_script'), 15);
|
101 |
-
if ( self::$settings[ 'track_users' ] == '
|
102 |
add_action( 'login_enqueue_scripts', array( __CLASS__, 'wp_slimstat_enqueue_tracking_script' ), 10 );
|
103 |
}
|
104 |
}
|
@@ -133,7 +133,7 @@ class wp_slimstat {
|
|
133 |
*/
|
134 |
public static function slimtrack_ajax() {
|
135 |
// If the website is using a caching plugin, the tracking code might still be there, even if the user turned off tracking
|
136 |
-
if ( self::$settings[ 'is_tracking' ] != '
|
137 |
self::$stat[ 'id' ] = -204;
|
138 |
self::_set_error_array( __( 'Tracker is turned off, but client-side tracking code is still running.', 'wp-slimstat' ), true );
|
139 |
self::slimstat_save_options();
|
@@ -252,7 +252,7 @@ class wp_slimstat {
|
|
252 |
*/
|
253 |
public static function slimtrack( $_argument = '' ) {
|
254 |
// If the website is using a caching plugin, the tracking code might still be there, even if the user turned off tracking
|
255 |
-
if ( self::$settings['is_tracking'] != '
|
256 |
self::$stat[ 'id' ] = -204;
|
257 |
self::_set_error_array( __( 'Tracker is turned off, but client-side tracking code is still running.', 'wp-slimstat' ), true );
|
258 |
return $_argument;
|
@@ -308,7 +308,7 @@ class wp_slimstat {
|
|
308 |
|
309 |
if ( !empty( self::$stat[ 'referer' ] ) ) {
|
310 |
$parsed_site_url_host = parse_url( get_site_url(), PHP_URL_HOST );
|
311 |
-
if ( !empty( $referer[ 'host' ] ) && $referer[ 'host' ] == $parsed_site_url_host && self::$settings[ 'track_same_domain_referers' ] != '
|
312 |
unset( self::$stat[ 'referer' ] );
|
313 |
}
|
314 |
else {
|
@@ -466,7 +466,7 @@ class wp_slimstat {
|
|
466 |
LIMIT 0,1", self::$stat[ 'ip' ] ), ARRAY_A );
|
467 |
|
468 |
if ( !empty( $spam_comment[ 'comment_count' ] ) ) {
|
469 |
-
if ( self::$settings[ 'ignore_spammers' ] == '
|
470 |
self::$stat[ 'id' ] = -306;
|
471 |
self::_set_error_array( sprintf( __( 'Spammer %s not tracked', 'wp-slimstat' ), $spam_comment[ 'comment_author' ] ), true );
|
472 |
return $_argument;
|
@@ -502,12 +502,33 @@ class wp_slimstat {
|
|
502 |
}
|
503 |
}
|
504 |
|
505 |
-
//
|
506 |
self::$stat[ 'language' ] = self::_get_language();
|
507 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
508 |
|
509 |
// Anonymize IP Address?
|
510 |
-
if ( self::$settings[ 'anonymize_ip' ] == '
|
511 |
// IPv4 or IPv6
|
512 |
$needle = '.';
|
513 |
$replace = '.0';
|
@@ -533,7 +554,7 @@ class wp_slimstat {
|
|
533 |
// Mark or ignore Firefox/Safari prefetching requests (X-Moz: Prefetch and X-purpose: Preview)
|
534 |
if ( ( isset( $_SERVER[ 'HTTP_X_MOZ' ] ) && ( strtolower( $_SERVER[ 'HTTP_X_MOZ' ] ) == 'prefetch' ) ) ||
|
535 |
( isset( $_SERVER[ 'HTTP_X_PURPOSE' ] ) && ( strtolower( $_SERVER[ 'HTTP_X_PURPOSE' ] ) == 'preview' ) ) ) {
|
536 |
-
if ( self::$settings[ 'ignore_prefetch' ] == '
|
537 |
self::$stat[ 'id' ] = -309;
|
538 |
self::_set_error_array( __( 'Prefetch requests are ignored', 'wp-slimstat' ), true );
|
539 |
return $_argument;
|
@@ -549,7 +570,7 @@ class wp_slimstat {
|
|
549 |
}
|
550 |
|
551 |
// Are we ignoring bots?
|
552 |
-
if ( ( self::$settings[ 'javascript_mode' ] == '
|
553 |
self::$stat[ 'id' ] = -310;
|
554 |
self::_set_error_array( __( 'Bot not tracked', 'wp-slimstat' ), true );
|
555 |
return $_argument;
|
@@ -641,7 +662,7 @@ class wp_slimstat {
|
|
641 |
COOKIEPATH
|
642 |
);
|
643 |
}
|
644 |
-
elseif ( !$cookie_has_been_set && self::$settings[ 'extend_session' ] == '
|
645 |
@setcookie(
|
646 |
'slimstat_tracking_code',
|
647 |
self::_get_id_with_checksum( self::$stat[ 'visit_id' ] ),
|
@@ -655,74 +676,6 @@ class wp_slimstat {
|
|
655 |
}
|
656 |
// end slimtrack
|
657 |
|
658 |
-
/**
|
659 |
-
* Searches for the country code associated to a given IP address
|
660 |
-
*/
|
661 |
-
public static function get_country( $_ip_address = '0.0.0.0' ){
|
662 |
-
$ipnum = ip2long( $_ip_address );
|
663 |
-
$country_output = 'xx';
|
664 |
-
|
665 |
-
// Is this a RFC1918 (local) IP?
|
666 |
-
if ( $ipnum == 2130706433 || // 127.0.0.1
|
667 |
-
( $ipnum >= 167772160 && $ipnum <= 184549375 ) || // 10.0.0.1 - 10.255.255.255
|
668 |
-
( $ipnum >= 2886729728 && $ipnum <= 2887778303 ) || // 172.16.0.1 - 172.31.255.255
|
669 |
-
( $ipnum >= 3232235521 && $ipnum <= 3232301055 ) ) { // 192.168.0.1 - 192.168.255.255
|
670 |
-
$country_output = 'xy';
|
671 |
-
}
|
672 |
-
else {
|
673 |
-
$country_codes = array("","ap","eu","ad","ae","af","ag","ai","al","am","cw","ao","aq","ar","as","at","au","aw","az","ba","bb","bd","be","bf","bg","bh","bi","bj","bm","bn","bo","br","bs","bt","bv","bw","by","bz","ca","cc","cd","cf","cg","ch","ci","ck","cl","cm","cn","co","cr","cu","cv","cx","cy","cz","de","dj","dk","dm","do","dz","ec","ee","eg","eh","er","es","et","fi","fj","fk","fm","fo","fr","sx","ga","gb","gd","ge","gf","gh","gi","gl","gm","gn","gp","gq","gr","gs","gt","gu","gw","gy","hk","hm","hn","hr","ht","hu","id","ie","il","in","io","iq","ir","is","it","jm","jo","jp","ke","kg","kh","ki","km","kn","kp","kr","kw","ky","kz","la","lb","lc","li","lk","lr","ls","lt","lu","lv","ly","ma","mc","md","mg","mh","mk","ml","mm","mn","mo","mp","mq","mr","ms","mt","mu","mv","mw","mx","my","mz","na","nc","ne","nf","ng","ni","nl","no","np","nr","nu","nz","om","pa","pe","pf","pg","ph","pk","pl","pm","pn","pr","ps","pt","pw","py","qa","re","ro","ru","rw","sa","sb","sc","sd","se","sg","sh","si","sj","sk","sl","sm","sn","so","sr","st","sv","sy","sz","tc","td","tf","tg","th","tj","tk","tm","tn","to","tl","tr","tt","tv","tw","tz","ua","ug","um","us","uy","uz","va","vc","ve","vg","vi","vn","vu","wf","ws","ye","yt","rs","za","zm","me","zw","a1","a2","o1","ax","gg","im","je","bl","mf","bq","ss","o1");
|
674 |
-
|
675 |
-
if ( file_exists( self::$maxmind_path ) && ( $handle = fopen( self::$maxmind_path, "rb" ) ) ) {
|
676 |
-
|
677 |
-
// Do we need to update the file?
|
678 |
-
if (false !== ($file_stat = stat(self::$maxmind_path))){
|
679 |
-
|
680 |
-
// Is the database more than 30 days old?
|
681 |
-
if ((date('U') - $file_stat['mtime'] > 2629740)){
|
682 |
-
fclose($handle);
|
683 |
-
|
684 |
-
add_action('shutdown', array(__CLASS__, 'download_maxmind_database'));
|
685 |
-
|
686 |
-
if (false === ($handle = fopen(self::$maxmind_path, "rb"))){
|
687 |
-
return apply_filters( 'slimstat_get_country', 'xx', $_ip_address );
|
688 |
-
}
|
689 |
-
}
|
690 |
-
}
|
691 |
-
|
692 |
-
$offset = 0;
|
693 |
-
for ( $depth = 31; $depth >= 0; --$depth ) {
|
694 |
-
if ( fseek($handle, 6 * $offset, SEEK_SET ) != 0 ) {
|
695 |
-
break;
|
696 |
-
}
|
697 |
-
$buf = fread( $handle, 6 );
|
698 |
-
$x = array(0,0);
|
699 |
-
for ($i = 0; $i < 2; ++$i) {
|
700 |
-
for ($j = 0; $j < 3; ++$j) {
|
701 |
-
$x[$i] += ord(substr($buf, 3 * $i + $j, 1)) << ($j * 8);
|
702 |
-
}
|
703 |
-
}
|
704 |
-
|
705 |
-
if ( $ipnum & ( 1 << $depth ) ) {
|
706 |
-
if ($x[1] >= 16776960 && !empty($country_codes[$x[1] - 16776960])) {
|
707 |
-
$country_output = $country_codes[$x[1] - 16776960];
|
708 |
-
break;
|
709 |
-
}
|
710 |
-
$offset = $x[1];
|
711 |
-
} else {
|
712 |
-
if ($x[0] >= 16776960 && !empty($country_codes[$x[0] - 16776960])) {
|
713 |
-
$country_output = $country_codes[$x[0] - 16776960];
|
714 |
-
break;
|
715 |
-
}
|
716 |
-
$offset = $x[0];
|
717 |
-
}
|
718 |
-
}
|
719 |
-
fclose($handle);
|
720 |
-
}
|
721 |
-
}
|
722 |
-
return apply_filters( 'slimstat_get_country', $country_output, $_ip_address );
|
723 |
-
}
|
724 |
-
// end get_country
|
725 |
-
|
726 |
/**
|
727 |
* Decodes the permalink
|
728 |
*/
|
@@ -1032,7 +985,7 @@ class wp_slimstat {
|
|
1032 |
}
|
1033 |
|
1034 |
// User doesn't have an active session
|
1035 |
-
if ( $is_new_session && ( $_force_assign || self::$settings[ 'javascript_mode' ] == '
|
1036 |
if ( empty( self::$settings[ 'session_duration' ] ) ) {
|
1037 |
self::$settings[ 'session_duration' ] = 1800;
|
1038 |
}
|
@@ -1066,7 +1019,7 @@ class wp_slimstat {
|
|
1066 |
WHERE id = %d AND visit_id = 0", self::$stat[ 'visit_id' ], $identifier
|
1067 |
) );
|
1068 |
}
|
1069 |
-
return ( $is_new_session && ( $_force_assign || self::$settings[ 'javascript_mode' ] == '
|
1070 |
}
|
1071 |
// end _set_visit_id
|
1072 |
|
@@ -1187,7 +1140,7 @@ class wp_slimstat {
|
|
1187 |
/**
|
1188 |
* Opens given domains during CORS requests to admin-ajax.php
|
1189 |
*/
|
1190 |
-
public static function open_cors_admin_ajax( $_allowed_origins = array() ){
|
1191 |
$exploded_domains = self::string_to_array( self::$settings[ 'external_domains' ] );
|
1192 |
|
1193 |
if ( !empty( $exploded_domains ) && !empty( $exploded_domains[ 0 ] ) ) {
|
@@ -1200,7 +1153,7 @@ class wp_slimstat {
|
|
1200 |
/**
|
1201 |
* Downloads the MaxMind geolocation database from their repository
|
1202 |
*/
|
1203 |
-
public static function download_maxmind_database(){
|
1204 |
// Create the folder, if it doesn't exist
|
1205 |
if ( !file_exists( dirname( self::$maxmind_path ) ) ) {
|
1206 |
mkdir( dirname( self::$maxmind_path ) );
|
@@ -1208,12 +1161,18 @@ class wp_slimstat {
|
|
1208 |
|
1209 |
// Download the most recent database directly from MaxMind's repository
|
1210 |
if ( !function_exists( 'download_url' ) ) {
|
1211 |
-
require_once(ABSPATH . 'wp-admin/includes/file.php');
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1212 |
}
|
1213 |
-
$maxmind_tmp = download_url( 'http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz', 5 );
|
1214 |
|
1215 |
-
if (is_wp_error($maxmind_tmp)){
|
1216 |
-
return __('There was an error downloading the MaxMind Geolite DB:', 'wp-slimstat').' '
|
1217 |
}
|
1218 |
|
1219 |
$zh = false;
|
@@ -1235,22 +1194,22 @@ class wp_slimstat {
|
|
1235 |
}
|
1236 |
|
1237 |
if ( false === ( $fh = fopen( self::$maxmind_path, 'wb' ) ) ) {
|
1238 |
-
return __('There was an error opening the
|
1239 |
}
|
1240 |
|
1241 |
-
while(($data = gzread($zh, 4096)) != false){
|
1242 |
-
fwrite($fh, $data);
|
1243 |
}
|
1244 |
|
1245 |
-
@gzclose($zh);
|
1246 |
-
@fclose($fh);
|
1247 |
|
1248 |
-
@unlink($maxmind_tmp);
|
1249 |
|
1250 |
return '';
|
1251 |
}
|
1252 |
|
1253 |
-
public static function slimstat_shortcode( $_attributes = '', $_content = '' ){
|
1254 |
extract( shortcode_atts( array(
|
1255 |
'f' => '', // recent, popular, count, widget
|
1256 |
'w' => '', // column to use (for recent, popular and count) or widget to use
|
@@ -1550,48 +1509,49 @@ class wp_slimstat {
|
|
1550 |
'browscap_last_modified' => 0,
|
1551 |
|
1552 |
// General
|
1553 |
-
'is_tracking' => '
|
1554 |
-
'javascript_mode' => '
|
1555 |
-
'enable_javascript' => '
|
1556 |
'track_admin_pages' => 'no',
|
1557 |
-
'use_separate_menu' => '
|
1558 |
'add_posts_column' => 'no',
|
1559 |
'posts_column_day_interval' => 30,
|
1560 |
-
'posts_column_pageviews' => '
|
1561 |
-
'add_dashboard_widgets' => '
|
1562 |
'hide_addons' => 'no',
|
1563 |
'auto_purge' => 0,
|
1564 |
-
'auto_purge_delete' => '
|
1565 |
|
1566 |
// Tracker
|
1567 |
'do_not_track_outbound_classes_rel_href' => 'noslimstat,ab-item',
|
1568 |
'extensions_to_track' => 'pdf,doc,xls,zip',
|
1569 |
-
'track_same_domain_referers' => '
|
1570 |
'session_duration' => 1800,
|
1571 |
'extend_session' => 'no',
|
1572 |
-
'
|
|
|
1573 |
'external_domains' => '',
|
1574 |
|
1575 |
// Filters
|
1576 |
-
'track_users' => '
|
1577 |
'ignore_users' => '',
|
1578 |
'ignore_ip' => '',
|
1579 |
'ignore_capabilities' => '',
|
1580 |
-
'ignore_spammers' => '
|
1581 |
'ignore_bots' => 'no',
|
1582 |
'ignore_resources' => '',
|
1583 |
'ignore_countries' => '',
|
1584 |
'ignore_browsers' => '',
|
1585 |
'ignore_referers' => '',
|
1586 |
'anonymize_ip' => 'no',
|
1587 |
-
'ignore_prefetch' => '
|
1588 |
|
1589 |
// Reports
|
1590 |
-
'use_european_separators' => '
|
1591 |
'date_format' => 'm-d-y',
|
1592 |
'time_format' => 'h:i a',
|
1593 |
'show_display_name' => 'no',
|
1594 |
-
'convert_resource_urls_to_titles' => '
|
1595 |
'convert_ip_addresses' => 'no',
|
1596 |
'async_load' => 'no',
|
1597 |
'use_current_month_timespan' => 'no',
|
@@ -1609,7 +1569,7 @@ class wp_slimstat {
|
|
1609 |
'enable_sov' => 'no',
|
1610 |
|
1611 |
// Access Control
|
1612 |
-
'restrict_authors_view' => '
|
1613 |
'capability_can_view' => 'activate_plugins',
|
1614 |
'can_view' => '',
|
1615 |
'rest_api_tokens' => wp_hash( uniqid( time() - 3600, true ) ),
|
@@ -1665,7 +1625,7 @@ class wp_slimstat {
|
|
1665 |
$params[ 'outbound_classes_rel_href_to_not_track' ] = str_replace( ' ', '', self::$settings[ 'do_not_track_outbound_classes_rel_href' ] );
|
1666 |
}
|
1667 |
|
1668 |
-
if ( self::$settings[ 'javascript_mode' ] != '
|
1669 |
// Do not enqueue the tracker if this page view was not tracked for some reason
|
1670 |
if ( intval( self::$stat[ 'id' ] ) < 0 ) {
|
1671 |
return false;
|
@@ -1691,12 +1651,12 @@ class wp_slimstat {
|
|
1691 |
|
1692 |
$params = apply_filters( 'slimstat_js_params', $params );
|
1693 |
|
1694 |
-
if ( self::$settings[ 'enable_cdn' ] == '
|
1695 |
$schema = is_ssl() ? 'https' : 'http';
|
1696 |
wp_register_script( 'wp_slimstat', $schema . '://cdn.jsdelivr.net/wp/wp-slimstat/tags/' . self::$version . '/wp-slimstat.min.js', array(), null, true );
|
1697 |
}
|
1698 |
else{
|
1699 |
-
wp_register_script('wp_slimstat', plugins_url('/wp-slimstat.min.js', __FILE__), array(), null, true);
|
1700 |
}
|
1701 |
|
1702 |
wp_enqueue_script( 'wp_slimstat' );
|
3 |
Plugin Name: Slimstat Analytics
|
4 |
Plugin URI: http://wordpress.org/plugins/wp-slimstat/
|
5 |
Description: The leading web analytics plugin for WordPress
|
6 |
+
Version: 4.7.2
|
7 |
Author: Jason Crouse
|
8 |
Author URI: http://www.wp-slimstat.com/
|
9 |
Text Domain: wp-slimstat
|
15 |
}
|
16 |
|
17 |
class wp_slimstat {
|
18 |
+
public static $version = '4.7.2';
|
19 |
public static $settings = array();
|
20 |
|
21 |
public static $wpdb = '';
|
72 |
self::$upload_dir .= '/wp-slimstat';
|
73 |
self::$upload_dir = apply_filters( 'slimstat_maxmind_path', self::$upload_dir );
|
74 |
|
75 |
+
self::$maxmind_path = self::$upload_dir . '/maxmind.mmdb';
|
76 |
|
77 |
// Path to wp-content folder, used to detect caching plugins via advanced-cache.php
|
78 |
if ( file_exists( dirname( dirname( plugin_dir_path( __FILE__ ) ) ) . '/advanced-cache.php' ) ) {
|
80 |
}
|
81 |
|
82 |
// Enable the tracker (both server- and client-side)
|
83 |
+
if ( !is_admin() || self::$settings[ 'track_admin_pages' ] == 'on' ) {
|
84 |
|
85 |
// Allow add-ons to turn off the tracker based on other conditions
|
86 |
$is_tracking_filter = apply_filters( 'slimstat_filter_pre_tracking', strpos( self::get_request_uri(), 'wp-admin/admin-ajax.php' ) === false );
|
87 |
$is_tracking_filter_js = apply_filters( 'slimstat_filter_pre_tracking_js', true );
|
88 |
|
89 |
// Is server-side tracking active?
|
90 |
+
if ( self::$settings[ 'javascript_mode' ] != 'on' && self::$settings[ 'is_tracking' ] == 'on' && $is_tracking_filter ) {
|
91 |
add_action( is_admin() ? 'admin_init' : 'wp', array( __CLASS__, 'slimtrack' ), 5 );
|
92 |
|
93 |
+
if ( self::$settings[ 'track_users' ] == 'on' ) {
|
94 |
add_action( 'login_init', array( __CLASS__, 'slimtrack' ), 10 );
|
95 |
}
|
96 |
}
|
97 |
|
98 |
// Slimstat tracks screen resolutions, outbound links and other client-side information using javascript
|
99 |
+
if ( ( self::$settings[ 'enable_javascript' ] == 'on' || self::$settings[ 'javascript_mode' ] == 'on' ) && self::$settings[ 'is_tracking' ] == 'on' && $is_tracking_filter_js ) {
|
100 |
add_action( is_admin() ? 'admin_enqueue_scripts' : 'wp_enqueue_scripts' , array(__CLASS__, 'wp_slimstat_enqueue_tracking_script'), 15);
|
101 |
+
if ( self::$settings[ 'track_users' ] == 'on' ) {
|
102 |
add_action( 'login_enqueue_scripts', array( __CLASS__, 'wp_slimstat_enqueue_tracking_script' ), 10 );
|
103 |
}
|
104 |
}
|
133 |
*/
|
134 |
public static function slimtrack_ajax() {
|
135 |
// If the website is using a caching plugin, the tracking code might still be there, even if the user turned off tracking
|
136 |
+
if ( self::$settings[ 'is_tracking' ] != 'on' ) {
|
137 |
self::$stat[ 'id' ] = -204;
|
138 |
self::_set_error_array( __( 'Tracker is turned off, but client-side tracking code is still running.', 'wp-slimstat' ), true );
|
139 |
self::slimstat_save_options();
|
252 |
*/
|
253 |
public static function slimtrack( $_argument = '' ) {
|
254 |
// If the website is using a caching plugin, the tracking code might still be there, even if the user turned off tracking
|
255 |
+
if ( self::$settings[ 'is_tracking' ] != 'on' ) {
|
256 |
self::$stat[ 'id' ] = -204;
|
257 |
self::_set_error_array( __( 'Tracker is turned off, but client-side tracking code is still running.', 'wp-slimstat' ), true );
|
258 |
return $_argument;
|
308 |
|
309 |
if ( !empty( self::$stat[ 'referer' ] ) ) {
|
310 |
$parsed_site_url_host = parse_url( get_site_url(), PHP_URL_HOST );
|
311 |
+
if ( !empty( $referer[ 'host' ] ) && $referer[ 'host' ] == $parsed_site_url_host && self::$settings[ 'track_same_domain_referers' ] != 'on' ) {
|
312 |
unset( self::$stat[ 'referer' ] );
|
313 |
}
|
314 |
else {
|
466 |
LIMIT 0,1", self::$stat[ 'ip' ] ), ARRAY_A );
|
467 |
|
468 |
if ( !empty( $spam_comment[ 'comment_count' ] ) ) {
|
469 |
+
if ( self::$settings[ 'ignore_spammers' ] == 'on' ){
|
470 |
self::$stat[ 'id' ] = -306;
|
471 |
self::_set_error_array( sprintf( __( 'Spammer %s not tracked', 'wp-slimstat' ), $spam_comment[ 'comment_author' ] ), true );
|
472 |
return $_argument;
|
502 |
}
|
503 |
}
|
504 |
|
505 |
+
// Language
|
506 |
self::$stat[ 'language' ] = self::_get_language();
|
507 |
+
|
508 |
+
// Geolocation
|
509 |
+
include_once ( plugin_dir_path( __FILE__ ) . 'maxmind.php' );
|
510 |
+
$geolocation_data = maxmind_geolite2_connector::get_geolocation_info( self::$stat[ 'ip' ] );
|
511 |
+
|
512 |
+
if ( !empty( $geolocation_data[ 'country' ][ 'iso_code' ] ) ) {
|
513 |
+
self::$stat[ 'country' ] = strtolower( $geolocation_data[ 'country' ][ 'iso_code' ] );
|
514 |
+
}
|
515 |
+
|
516 |
+
if ( !empty( $geolocation_data[ 'city' ][ 'names' ][ 'en' ] ) ) {
|
517 |
+
self::$stat[ 'city' ] = $geolocation_data[ 'city' ][ 'names' ][ 'en' ];
|
518 |
+
}
|
519 |
+
|
520 |
+
if ( !empty( $geolocation_data[ 'subdivisions' ][ 0 ][ 'iso_code' ] ) && !empty( self::$stat[ 'city' ] ) ) {
|
521 |
+
self::$stat[ 'city' ] .= ' (' . $geolocation_data[ 'subdivisions' ][ 0 ][ 'iso_code' ] . ')';
|
522 |
+
}
|
523 |
+
|
524 |
+
if ( !empty( $geolocation_data[ 'location' ][ 'latitude' ] ) && !empty( $geolocation_data[ 'location' ][ 'longitude' ] ) ) {
|
525 |
+
self::$stat[ 'location' ] = $geolocation_data[ 'location' ][ 'latitude' ] . ',' . $geolocation_data[ 'location' ][ 'longitude' ];
|
526 |
+
}
|
527 |
+
|
528 |
+
unset( $geolocation_data );
|
529 |
|
530 |
// Anonymize IP Address?
|
531 |
+
if ( self::$settings[ 'anonymize_ip' ] == 'on' ) {
|
532 |
// IPv4 or IPv6
|
533 |
$needle = '.';
|
534 |
$replace = '.0';
|
554 |
// Mark or ignore Firefox/Safari prefetching requests (X-Moz: Prefetch and X-purpose: Preview)
|
555 |
if ( ( isset( $_SERVER[ 'HTTP_X_MOZ' ] ) && ( strtolower( $_SERVER[ 'HTTP_X_MOZ' ] ) == 'prefetch' ) ) ||
|
556 |
( isset( $_SERVER[ 'HTTP_X_PURPOSE' ] ) && ( strtolower( $_SERVER[ 'HTTP_X_PURPOSE' ] ) == 'preview' ) ) ) {
|
557 |
+
if ( self::$settings[ 'ignore_prefetch' ] == 'on' ) {
|
558 |
self::$stat[ 'id' ] = -309;
|
559 |
self::_set_error_array( __( 'Prefetch requests are ignored', 'wp-slimstat' ), true );
|
560 |
return $_argument;
|
570 |
}
|
571 |
|
572 |
// Are we ignoring bots?
|
573 |
+
if ( ( self::$settings[ 'javascript_mode' ] == 'on' || self::$settings[ 'ignore_bots' ] == 'on' ) && self::$browser[ 'browser_type' ] == 1 ) {
|
574 |
self::$stat[ 'id' ] = -310;
|
575 |
self::_set_error_array( __( 'Bot not tracked', 'wp-slimstat' ), true );
|
576 |
return $_argument;
|
662 |
COOKIEPATH
|
663 |
);
|
664 |
}
|
665 |
+
elseif ( !$cookie_has_been_set && self::$settings[ 'extend_session' ] == 'on' && self::$stat[ 'visit_id' ] > 0 ) {
|
666 |
@setcookie(
|
667 |
'slimstat_tracking_code',
|
668 |
self::_get_id_with_checksum( self::$stat[ 'visit_id' ] ),
|
676 |
}
|
677 |
// end slimtrack
|
678 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
679 |
/**
|
680 |
* Decodes the permalink
|
681 |
*/
|
985 |
}
|
986 |
|
987 |
// User doesn't have an active session
|
988 |
+
if ( $is_new_session && ( $_force_assign || self::$settings[ 'javascript_mode' ] == 'on' ) ) {
|
989 |
if ( empty( self::$settings[ 'session_duration' ] ) ) {
|
990 |
self::$settings[ 'session_duration' ] = 1800;
|
991 |
}
|
1019 |
WHERE id = %d AND visit_id = 0", self::$stat[ 'visit_id' ], $identifier
|
1020 |
) );
|
1021 |
}
|
1022 |
+
return ( $is_new_session && ( $_force_assign || self::$settings[ 'javascript_mode' ] == 'on' ) );
|
1023 |
}
|
1024 |
// end _set_visit_id
|
1025 |
|
1140 |
/**
|
1141 |
* Opens given domains during CORS requests to admin-ajax.php
|
1142 |
*/
|
1143 |
+
public static function open_cors_admin_ajax( $_allowed_origins = array() ) {
|
1144 |
$exploded_domains = self::string_to_array( self::$settings[ 'external_domains' ] );
|
1145 |
|
1146 |
if ( !empty( $exploded_domains ) && !empty( $exploded_domains[ 0 ] ) ) {
|
1153 |
/**
|
1154 |
* Downloads the MaxMind geolocation database from their repository
|
1155 |
*/
|
1156 |
+
public static function download_maxmind_database() {
|
1157 |
// Create the folder, if it doesn't exist
|
1158 |
if ( !file_exists( dirname( self::$maxmind_path ) ) ) {
|
1159 |
mkdir( dirname( self::$maxmind_path ) );
|
1161 |
|
1162 |
// Download the most recent database directly from MaxMind's repository
|
1163 |
if ( !function_exists( 'download_url' ) ) {
|
1164 |
+
require_once( ABSPATH . 'wp-admin/includes/file.php' );
|
1165 |
+
}
|
1166 |
+
|
1167 |
+
if ( self::$settings[ 'geolocation_country' ] == 'on' ) {
|
1168 |
+
$maxmind_tmp = download_url( 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz', 5 );
|
1169 |
+
}
|
1170 |
+
else {
|
1171 |
+
$maxmind_tmp = download_url( 'http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz', 25 );
|
1172 |
}
|
|
|
1173 |
|
1174 |
+
if ( is_wp_error( $maxmind_tmp ) ) {
|
1175 |
+
return __( 'There was an error downloading the MaxMind Geolite DB:', 'wp-slimstat' ) . ' ' . $maxmind_tmp->get_error_message();
|
1176 |
}
|
1177 |
|
1178 |
$zh = false;
|
1194 |
}
|
1195 |
|
1196 |
if ( false === ( $fh = fopen( self::$maxmind_path, 'wb' ) ) ) {
|
1197 |
+
return __( 'There was an error opening the MaxMind Geolite DB.', 'wp-slimstat' );
|
1198 |
}
|
1199 |
|
1200 |
+
while ( ( $data = gzread( $zh, 4096 ) ) != false ) {
|
1201 |
+
fwrite( $fh, $data );
|
1202 |
}
|
1203 |
|
1204 |
+
@gzclose( $zh );
|
1205 |
+
@fclose( $fh );
|
1206 |
|
1207 |
+
@unlink( $maxmind_tmp );
|
1208 |
|
1209 |
return '';
|
1210 |
}
|
1211 |
|
1212 |
+
public static function slimstat_shortcode( $_attributes = '', $_content = '' ) {
|
1213 |
extract( shortcode_atts( array(
|
1214 |
'f' => '', // recent, popular, count, widget
|
1215 |
'w' => '', // column to use (for recent, popular and count) or widget to use
|
1509 |
'browscap_last_modified' => 0,
|
1510 |
|
1511 |
// General
|
1512 |
+
'is_tracking' => 'on',
|
1513 |
+
'javascript_mode' => 'on',
|
1514 |
+
'enable_javascript' => 'on',
|
1515 |
'track_admin_pages' => 'no',
|
1516 |
+
'use_separate_menu' => 'on',
|
1517 |
'add_posts_column' => 'no',
|
1518 |
'posts_column_day_interval' => 30,
|
1519 |
+
'posts_column_pageviews' => 'on',
|
1520 |
+
'add_dashboard_widgets' => 'on',
|
1521 |
'hide_addons' => 'no',
|
1522 |
'auto_purge' => 0,
|
1523 |
+
'auto_purge_delete' => 'on',
|
1524 |
|
1525 |
// Tracker
|
1526 |
'do_not_track_outbound_classes_rel_href' => 'noslimstat,ab-item',
|
1527 |
'extensions_to_track' => 'pdf,doc,xls,zip',
|
1528 |
+
'track_same_domain_referers' => 'on',
|
1529 |
'session_duration' => 1800,
|
1530 |
'extend_session' => 'no',
|
1531 |
+
'geolocation_country' => 'on',
|
1532 |
+
'enable_cdn' => 'on',
|
1533 |
'external_domains' => '',
|
1534 |
|
1535 |
// Filters
|
1536 |
+
'track_users' => 'on',
|
1537 |
'ignore_users' => '',
|
1538 |
'ignore_ip' => '',
|
1539 |
'ignore_capabilities' => '',
|
1540 |
+
'ignore_spammers' => 'on',
|
1541 |
'ignore_bots' => 'no',
|
1542 |
'ignore_resources' => '',
|
1543 |
'ignore_countries' => '',
|
1544 |
'ignore_browsers' => '',
|
1545 |
'ignore_referers' => '',
|
1546 |
'anonymize_ip' => 'no',
|
1547 |
+
'ignore_prefetch' => 'on',
|
1548 |
|
1549 |
// Reports
|
1550 |
+
'use_european_separators' => 'on',
|
1551 |
'date_format' => 'm-d-y',
|
1552 |
'time_format' => 'h:i a',
|
1553 |
'show_display_name' => 'no',
|
1554 |
+
'convert_resource_urls_to_titles' => 'on',
|
1555 |
'convert_ip_addresses' => 'no',
|
1556 |
'async_load' => 'no',
|
1557 |
'use_current_month_timespan' => 'no',
|
1569 |
'enable_sov' => 'no',
|
1570 |
|
1571 |
// Access Control
|
1572 |
+
'restrict_authors_view' => 'on',
|
1573 |
'capability_can_view' => 'activate_plugins',
|
1574 |
'can_view' => '',
|
1575 |
'rest_api_tokens' => wp_hash( uniqid( time() - 3600, true ) ),
|
1625 |
$params[ 'outbound_classes_rel_href_to_not_track' ] = str_replace( ' ', '', self::$settings[ 'do_not_track_outbound_classes_rel_href' ] );
|
1626 |
}
|
1627 |
|
1628 |
+
if ( self::$settings[ 'javascript_mode' ] != 'on' ) {
|
1629 |
// Do not enqueue the tracker if this page view was not tracked for some reason
|
1630 |
if ( intval( self::$stat[ 'id' ] ) < 0 ) {
|
1631 |
return false;
|
1651 |
|
1652 |
$params = apply_filters( 'slimstat_js_params', $params );
|
1653 |
|
1654 |
+
if ( self::$settings[ 'enable_cdn' ] == 'on' ) {
|
1655 |
$schema = is_ssl() ? 'https' : 'http';
|
1656 |
wp_register_script( 'wp_slimstat', $schema . '://cdn.jsdelivr.net/wp/wp-slimstat/tags/' . self::$version . '/wp-slimstat.min.js', array(), null, true );
|
1657 |
}
|
1658 |
else{
|
1659 |
+
wp_register_script( 'wp_slimstat', plugins_url( '/wp-slimstat.min.js', __FILE__ ), array(), null, true );
|
1660 |
}
|
1661 |
|
1662 |
wp_enqueue_script( 'wp_slimstat' );
|